Mercurial Hosting > luan
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 } |