comparison src/org/eclipse/jetty/util/log/StdErrLog.java @ 802:3428c60d7cfc

replace jetty jars with source
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 07 Sep 2016 21:15:48 -0600
parents
children
comparison
equal deleted inserted replaced
801:6a21393191c1 802:3428c60d7cfc
1 //
2 // ========================================================================
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.util.log;
20
21 import java.io.PrintStream;
22 import java.security.AccessControlException;
23 import java.util.Properties;
24
25 import org.eclipse.jetty.util.DateCache;
26
27 /**
28 * StdErr Logging. This implementation of the Logging facade sends all logs to StdErr with minimal formatting.
29 * <p>
30 * If the system property "org.eclipse.jetty.LEVEL" is set to one of the following (ALL, DEBUG, INFO, WARN), then set
31 * the eclipse jetty root level logger level to that specified level. (Default level is INFO)
32 * <p>
33 * If the system property "org.eclipse.jetty.util.log.SOURCE" is set, then the source method/file of a log is logged.
34 * For named debuggers, the system property name+".SOURCE" is checked, eg "org.eclipse.jetty.util.log.stderr.SOURCE".
35 * If it is not not set, then "org.eclipse.jetty.util.log.SOURCE" is used as the default.
36 * <p>
37 * If the system property "org.eclipse.jetty.util.log.stderr.LONG" is set, then the full, unabbreviated name of the logger is
38 * used for logging.
39 */
40 public class StdErrLog extends AbstractLogger
41 {
42 private static final String EOL = System.getProperty("line.separator");
43 private static DateCache _dateCache;
44 private static final Properties __props = new Properties();
45
46 private final static boolean __source = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE",
47 Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE","false")));
48 private final static boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG","false"));
49
50 static
51 {
52 __props.putAll(Log.__props);
53
54 String deprecatedProperties[] =
55 { "DEBUG", "org.eclipse.jetty.util.log.DEBUG", "org.eclipse.jetty.util.log.stderr.DEBUG" };
56
57 // Toss a message to users about deprecated system properties
58 for (String deprecatedProp : deprecatedProperties)
59 {
60 if (System.getProperty(deprecatedProp) != null)
61 {
62 System.err.printf("System Property [%s] has been deprecated! (Use org.eclipse.jetty.LEVEL=DEBUG instead)%n",deprecatedProp);
63 }
64 }
65
66 try
67 {
68 _dateCache = new DateCache("yyyy-MM-dd HH:mm:ss");
69 }
70 catch (Exception x)
71 {
72 x.printStackTrace(System.err);
73 }
74 }
75
76 public static final int LEVEL_ALL = 0;
77 public static final int LEVEL_DEBUG = 1;
78 public static final int LEVEL_INFO = 2;
79 public static final int LEVEL_WARN = 3;
80
81 private int _level = LEVEL_INFO;
82 // Level that this Logger was configured as (remembered in special case of .setDebugEnabled())
83 private int _configuredLevel;
84 private PrintStream _stderr = null;
85 private boolean _source = __source;
86 // Print the long form names, otherwise use abbreviated
87 private boolean _printLongNames = __long;
88 // The full log name, as provided by the system.
89 private final String _name;
90 // The abbreviated log name (used by default, unless _long is specified)
91 private final String _abbrevname;
92 private boolean _hideStacks = false;
93
94 public StdErrLog()
95 {
96 this(null);
97 }
98
99 public StdErrLog(String name)
100 {
101 this(name,__props);
102 }
103
104 public StdErrLog(String name, Properties props)
105 {
106 if (props!=null && props!=__props)
107 __props.putAll(props);
108 this._name = name == null?"":name;
109 this._abbrevname = condensePackageString(this._name);
110 this._level = getLoggingLevel(props,this._name);
111 this._configuredLevel = this._level;
112
113 try
114 {
115 _source = Boolean.parseBoolean(props.getProperty(_name + ".SOURCE",Boolean.toString(_source)));
116 }
117 catch (AccessControlException ace)
118 {
119 _source = __source;
120 }
121 }
122
123 /**
124 * Get the Logging Level for the provided log name. Using the FQCN first, then each package segment from longest to
125 * shortest.
126 *
127 * @param props
128 * the properties to check
129 * @param name
130 * the name to get log for
131 * @return the logging level
132 */
133 public static int getLoggingLevel(Properties props, final String name)
134 {
135 // Calculate the level this named logger should operate under.
136 // Checking with FQCN first, then each package segment from longest to shortest.
137 String nameSegment = name;
138
139 while ((nameSegment != null) && (nameSegment.length() > 0))
140 {
141 String levelStr = props.getProperty(nameSegment + ".LEVEL");
142 // System.err.printf("[StdErrLog.CONFIG] Checking for property [%s.LEVEL] = %s%n",nameSegment,levelStr);
143 int level = getLevelId(nameSegment + ".LEVEL",levelStr);
144 if (level != (-1))
145 {
146 return level;
147 }
148
149 // Trim and try again.
150 int idx = nameSegment.lastIndexOf('.');
151 if (idx >= 0)
152 {
153 nameSegment = nameSegment.substring(0,idx);
154 }
155 else
156 {
157 nameSegment = null;
158 }
159 }
160
161 // Default Logging Level
162 return getLevelId("log.LEVEL",props.getProperty("log.LEVEL","INFO"));
163 }
164
165 protected static int getLevelId(String levelSegment, String levelName)
166 {
167 if (levelName == null)
168 {
169 return -1;
170 }
171 String levelStr = levelName.trim();
172 if ("ALL".equalsIgnoreCase(levelStr))
173 {
174 return LEVEL_ALL;
175 }
176 else if ("DEBUG".equalsIgnoreCase(levelStr))
177 {
178 return LEVEL_DEBUG;
179 }
180 else if ("INFO".equalsIgnoreCase(levelStr))
181 {
182 return LEVEL_INFO;
183 }
184 else if ("WARN".equalsIgnoreCase(levelStr))
185 {
186 return LEVEL_WARN;
187 }
188
189 System.err.println("Unknown StdErrLog level [" + levelSegment + "]=[" + levelStr + "], expecting only [ALL, DEBUG, INFO, WARN] as values.");
190 return -1;
191 }
192
193 /**
194 * Condenses a classname by stripping down the package name to just the first character of each package name
195 * segment.Configured
196 * <p>
197 *
198 * <pre>
199 * Examples:
200 * "org.eclipse.jetty.test.FooTest" = "oejt.FooTest"
201 * "org.eclipse.jetty.server.logging.LogTest" = "orjsl.LogTest"
202 * </pre>
203 *
204 * @param classname
205 * the fully qualified class name
206 * @return the condensed name
207 */
208 protected static String condensePackageString(String classname)
209 {
210 String parts[] = classname.split("\\.");
211 StringBuilder dense = new StringBuilder();
212 for (int i = 0; i < (parts.length - 1); i++)
213 {
214 dense.append(parts[i].charAt(0));
215 }
216 if (dense.length() > 0)
217 {
218 dense.append('.');
219 }
220 dense.append(parts[parts.length - 1]);
221 return dense.toString();
222 }
223
224 public String getName()
225 {
226 return _name;
227 }
228
229 public void setPrintLongNames(boolean printLongNames)
230 {
231 this._printLongNames = printLongNames;
232 }
233
234 public boolean isPrintLongNames()
235 {
236 return this._printLongNames;
237 }
238
239 public boolean isHideStacks()
240 {
241 return _hideStacks;
242 }
243
244 public void setHideStacks(boolean hideStacks)
245 {
246 _hideStacks = hideStacks;
247 }
248
249 /* ------------------------------------------------------------ */
250 /**
251 * Is the source of a log, logged
252 *
253 * @return true if the class, method, file and line number of a log is logged.
254 */
255 public boolean isSource()
256 {
257 return _source;
258 }
259
260 /* ------------------------------------------------------------ */
261 /**
262 * Set if a log source is logged.
263 *
264 * @param source
265 * true if the class, method, file and line number of a log is logged.
266 */
267 public void setSource(boolean source)
268 {
269 _source = source;
270 }
271
272 public void warn(String msg, Object... args)
273 {
274 if (_level <= LEVEL_WARN)
275 {
276 StringBuilder buffer = new StringBuilder(64);
277 format(buffer,":WARN:",msg,args);
278 (_stderr==null?System.err:_stderr).println(buffer);
279 }
280 }
281
282 public void warn(Throwable thrown)
283 {
284 warn("",thrown);
285 }
286
287 public void warn(String msg, Throwable thrown)
288 {
289 if (_level <= LEVEL_WARN)
290 {
291 StringBuilder buffer = new StringBuilder(64);
292 format(buffer,":WARN:",msg,thrown);
293 (_stderr==null?System.err:_stderr).println(buffer);
294 }
295 }
296
297 public void info(String msg, Object... args)
298 {
299 if (_level <= LEVEL_INFO)
300 {
301 StringBuilder buffer = new StringBuilder(64);
302 format(buffer,":INFO:",msg,args);
303 (_stderr==null?System.err:_stderr).println(buffer);
304 }
305 }
306
307 public void info(Throwable thrown)
308 {
309 info("",thrown);
310 }
311
312 public void info(String msg, Throwable thrown)
313 {
314 if (_level <= LEVEL_INFO)
315 {
316 StringBuilder buffer = new StringBuilder(64);
317 format(buffer,":INFO:",msg,thrown);
318 (_stderr==null?System.err:_stderr).println(buffer);
319 }
320 }
321
322 public boolean isDebugEnabled()
323 {
324 return (_level <= LEVEL_DEBUG);
325 }
326
327 /**
328 * Legacy interface where a programmatic configuration of the logger level
329 * is done as a wholesale approach.
330 */
331 public void setDebugEnabled(boolean enabled)
332 {
333 if (enabled)
334 {
335 this._level = LEVEL_DEBUG;
336
337 for (Logger log : Log.getLoggers().values())
338 {
339 if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
340 ((StdErrLog)log).setLevel(LEVEL_DEBUG);
341 }
342 }
343 else
344 {
345 this._level = this._configuredLevel;
346
347 for (Logger log : Log.getLoggers().values())
348 {
349 if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
350 ((StdErrLog)log).setLevel(((StdErrLog)log)._configuredLevel);
351 }
352 }
353 }
354
355 public int getLevel()
356 {
357 return _level;
358 }
359
360 /**
361 * Set the level for this logger.
362 * <p>
363 * Available values ({@link StdErrLog#LEVEL_ALL}, {@link StdErrLog#LEVEL_DEBUG}, {@link StdErrLog#LEVEL_INFO},
364 * {@link StdErrLog#LEVEL_WARN})
365 *
366 * @param level
367 * the level to set the logger to
368 */
369 public void setLevel(int level)
370 {
371 this._level = level;
372 }
373
374 public void setStdErrStream(PrintStream stream)
375 {
376 this._stderr = stream==System.err?null:stream;
377 }
378
379 public void debug(String msg, Object... args)
380 {
381 if (_level <= LEVEL_DEBUG)
382 {
383 StringBuilder buffer = new StringBuilder(64);
384 format(buffer,":DBUG:",msg,args);
385 (_stderr==null?System.err:_stderr).println(buffer);
386 }
387 }
388
389 public void debug(Throwable thrown)
390 {
391 debug("",thrown);
392 }
393
394 public void debug(String msg, Throwable thrown)
395 {
396 if (_level <= LEVEL_DEBUG)
397 {
398 StringBuilder buffer = new StringBuilder(64);
399 format(buffer,":DBUG:",msg,thrown);
400 (_stderr==null?System.err:_stderr).println(buffer);
401 }
402 }
403
404 private void format(StringBuilder buffer, String level, String msg, Object... args)
405 {
406 String d = _dateCache.now();
407 int ms = _dateCache.lastMs();
408 tag(buffer,d,ms,level);
409 format(buffer,msg,args);
410 }
411
412 private void format(StringBuilder buffer, String level, String msg, Throwable thrown)
413 {
414 format(buffer,level,msg);
415 if (isHideStacks())
416 {
417 format(buffer,String.valueOf(thrown));
418 }
419 else
420 {
421 format(buffer,thrown);
422 }
423 }
424
425 private void tag(StringBuilder buffer, String d, int ms, String tag)
426 {
427 buffer.setLength(0);
428 buffer.append(d);
429 if (ms > 99)
430 {
431 buffer.append('.');
432 }
433 else if (ms > 9)
434 {
435 buffer.append(".0");
436 }
437 else
438 {
439 buffer.append(".00");
440 }
441 buffer.append(ms).append(tag);
442 if (_printLongNames)
443 {
444 buffer.append(_name);
445 }
446 else
447 {
448 buffer.append(_abbrevname);
449 }
450 buffer.append(':');
451 if (_source)
452 {
453 Throwable source = new Throwable();
454 StackTraceElement[] frames = source.getStackTrace();
455 for (int i = 0; i < frames.length; i++)
456 {
457 final StackTraceElement frame = frames[i];
458 String clazz = frame.getClassName();
459 if (clazz.equals(StdErrLog.class.getName()) || clazz.equals(Log.class.getName()))
460 {
461 continue;
462 }
463 if (!_printLongNames && clazz.startsWith("org.eclipse.jetty."))
464 {
465 buffer.append(condensePackageString(clazz));
466 }
467 else
468 {
469 buffer.append(clazz);
470 }
471 buffer.append('#').append(frame.getMethodName());
472 if (frame.getFileName() != null)
473 {
474 buffer.append('(').append(frame.getFileName()).append(':').append(frame.getLineNumber()).append(')');
475 }
476 buffer.append(':');
477 break;
478 }
479 }
480 }
481
482 private void format(StringBuilder builder, String msg, Object... args)
483 {
484 if (msg == null)
485 {
486 msg = "";
487 for (int i = 0; i < args.length; i++)
488 {
489 msg += "{} ";
490 }
491 }
492 String braces = "{}";
493 int start = 0;
494 for (Object arg : args)
495 {
496 int bracesIndex = msg.indexOf(braces,start);
497 if (bracesIndex < 0)
498 {
499 escape(builder,msg.substring(start));
500 builder.append(" ");
501 builder.append(arg);
502 start = msg.length();
503 }
504 else
505 {
506 escape(builder,msg.substring(start,bracesIndex));
507 builder.append(String.valueOf(arg));
508 start = bracesIndex + braces.length();
509 }
510 }
511 escape(builder,msg.substring(start));
512 }
513
514 private void escape(StringBuilder builder, String string)
515 {
516 for (int i = 0; i < string.length(); ++i)
517 {
518 char c = string.charAt(i);
519 if (Character.isISOControl(c))
520 {
521 if (c == '\n')
522 {
523 builder.append('|');
524 }
525 else if (c == '\r')
526 {
527 builder.append('<');
528 }
529 else
530 {
531 builder.append('?');
532 }
533 }
534 else
535 {
536 builder.append(c);
537 }
538 }
539 }
540
541 private void format(StringBuilder buffer, Throwable thrown)
542 {
543 if (thrown == null)
544 {
545 buffer.append("null");
546 }
547 else
548 {
549 buffer.append(EOL);
550 format(buffer,thrown.toString());
551 StackTraceElement[] elements = thrown.getStackTrace();
552 for (int i = 0; elements != null && i < elements.length; i++)
553 {
554 buffer.append(EOL).append("\tat ");
555 format(buffer,elements[i].toString());
556 }
557
558 Throwable cause = thrown.getCause();
559 if (cause != null && cause != thrown)
560 {
561 buffer.append(EOL).append("Caused by: ");
562 format(buffer,cause);
563 }
564 }
565 }
566
567
568 /**
569 * Create a Child Logger of this Logger.
570 */
571 protected Logger newLogger(String fullname)
572 {
573 StdErrLog logger = new StdErrLog(fullname);
574 // Preserve configuration for new loggers configuration
575 logger.setPrintLongNames(_printLongNames);
576 // Let Level come from configured Properties instead - sel.setLevel(_level);
577 logger.setSource(_source);
578 logger._stderr = this._stderr;
579
580 // Force the child to have any programmatic configuration
581 if (_level!=_configuredLevel)
582 logger._level=_level;
583
584 return logger;
585 }
586
587 @Override
588 public String toString()
589 {
590 StringBuilder s = new StringBuilder();
591 s.append("StdErrLog:");
592 s.append(_name);
593 s.append(":LEVEL=");
594 switch (_level)
595 {
596 case LEVEL_ALL:
597 s.append("ALL");
598 break;
599 case LEVEL_DEBUG:
600 s.append("DEBUG");
601 break;
602 case LEVEL_INFO:
603 s.append("INFO");
604 break;
605 case LEVEL_WARN:
606 s.append("WARN");
607 break;
608 default:
609 s.append("?");
610 break;
611 }
612 return s.toString();
613 }
614
615 public static void setProperties(Properties props)
616 {
617 __props.clear();
618 __props.putAll(props);
619 }
620
621 public void ignore(Throwable ignored)
622 {
623 if (_level <= LEVEL_ALL)
624 {
625 StringBuilder buffer = new StringBuilder(64);
626 format(buffer,":IGNORED:","",ignored);
627 (_stderr==null?System.err:_stderr).println(buffer);
628 }
629 }
630 }