(五)Logback中的Layout_logback layout_凌波漫步&的博客

CSDN博客 · · 965 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、什么是Layout?

Layout是logback中负责把日志事件转换成成字符串的组件,接口如下:

public interface Layout<E> extends ContextAware, LifeCycle {

  String doLayout(E event);
  String getFileHeader();
  String getPresentationHeader();
  String getFileFooter();
  String getPresentationFooter();
  String getContentType();
}

二、自定义Layout

1、继承自LayoutBase接口即可,如下:

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();
  }
}

日志输出如下:

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

在配置文件中配置layout

<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>

2、包含自定义属性的layout,自定义实现如下:

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>

三、转换词

有效转换词以及相关选项如下表:

转换词备注
c{length}
lo{length}
logger{length}

输出日志记录器的名字,该类转换词带有一个可选整形参数,转换器省略算法会缩短日志记录器的名字。

转换符日志记录器名结果
%loggermainPackage.sub.sample.BarmainPackage.sub.sample.Bar
%logger{0}mainPackage.sub.sample.BarBar
%logger{5}mainPackage.sub.sample.Barm.s.s.Bar
%logger{10}mainPackage.sub.sample.Barm.s.s.Bar
%logger{15}mainPackage.sub.sample.Barm.s.sample.Bar
%logger{16}mainPackage.sub.sample.Barm.sub.sample.Bar
%logger{26}mainPackage.sub.sample.BarmainPackage.sub.sample.Bar

注意:日志记录器名最右边部分不会被省略,即使长度超出了设定的length选项。

C{length}
class{length}

输出发出日志请求调用者的完整类名。

contextName
cn
输出日志记录器上下文的名字。
d{pattern}
date{pattern}
d{pattern, timezone}
date{patterntimezone}

用来输出日志事件日期,日期转换词需要一个格式化字符串作为参数,格式化字符串语义与java.text.SimpleDateFormat相同。

转换格式结果
%d2006-10-20 14:06:49,812
%date2006-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

第二个参数可以指定时区,例如:%date{HH:mm:ss.SSS, Australia/Perth}。','作为参数分割符,HH:mm:ss,SSS会被翻译成HH:mm:ss和时区SSS。

F / file

输出发出日志请求的Java源文件文件名,一般生成文件信息比较慢,因此一般不使用这个转换词。

caller{depth} caller{depthStart..depthEnd} caller{depth, evaluator-1, ... evaluator-n} caller{depthStart..depthEnd, evaluator-1, ... evaluator-n}

输出生成日志事件的调用者位置信息,例如,%caller{2} 会打印如下信息:

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)

%caller{3} 会打印如下信息:

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)

同样可以使用范围指定符,例如, %caller{1..2} 会打印如下信息:

0    [main] DEBUG - logging statement
Caller+0   at mainPackage.sub.sample.Bar.createLoggingRequest(Bar.java:17)
L / line

输出发出日志请求的行号,由于生成行号信息比较慢,因此一般不使用这个转换词。

m / msg / message

输出与日志事件相关的应用提供的信息。

M / method

输出发出日志请求的方法名,由于生成方法名的比较慢,因此一般不使用这个转换词。

n

输出与平台独立的行分隔符,等价于"\n"或者"\r\n"。

p / le / level输出日志对象的级别。
r / relative输出应用程序启动到日志事件产生所用到的时间(毫秒)。
t / thread输出产生日志事件的线程名。
X{key:-defaultVal}
mdc{key:-defaultVal}

输出与产生日志事件线程相关的MDC(mapped diagnostic context)。如果mdc转换词后面花括号中有key,例如:%mdc{transactionId},那么与key 'transactionId'的值将会被输出,如果值为空,那么:-后的默认值将会被输出,如果没有默认值,则输出空字符串。

ex{depth}
exception{depth}
throwable{depth}

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

输出与日志事件相关的异常栈,默认所有异常栈都会被输出。throwable转换词支持如下选项:

  • short: 打印异常栈第一行。
  • full: 打印所有异常栈。
  • Any integer: 打印指定行数异常栈。

下面是一些示例:

转换格式结果
%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)
xEx{depth}
xException{depth}
xThrowable{depth}

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

与转换词%throwable相同,只不过会额外添加类所属包的信息。

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 exceptions.

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}

输出与属性名key相关的值,如何定义锚点以及变量作用域请参考:Chapter 3: Configuration

replace(p){r, t}

用't'替代p中匹配正则表达式r的内容,例如, "%replace(%msg){'\s', ''}" 会去除事件消息中包含的所有空格。

模式'p'可以是任意多个转换词,例如,"%replace(%logger %msg){'\.', '/'}"会替换日志事件日志记录器或者消息中所有的点为斜杠。

rEx{depth}
rootException{depth}

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

输出与日志事件香瓜的异常栈,示例如下:

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]

四、格式修饰符

通过格式修饰符可以改变数据域最小和最大宽度,格式修饰符位于百分号和转换词之间,默认格式是右调整,左调整可以使用(-)减号,下面是一些示例:

格式修饰符左调整最小宽度最大宽度备注
%20loggerfalse20none如果日志记录器名字长度小于20个字符,左边会添加空格补全。
%-20loggertrue20none如果日志记录器名字长度小于20个字符,右边会添加空格补全。
%.30loggerNAnone30如果日志记录器名字长度大于30个字符,从头开始截取。
%20.30loggerfalse2030如果日志记录器名字长度小于20个字符,左边会添加空格补全。如果日志记录器名字长度大于30个字符,从头开始截取。
%-20.30loggertrue2030如果日志记录器名字长度小于20个字符,右边会添加空格补全。如果日志记录器名字长度大于30个字符,从头开始截取。
%.-30loggerNAnone30如果日志记录器名字长度大于30个字符,从右边开始截取。

下面这张表是格式修饰符截取的例子,注意方括号不是日志输出的一部分,只用来分割日志输出的宽度。

格式修饰符日志记录器名结果
[%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]

本文来自:CSDN博客

感谢作者:CSDN博客

查看原文:(五)Logback中的Layout_logback layout_凌波漫步&的博客

965 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传