LogBack学习记录(六)Layout的学习

Layout是logback的一个组件,负责将日志事件转换为string,在layout接口中定义了format方法,用于将事件转换为String。Layout的接口大体如下:

public interface Layout<E> extends ContextAware, LifeCycle {

  String doLayout(E event);
  String getFileHeader();
  String getPresentationHeader();
  String getFileFooter();
  String getPresentationFooter();
  String getContentType();
}
这个接口基本可以满足大部分的转换需求。

Logback-classic

logback-classic 可以处理 IloggingEvent的子类事件。

编写自己的Layout

我们采用logback-class的架构来实现一个可以打印出 应用以运行时间,日志级别,调用的线程,日志名称,日志内容的功能。
例子如下:

package chapters.layouts;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.LayoutBase;

public class MySampleLayout extends LayoutBase<ILoggingEvent> {

  public String doLayout(ILoggingEvent event) {
    StringBuffer sbuf = new StringBuffer(128);
    sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());
    sbuf.append(" ");
    sbuf.append(event.getLevel());
    sbuf.append(" [");
    sbuf.append(event.getThreadName());
    sbuf.append("] ");
    sbuf.append(event.getLoggerName();
    sbuf.append(" - ");
    sbuf.append(event.getFormattedMessage());
    sbuf.append(CoreConstants.LINE_SEP);
    return sbuf.toString();
  }
}
注意到mysampleLayout继承自layoutbase。layoutbase对所有layout实例的基本状态进行了管理,比如layout何时启动或者停止,信息的头部,尾部,内容类型的信息。layoutbase是一个非常通用的类,开发者一般可以通过继承该类来实现所期望的输出格式。

mysample类中唯一的方法是dolayout,该方法中首先初始化了一乐stringbuffer,然后将一系列event的属性进行添加。之后将buffer转换为string,然后进行输出。
在上面的例子,dolayout方法中忽略了事件中的异常,在实际的应用中,一般都会需要对异常信息进行展示。

配置 自定义的layout

自定义的layout 可以按照其他组件的方式进行配置。在前文我们说过,FileAppender及其子类需要一个encoder,满足这个需求,我们用layoutwrappingencoder来封装我们的mysampleout然后将其传递给fileappender。配置文件,如下所示:

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="chapters.layouts.MySampleLayout" />
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
最终的到日志输出格式如下:

10489 DEBUG [main] com.marsupial.Pouch - Hello world.

实际输出如下:

0 DEBUG [main] chapters.layouts.SampleLogging - Everything's going well
0 ERROR [main] chapters.layouts.SampleLogging - maybe not quite...

可以在layout或者其他任何的logback组件中通过添加setter的方式来添加属性。如下面的列子就是在前面的例子基础上进行了属性添加,具体代码及配置文件如下:

package chapters.layouts;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.LayoutBase;

public class MySampleLayout2 extends LayoutBase<ILoggingEvent> {

  String prefix = null;
  boolean printThreadName = true;

  public void setPrefix(String prefix) {
    this.prefix = prefix;
  }

  public void setPrintThreadName(boolean printThreadName) {
    this.printThreadName = printThreadName;
  }

  public String doLayout(ILoggingEvent event) {
    StringBuffer sbuf = new StringBuffer(128);
    if (prefix != null) {
      sbuf.append(prefix + ": ");
    }
    sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime());
    sbuf.append(" ");
    sbuf.append(event.getLevel());
    if (printThreadName) {
      sbuf.append(" [");
      sbuf.append(event.getThreadName());
      sbuf.append("] ");
    } else {
      sbuf.append(" ");
    }
    sbuf.append(event.getLoggerName());
    sbuf.append(" - ");
    sbuf.append(event.getFormattedMessage());
    sbuf.append(LINE_SEP);
    return sbuf.toString();
  }
}

配置文件如下:

<configuration>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="chapters.layouts.MySampleLayout2"> 
        <prefix>MyPrefix</prefix>
        <printThreadName>false</printThreadName>
      </layout>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
需要注意的是,printThreadName属性是一个boolean类型,而不是string类型。

PatternLayout

logback classic 提供了一个配置性非常好的实现类 :patternLayout。就像所有的layout一样,patternlayout也是实现将日志事件转换为String进行输出。但是他的输出可以通过他的转换模式进行定制。

转换模式与C语言的printf()方法的格式控制非常类似。一个转换模式由 输出字符 和 转换控制表达式组成。你可以随意的在转换模式中插入任何字符。 每一个转换表达式以‘%’开头,然后在一对大括号中添加各种格式控制参数。其中有一些转换词可以用来控制时间属性,等级,线程等等。

由于Fileappender及其子类必须有一个encoder。因此,当将fileappender及其子类与patternlayout联合起来使用时,必须提供用encoder将patternlayout进行封装。由于fileappender和patterlayout的组合使用非常频繁,因此logback提供了一个名为patternlayoutencoder的encoder实现类,用于将patternlayout进行封装,然后可以作为一个encoder来进行使用。下面的例子展示了consoleappender和patternlayoutencoder的联合使用。

package chapters.layouts;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;

public class PatternSample {

  static public void main(String[] args) throws Exception {
    Logger rootLogger = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
    LoggerContext loggerContext = rootLogger.getLoggerContext();
    // we are not interested in auto-configuration
    loggerContext.reset();

    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
    encoder.setContext(loggerContext);
    encoder.setPattern("%-5level [%thread]: %message%n");
    encoder.start();

    ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<ILoggingEvent>();
    appender.setContext(loggerContext);
    appender.setEncoder(encoder); 
    appender.start();

    rootLogger.addAppender(appender);

    rootLogger.debug("Message 1"); 
    rootLogger.warn("Message 2");
  } 
}
输出结果将如下所示:

DEBUG [main]: Message 1 

WARN [main]: Message 2

需要注意的是,在上面的转换模式“%-5level [%thread]: %message%n”中,在输出字符及转换表达式之间并没有分隔符。当进行转换模式的解析时,patternlayout能够将输出字符(空格,括号,冒号)和转换表达式进行区分。在上面的例子中,转换表达式“%5level”表示日志的级别信息将会只能输出五个字符长度。后面将会对格式进行进行更加详细的介绍。

在 patternlayout 小括号是有特殊意义的,在输出字符中应尽量避免使用。就像在前面提到了,转换表达式可能将一些 配置参数在大括号中进行配置。比如%logger{10},这里logger是转换词,而10就是他的属性。

下面的表格对 转换词及其属性进行了介绍。当多个转换词在同一个单元中列出时,他们就是别名的关系。

Conversion Word(转换词)Effect(作用) 
c{length
lo{length
logger{length}
Outputs the name of the logger at the origin of the logging event.

This conversion word takes an integer as its first and only option. The converter's abbreviation algorithm will shorten the logger name, usually without significant loss of meaning. Setting the value of length option to zero constitutes an exception. It will cause the conversion word to return the sub-string right to the rightmost dot character in the logger name. The next table provides examples of the abbreviation algorithm in action.

输出日志事件的名称,这个转换词的唯一属性是数字类型的。将会将日志的名称进行缩短。当将这个值设为0,将会导致异常。下面是一些截取的例子:

Conversion specifierLogger nameResult
%logger mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar
%logger{0} mainPackage.sub.sample.Bar Bar
%logger{5} mainPackage.sub.sample.Bar m.s.s.Bar
%logger{10} mainPackage.sub.sample.Bar m.s.s.Bar
%logger{15} mainPackage.sub.sample.Bar m.s.sample.Bar
%logger{16} mainPackage.sub.sample.Bar m.sub.sample.Bar
%logger{26} mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar

Please note that the rightmost segment in a logger name is never abbreviated, even if its length is longer than the length option. Other segments may be shortened to at most a single character but are never removed.

需要注意的是,最右侧的类名是不会被缩短的,即使设置的长度比类名还要端。其他部分的会被缩短,但不会被删除。


C{length

class{length}

Outputs the fully-qualified class name of the caller issuing the logging request.

Just like the %logger conversion word above, this conversion takes an integer as an option to shorten the class name. Zero carries special meaning and will cause the simple class name to be printed without the package name prefix. By default the class name is printed in full.

Generating the caller class information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue.

将调用日志的类的全路径进行输出。就像%logger一样,采用一个整型数字作为属性。如果将值设置为0的话,将会只输出类名,而路径名称就不会输出。默认情况下会输出全路径。总的来说,这个属性的运行效率不高,建议不要采用。

contextName
cn
Outputs the name of the logger context to which the logger at the origin of the event was attached to.
将日志的上下文名称进行输出
d{pattern
date{pattern
d{patterntimezone
date{patterntimezone}

Used to output the date of the logging event. The date conversion word admits a pattern string as a parameter. The pattern syntax is compatible with the format accepted by java.text.SimpleDateFormat.

You can specify the string "ISO8601" for the ISO8601 date format. Note that the %date conversion word defaults to the ISO 8601 date format in the absence of a pattern parameter.

Here are some sample parameter values. They assume that the actual date is Friday 20th of October, 2006 and that the author has returned to working on this document just after lunch.

输出日志的时间,data 属性将 pattern string 作为一个参数,其构造方式和simpledateformat相同。,下面是一些例子

Conversion PatternResult
%d 2006-10-20 14:06:49,812
%date 2006-10-20 14:06:49,812
%date{ISO8601} 2006-10-20 14:06:49,812
%date{HH:mm:ss.SSS} 14:06:49.812
%date{dd MMM yyyy;HH:mm:ss.SSS} 20 oct. 2006;14:06:49.812

The second parameter specifies a timezone. For example, the '%date{HH:mm:ss.SSS, Australia/Perth} would print the time in the time zone of Perth, Australia, the world's most isolated city. Note that in the absence of the timezone parameter, the default timezone of the host Java platform is used. If the specified timezone identifier is unknown or misspelled, the GMT timezone is assumed as dictated by the TimeZone.getTimeZone(String) method specification.

COMMON ERROR Given that the comma ',' character is interpreted as the parameter separator, the patternHH:mm:ss,SSS will be interpreted as the pattern HM:mm:ss and the timezone SSS. If you wish to include a comma in your date pattern, then simply enclose the pattern between quotes. For example, %date{"HH:mm:ss,SSS"}.

第二参数用以确定一个时区3,如 the '%date{HH:mm:ss.SSS, Australia/Perth},将会输出Perth, Australia的时间。注意,默认采用的时区是主机java平台采用的时区。如果时区没有或者拼写错误,则将设置为GMT的时区。

注意:在这里面,逗号被视为分隔符,如HH:mm:ss,SSS将被 视为采用HH:mm:ss的时间输出格式,采用ssss作为时区。如果需要在时间样式里面输出逗号,需要将其放在引号里面。如%date{"HH:mm:ss,SSS"}.



F / file

Outputs the file name of the Java source file where the logging request was issued.

Generating the file information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue

不解释,建议不用
caller{depth}caller{depth, evaluator-1, ... evaluator-n}

Outputs location information of the caller which generated the logging event.

The location information depends on the JVM implementation but usually consists of the fully qualified name of the calling method followed by the caller's source, the file name and line number between parentheses.

A integer can be added to the caller conversion specifier's options to configure the depth of the information to be displayed.

For example, %caller{2} would display the following excerpt:

0    [main] DEBUG - logging statement 
Caller+0   at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22)
Caller+1   at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)

And %caller{3} would display this other excerpt:

16   [main] DEBUG - logging statement 
Caller+0   at mainPackage.sub.sample.Bar.sampleMethodName(Bar.java:22)
Caller+1   at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)
Caller+2   at mainPackage.ConfigTester.main(ConfigTester.java:38)

This conversion word can also use evaluators to test logging events against a given criterion before computing caller data. For example, using %caller{3, CALLER_DISPLAY_EVAL} will display three lines of stacktrace, only if the evaluator called CALLER_DISPLAY_EVAL returns a positive answer.

Evaluators are described below.

输出产生日志事件的调用者的信息。调用者的信息取决与具体的JVM实现。但是通常包括完全路径名,方法名,文件名,方法的line number。 一个整型参数可以用以控制信息展示的深度,如:%caller{2} 将展示两层。 %caller{3} 就会展示三层。这个参数词还可以以指定的条件进行日志输出,如%caller{3, CALLER_DISPLAY_EVAL} 只有当CALLER_DISPLAY_EVAL满足了才会输出日志。
L / line

Outputs the line number from where the logging request was issued.

Generating the line number information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue.

输出日志的 line number,尽量少用
m / msg / messageOutputs the application-supplied message associated with the logging event.
事件相关的信息
M / method

Outputs the method name where the logging request was issued.

Generating the method name is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue.

不解释,建议少用
n

Outputs the platform dependent line separator character or characters.

This conversion word offers practically the same performance as using non-portable line separator strings such as "\n", or "\r\n". Thus, it is the preferred way of specifying a line separator.

指定平台的换行符。
p / le / levelOutputs the level of the logging event. 日志级别。
r / relativeOutputs the number of milliseconds elapsed since the start of the application until the creation of the logging event.
输出自系统启动到日志时间发生的耗时。
t / threadOutputs the name of the thread that generated the logging event.线程不解释
X{key:-defaultVal
mdc{key:-defaultVal}

Outputs the MDC (mapped diagnostic context) associated with the thread that generated the logging event.

If the mdc conversion word is followed by a key between braces, as in %mdc{userid}, then the MDC value corresponding to the key 'userid' will be output. If the value is null, then the default valuespeficied after the :- operator is output. If no deault value is specified than the empty string is output.

If no key is given, then the entire content of the MDC will be output in the format "key1=val1, key2=val2".

See the chapter on MDC for more details on the subject.

这个属性很少用到,用到再研究吧。


csdn的破表格编辑器不会自动加行,继续上面的表。

ex{depth
exception{depth
throwable{depth

ex{depth, evaluator-1, ..., evaluator-n} 
exception{depth, evaluator-1, ..., evaluator-n} 
throwable{depth, evaluator-1, ..., evaluator-n}

Outputs the stack trace of the exception associated with the logging event, if any. By default the full stack trace will be output.

The throwable conversion word can followed by one of the following options:

  • short: prints the first line of the stack trace
  • full: prints the full stack trace
  • Any integer: prints the given number of lines of the stack trace

Here are some examples:

将与日志事件相关的异常的stack trace进行输出。默认情况下,输出全部的stack trace。 throwable中可以设置以下的一项值:

short 只输出stack trace的第一行

full 全部输出

any 输出指定的行()

Conversion PatternResult
%ex
mainPackage.foo.bar.TestException: Houston we have a problem
  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
  at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
%ex{short}
mainPackage.foo.bar.TestException: Houston we have a problem
  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
%ex{full}
mainPackage.foo.bar.TestException: Houston we have a problem
  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
  at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
%ex{2}
mainPackage.foo.bar.TestException: Houston we have a problem
  at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
  at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)

This conversion word can also use evaluators to test logging events against a given criterion before creating the output. For example, using %ex{full, EX_DISPLAY_EVAL} will display the full stack trace of the exception only if the evaluator called EX_DISPLAY_EVAL returns a negative answer. Evaluators are described further down in this document.


xEx{depth
xException{depth
xThrowable{depth

xEx{depth, evaluator-1, ..., evaluator-n} 
xException{depth, evaluator-1, ..., evaluator-n} 
xThrowable{depth, evaluator-1, ..., evaluator-n}

Same as the %throwable conversion word above with the addition of class packaging information.

If you do not specify %xThrowable or another throwable-related conversion word in the conversion pattern, PatternLayout will automatically add it as the last conversion word, on account of the importance of stack trace information. The $nopex conversion word can be substituted for %xThrowable, if you do not wish stack trace information to be displayed. See also the %nopex conversion word.

At the end of each stack frame of the exception, a string consisting of the jar file containing the relevant class followed by the "Implementation-Version" as found in that jar's manifest will be added. This innovative technique was originally suggested by James Strachan. If the information is uncertain, then the class packaging data will be preceded by a tilde, i.e. the '~' character.

%throwable 相同

如果没有指定%xThrowable 或 另一个 throwable-related 转换词。patternlayout将会自动这个属性添加,以统计stack trace的信息。如果不想stack trace信息输出的话,可以用 $nopex替代%xThrowable。

在每个stack trace的结尾,将会输出相关类所在的jar包。如果包信息不能确定的话,就用波浪号进行表示,如下面的例子。


java.lang.NullPointerException at com.xyz.Wombat(Wombat.java:57) ~[wombat-1.3.jar:1.3]

at com.xyz.Wombat(Wombat.java:76) ~[wombat-1.3.jar:1.3] 

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.5.0_06] 

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.5.0_06] 

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.5.0_06] 

at java.lang.reflect.Method.invoke(Method.java:585) ~[na:1.5.0_06] 

at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59) [junit-4.4.jar:na] 

at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98) [junit-4.4.jar:na]

nopex  
nopexception

Although it pretends to handle stack trace data, this conversion word does not output any data, thus, effectively ignoring exceptions.

The %nopex conversion word allows the user to override PatternLayout's internal safety mechanism which silently adds the %xThrowable conversion keyword in the absence of another conversion word handling 

这个属性用以忽略logback的默认机制,在输出样式的最后自动加上 %xThrowable 的设置。这样的话,异常堆栈将不会显示。 marker

Outputs the marker associated with the logger request.

In case the marker contains children markers, the converter displays the parent as well as childrens' names according to the format shown below.

parentName [ child1, child2 ]

没用

property{key}

Outputs the value associated with a property named key. The the relevant docs on how to define ion entitled define variables and variable scopes. If key is not a property of the logger context, then keywill be looked up in the System properties.

There is no default value for key. If it is omitted, the returned value will be "Property_HAS_NO_KEY", expliciting the error condition.

没用 replace(p){r, t}

Replaces occurrences of 'r', a regex, with its replacement 't' in the string produces by the sub-pattern 'p'. For example, "%replace(%msg){'\s', ''}" will remove all spaces contained in the event message.

The pattern 'p' can be arbitrarily complex and in particular can contain multiple conversion keywords. For instance, "%replace(%logger %msg){'\.', '/'}" will replace all dots in the logger or the message of the event with a forward slash.

替换作用,很少用到吧 rEx { depth
rootException { depth

rEx {depth, evaluator-1, ..., evaluator-n} 
rootException {depth, evaluator-1, ..., evaluator-n}

Outputs the stack trace of the exception associated with the logging event, if any. The root cause will be output first instead of the standard "root cause last". Here is a sample output (edited for space):

java.lang.NullPointerException
  at com.xyz.Wombat(Wombat.java:57) ~[wombat-1.3.jar:1.3]
  at com.xyz.Wombat(Wombat.java:76) ~[wombat-1.3.jar:1.3]
Wrapped by: org.springframework.BeanCreationException: Error creating bean with name 'wombat': 
  at org.springframework.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248) [spring-2.0.jar:2.0]
  at org.springframework.AbstractBeanFactory.getBean(AbstractBeanFactory.java:170) [spring-2.0.jar:2.0]
  at org.apache.catalina.StandardContext.listenerStart(StandardContext.java:3934) [tomcat-6.0.26.jar:6.0.26]

The %rootException converter admits the same optional parameters as the %xException converter described above, including depth and eveluators. It outputs also packaging information. In short, %rootException is very similar to %xException, only the order of exception output is reversed.

Tomasz Nurkiewicz, the author of %rootException converter, documents his contribution in a blog entry entitled "Logging exceptions root cause first".

如果设置,错误的更原因将会最先输出  


% character has special meaning

%的输出

通过前面可以看出,%在logback中有特殊含义,当需要将其进行输出是,采用反斜杠的方式:\%。

Restrictions on literals immediately following conversion words
转换词的输出
一般情况下,文字输出中也就包括一些空格或者限定型的符号,不会与转换词冲突。如 "%level [%thread] - %message%n" 中的文字输出只是包括   [  和  ] 以及-。然而,总有2b的情况,如"%date%nHello" 就会报错,%nHello无法解析究竟是做什么的,这时应该改为:"%date%n{}Hello"。

Format modifiers

在默认情况下, 相关信息会按照上述的设置进行输出。但是有的时候需要另外对格式进行调整(最大最小宽度)。formate modifier属性就是用来在百分号和转换词之间进行设置。第一个format modifier 是左对齐婊子通过(-)减号标记。然后是最小宽度表示是一个十进制的数值。

如果其中还包含其他字符,那么将会填充其中,直到最小字符的长度。默认是填充左侧,但是也可以设置为右侧填充。如果数据的长度大于最小长度限制,这个区域就扩大,以适应数据长度,数据是不会被删除的。

当然这种行为可以通过maximum进行控制,当数据的长度大于maximum是,将会从数据的开始部分进行截取。例如,maximum值是8,而数据长度是10,那么最开始的两个字符将会被截取。这与c语言中的从后面截取是不同的。 可以通过将减号符号放置在filed的后面实现从后面截取。下面是例子:

Format modifierLeft justifyMinimum widthMaximum widthComment
%20logger false 20 noneLeft pad with spaces if the logger name is less than 20 characters long.
当数据小于20时,在左侧填充空格
%-20logger true 20 noneRight pad with spaces if the logger name is less than 20 characters long.
当数据小于20时,将会在右侧填充空格,实现了左对齐
%.30logger NA none 30Truncate from the beginning if the logger name is longer than 30 characters.
当数据大于30个字符,将从前面开始截取
%20.30logger false 20 30Left pad with spaces if the logger name is shorter than 20 characters. However, if logger name is longer than 30 characters, then truncate from the beginning.
当数据小于20从左侧填充,当数据大于30,从开始进行截取
%-20.30logger true 20 30Right pad with spaces if the logger name is shorter than 20 characters. However, if logger name is longer than 30 characters, then truncate from the beginning.
当数据小于20,从右侧开始填充,当数据大于30,从开始进行截取
%.-30logger NA none 30Truncate from the end if the logger name is longer than 30 characters.
当数据大于30,从尾部进行截取。

下面的例子显示了一下输出结果,注意中括号,只是为了展示宽度而添加的。、

Format modifierLogger nameResult
[%20.20logger] main.Name
[           main.Name]
[%-20.20logger] main.Name
[main.Name           ]
[%10.10logger] main.foo.foo.bar.Name
[o.bar.Name]
[%10.-10logger] main.foo.foo.bar.Name
[main.foo.f]

Output just one letter for the level 用一个字母表示日志等级

可以用  T, D, W, I and E.替代TRACE, DEBUG, WARN, INFO or ERROR表示日志等级。做如下配置即可实现:"%.-1level".

Parentheses are special

在logback中,将样式放在括号中被看成一个组。因此可以构成一个子组模式,并在其基础上进行样式控制。在0.9.27版本后,logback支持子组功能。如下面的例子

%-30(%d{HH:mm:ss.SSS} [%thread]) %-5level %logger{32} - %msg%n

就将会构造一个子样式 "%d{HH:mm:ss.SSS} [%thread]",这个样式作为一个整体被控制为当字符少于30会进行右侧填充。

如果没有子组,结果输出如下:

If without the grouping the output was

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server

13:09:30 [pool-1-thread-1] INFO ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0

13:09:38 [btpool0-7] INFO c.q.l.demo.lottery.LotteryAction - Number: 50 was tried.

13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Beginning to factor.

13:09:40 [btpool0-7] DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor.

13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Found factor 2

添加了子组的样式,"%-30()" ,日志输出如下所示:

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Classload hashcode is 13995234

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Initializing for ServletContext

13:09:30 [main] DEBUG c.q.logback.demo.ContextListener - Trying platform Mbean server

13:09:30 [pool-1-thread-1] INFO ch.qos.logback.demo.LoggingTask - Howdydy-diddly-ho - 0

13:09:38 [btpool0-7] INFO c.q.l.demo.lottery.LotteryAction - Number: 50 was tried.

13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Beginning to factor.

13:09:40 [btpool0-7] DEBUG c.q.l.d.prime.NumberCruncherImpl - Trying 2 as a factor.

13:09:40 [btpool0-7] INFO c.q.l.d.prime.NumberCruncherImpl - Found factor 2

显然第二种的样式,输出更加便于阅读。如果希望输出括号则需要加上反斜杠,如下所示:\(%d{HH:mm:ss.SSS} [%thread]\).

Coloring

通过括号的构成的子组可以对其日志输出颜色进行控制。在1。0。5版本后,patternlayout能够识别如下颜色: "%black", "%red", "%green","%yellow","%blue", "%magenta","%cyan", "%white", "%gray", "%boldRed","%boldGreen", "%boldYellow", "%boldBlue", "%boldMagenta""%boldCyan", "%boldWhite" and "%highlight" 。这些颜色将作为转换词存在,这些转换词将包含一个子模式,这样该子模式的内容将会以指定颜色进行输出。
下面的配置文件演示了颜色是使用,
 %cyan(%logger{15}) 表示日志的名称将为缩短为15个字符,并且以cyan 的颜色显示。%highlight属性将会根据日志的等级输出不同颜色,n bold-red for events of level ERROR, in red for WARN, in BLUE for INFO, and in the default color for other levels.

View as .groovy
<configuration debug="true">
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- On Windows machines setting withJansi to true enables ANSI
         color code interpretation by the Jansi library. This requires
         org.fusesource.jansi:jansi:1.8 on the class path.  Note that
         Unix-based operating systems such as Linux and Mac OS X
         support ANSI color codes by default. -->
    <withJansi>true</withJansi>
    <encoder>
      <pattern>[%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg %n</pattern>
    </encoder>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

输出如下所示:

[main] WARN  c.l.TrivialMain - a warning message 0
[main] DEBUG c.l.TrivialMain - hello world number1
[main] DEBUG c.l.TrivialMain - hello world number2
[main] INFO  c.l.TrivialMain - hello world number3
[main] DEBUG c.l.TrivialMain - hello world number4
[main] WARN  c.l.TrivialMain - a warning message 5
[main] ERROR c.l.TrivialMain - Finish off with fireworks


Evaluators

根据条件来判定日志是否显示,个人感觉应该很少用到,将原文记录如下,用到再进行翻译。

As mentioned above, option lists come in handy when a conversion specifier is required to behave dynamically based on one or more EventEvaluator objects. EventEvaluator objects have the responsibility to determine whether a given logging event matches the criteria of the evaluator.

Let us review an example involving a EventEvaluator. The next configuration file outputs the logging events to the console, displaying date, thread, level, message and caller data. Given that extracting the caller data of a logging event is on the expensive side, we will do so only when the logging request originates from a specific logger, and when the message contains a certain string. Thus, we make sure that only specific logging requests will have their caller information generated and displayed. In other cases, where the caller data is superfluous, we will not penalize application performance.

Evaluators and in particular evaluation expressions are presented in a dedicated section of the chapter on filters which you MUST read if you want to use evaluators in any meaningful way. Also note that the examples below are implicitly based on JaninoEventEvaluator which requires the Janino library. Please see the corresponding section of the setup document.

Example: Sample usage of EventEvaluators (logback-examples/src/main/java/chapters/layouts/callerEvaluatorConfig.xml) View as .groovy
<configuration>
  <evaluator name="DISP_CALLER_EVAL">
    <expression>logger.contains("chapters.layouts") &amp;&amp; \
      message.contains("who calls thee")</expression>
  </evaluator>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <encoder>
      <pattern>
        %-4relative [%thread] %-5level - %msg%n%caller{2, DISP_CALLER_EVAL}
      </pattern>
    </encoder>
  </appender>

  <root level="DEBUG"> 
    <appender-ref ref="STDOUT" /> 
  </root>
</configuration>

The above evaluation expression matches events which emanate from a logger with a name containing the string "chapters.layouts" and the message contains the string "who calls thee". Due to XML encoding rules, the & character cannot be written as is, and needs to be escaped as &amp;.

The following class makes use of some of the characteristics mentioned in above configuration file.

Example: Sample usage of EventEvaluators (logback-examples/src/main/java/chapters/layouts/CallerEvaluatorExample.java)

package chapters.layouts;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;

public class CallerEvaluatorExample {

  public static void main(String[] args)  {
    Logger logger = LoggerFactory.getLogger(CallerEvaluatorExample.class);
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    try {
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(lc);
      configurator.doConfigure(args[0]);
    } catch (JoranException je) {
      // StatusPrinter will handle this
    }
    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

    for (int i = 0; i < 5; i++) {
      if (i == 3) {
        logger.debug("who calls thee?");
      } else {
        logger.debug("I know me " + i);
      }
    }
  }
}

The above application does nothing particularly fancy. Five logging requests are issued, the third one emitting the message "who calls thee?"

The command

java chapters.layouts.CallerEvaluatorExample src/main/java/chapters/layouts/callerEvaluatorConfig.xml

will yield

0    [main] DEBUG - I know me 0 
0    [main] DEBUG - I know me 1 
0    [main] DEBUG - I know me 2 
0    [main] DEBUG - who calls thee? 
Caller+0   at chapters.layouts.CallerEvaluatorExample.main(CallerEvaluatorExample.java:28)
0    [main] DEBUG - I know me 4

When a logging request is issued, the corresponding logging event is evaluated. Only the third logging event matches the evaluation criteria, causing its caller data to be displayed. For other logging events, the evaluation criteria do not match and no caller data is printed.

One can change the expression to correspond a real world scenario. For instance, one could combine the logger name and request level. Thus, logging requests of level WARN and up, originating from a sensitive part of an application, e.g. a financial transaction module, would have their caller data displayed.

Important: With the caller conversion word, caller data is output when the expression evaluates totrue.

Let us consider at a different situation. When exceptions are included in a logging request, their stack trace is also output. However, one might want to suppress the stack trace for some specific exceptions.

The Java code shown below creates three log requests, each with an exception. The second exception is different from the others: it contains the string "do not display this" and it is of typechapters.layouts.TestException. As its message commands, let us now prevent the second exception from being printed.

Example: Sample usage of EventEvaluators (logback-examples/src/main/java/chapters/layouts/ExceptionEvaluatorExample.java)

package chapters.layouts;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;

public class ExceptionEvaluatorExample {

  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(ExceptionEvaluatorExample.class);
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

    try {
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(lc);
      lc.reset();
      configurator.doConfigure(args[0]);
    } catch (JoranException je) {
       // StatusPrinter will handle this
    }
    StatusPrinter.printInCaseOfErrorsOrWarnings(lc);

    for (int i = 0; i < 3; i++) {
      if (i == 1) {
        logger.debug("logging statement " + i, new TestException(
            "do not display this"));
      } else {
        logger.debug("logging statement " + i, new Exception("display"));
      }
    }
  }
}

In the next configuration file, the evaluation expression matches events containing a throwable of typechapters.layouts.TextException, precisely the type of exceptions we wish to suppress.

Example: Sample usage of EventEvaluators (logback-examples/src/main/java/chapters/layouts/exceptionEvaluatorConfig.xml)
<configuration>

  <evaluator name="DISPLAY_EX_EVAL">
    <expression>throwable != null &amp;&amp; throwable instanceof  \
      chapters.layouts.TestException</expression>
  </evaluator>
        
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%msg%n%ex{full, DISPLAY_EX_EVAL}</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

With this configuration, each time an instance of the chapters.layouts.TestException is included within a logging request, the stack trace will be suppressed.

Launching the command

java chapters.layouts.ExceptionEvaluatorExample src/main/java/chapters/layouts/exceptionEvaluatorConfig.xml

will yield

logging statement 0java.lang.Exception: display at chapters.layouts.ExceptionEvaluatorExample.main(ExceptionEvaluatorExample.java:43) [logback-examples-0.9.19.jar:na]logging statement 1logging statement 2java.lang.Exception: display at chapters.layouts.ExceptionEvaluatorExample.main(ExceptionEvaluatorExample.java:43) [logback-examples-0.9.19.jar:na]

Notice how the second log statement has no stack trace. We effectively suppressed the stack trace for the TextException. The text between square brackets at the end of each stack trace line is packaging information discussed earlier.

NOTE With the %ex conversion specifier, the stack trace is displayed when the expression evaluates tofalse.

Creating a custom conversion specifier

自定义转换模式,这个基本用不到。原文记录一下

Up to this point we have presented the built-in conversion words in PatternLayout. But it is also possible to add conversion words of your own making.

Building a custom conversion specifier consists of two steps.

Step 1

First, you must extend the ClassicConverter class. ClassicConverter objects are responsible for extracting information out of ILoggingEvent instances and producing a String. For example, LoggerConverter, the converter underlying the %logger conversion word, extracts the name of the logger from ILoggingEvent and returns it as a String. It might abbreviate the logger name in the process.

Here is a customer converter which returns the time elapsed since its creaton in nanoseconds:

Example: Sample Converter Example (src/main/java/chapters/layouts/MySampleConverter.java)
public class MySampleConverter extends ClassicConverter {

  long start = System.nanoTime();

  @Override
  public String convert(ILoggingEvent event) {
    long nowInNanos = System.nanoTime();
    return Long.toString(nowInNanos-start);
  }
}

This implementation is pretty straightforward. The MySampleConverter class extends ClassicConverter, and implements the convert method which returns the number of nano-seconds elapsed since its creation.

Step 2

In the second step, we must let logback know about the new Converter. For this purpose, we need to declare the new conversion word in the configuration file, as shown below:

Example: Sample Converter Example (src/main/java/chapters/layouts/mySampleConverterConfig.xml) View as .groovy
<configuration>

  <conversionRule conversionWord="nanos" 
                  converterClass="chapters.layouts.MySampleConverter" />
        
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%-6nanos [%thread] - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

Once the new conversion word has been declared in the configuration file, we can refer to it withinPatternLayout pattern, as with any other conversion word.

The command:

java chapters.layouts.SampleLogging src/main/java/chapters/layouts/mySampleConverterConfig.xml

should yield output akin to:

4868695 [main] DEBUG - Everything's going well
5758748 [main] ERROR - maybe not quite...

The reader might want to take a look at other Converter implementations such as MDCConverter to learn about more complex behaviours, such as option handling. For creating your own coloring schemes have a look at HighlightingCompositeConverter.

HTMLLayout


采用html样式输出,不介绍,将配置文件列出,可以与patternlayout的配置文件进行一下对比使用:可以看出encoder和layout的实现类都要进行设置,而之前的都是采用了默认设置,因此会更加简洁。

<configuration debug="true">
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="ch.qos.logback.classic.html.HTMLLayout">
        <pattern>%relative%thread%mdc%level%logger%msg</pattern>
      </layout>
    </encoder>
    <file>test.html</file>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>

Log4j XMLLayout

XML的输出方式,不介绍,配置文件如下,做一下对比。

View as .groovy
<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>test.xml</file>
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="ch.qos.logback.classic.log4j.XMLLayout">
        <locationInfo>true</locationInfo>
      </layout>
    </encoder> 
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration> 

后续的logback-access部分不进行介绍。layout部分至此结束。









  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值