阅读Logback文档笔记--Logback的Configuration配置

要在项目中引入日志,需要一定的代价,据统计日志代码量将会占整个代码量的4%左右。因此我们需要一个工具管理这些日志声明。

对于Log4j.properties可以通过以下网址转化成logback.xml

http://logback.qos.ch/translator/

Logback如何查找配置文件:

  1. 在classpath中查找logback.groovy
  2. 如果不存在,则在classpath中查找logback-test.xml
  3. 如果不存在,继续查找logback.xml
  4. 如果不存在,则由jdk1.6中提出的service-provider loading facility 通过查找META-INF\services\ch.qos.logback.classic.spi.Configurator这个文件中定义的继承
    com.qos.logback.classic.spi.Configurator接口的配置实现类的全限定名
  5. 如果还不存在,logback则会使用基本的配置,将日志输出定向到控制台。

如果你使用maven构建项目,可以将logback-test.xml放在src/test/resources路径下,如此,该配置就只在test阶段会启用。将logback.xml放在src/main/resources中,则会随项目一起打包到正式环境使用。

快速启动(不明觉厉):将配置文件转化需要100毫秒的时间,可以通过使用以上第四步的方法来缩减这个时间。

我们来看看上面第5步的BasicConfigurator的源码

public class BasicConfigurator extends ContextAwareBase implements Configurator {

31

32      public BasicConfigurator() {

33      }

34

35      public void configure(LoggerContext lc) {

36          addInfo("Setting up default configuration.");

37

38          ConsoleAppender<ILoggingEvent> ca = new ConsoleAppender<ILoggingEvent>();

39          ca.setContext(lc);

40          ca.setName("console");

41          LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<ILoggingEvent>();

42          encoder.setContext(lc);

43

44

45          // same as

46          // PatternLayout layout = new PatternLayout();

47          // layout.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");

48          TTLLLayout layout = new TTLLLayout();

49

50          layout.setContext(lc);

51          layout.start();

52          encoder.setLayout(layout);

53

54          ca.setEncoder(encoder);

55          ca.start();

56

57          Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME);

58          rootLogger.addAppender(ca);

59      }

60  }

这个最小的配置为root logger绑定一个ConsoleAppender,输出则使用PatternLayoutEncoder将日志模板设置成

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n.

另外,root logger的默认级别是debug。

输出格式如下:

16:06:09.031 [main] INFO chapters.configuration.MyApp1 - Entering application. 16:06:09.046 [main] DEBUG chapters.configuration.Foo - Did it again! 16:06:09.046 [main] INFO chapters.configuration.MyApp1 - Exiting application.

下面我们来看个小例子

package manual.configuration;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public class MyApp1 {

final static Logger logger = LoggerFactory.getLogger(MyApp1.class);

public static void main(String[] args) {

logger.info("Entering application.");

Foo foo = new Foo();

foo.doIt();

logger.info("Exiting application.");

}

}

例子中我们使用slf4j的接口类,并没有使用直接导入logback的实现。事实上,我们也不需要让logback客户端声明式地依赖logback,因为slf4j会在抽象层采用可以使用的日志框架。这就为我们可以随时方便地切换日志框架提供了可能。

打印logback status message(logback上下文状态)的方法

方式一:

public static void main(String[] args) {

// assume SLF4J is bound to logback in the current environment

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

// print logback‘s internal status

StatusPrinter.print(lc);

...

}

方式二:cofiguration 的debug设置为true,但如果该配置文件有错将无法自动输出状态信息。

<configuration debug="true">

这种方式也相当于,注册了一个statusListener

<configuration>

<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

</configuration>

我们也可以通过jvm参数指定默认配置文件,注意:文件名必须以.xml或者.groovy结尾

java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1

自动重载配置:当配置文件更新时,自动重新加载

扫描时间间隔单位可以是:milliseconds, seconds, minutes or hours.,如不设置默认为1分钟检测一次。实际上扫描间隔,不单单取决于间隔时间,还取决于logger request的次数

<configuration scan="true" scanPeriod="30 seconds" >

...

</configuration>

允许记录产生错误时的堆栈状态,默认为false。虽然有用,但在错误频繁的系统中,性能消耗比较大

<configuration packagingData="true">

...

</configuration>

也可以通过代码实现

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

lc.setPackagingDataEnabled(true);

如果你想改写logback默认的配置加载机制,可以调用 JoranConfigurator.doConfigure(String arg0)重新配置

但是先要调用loggerContext.context的reset()方法清除之前的配置

public static void main(String[] args) {

// assume SLF4J is bound to logback in the current environment

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

try {

JoranConfigurator configurator = new JoranConfigurator();

configurator.setContext(context);

// Call context.reset() to clear any previous configuration, e.g. default

// configuration. For multi-step configuration, omit calling context.reset().

context.reset();

configurator.doConfigure(args[0]);

} catch (JoranException je) {

// StatusPrinter will handle this

}

StatusPrinter.printInCaseOfErrorsOrWarnings(context);

}

通过网页查看LoggerContext上下文信息:Logback将它的内部状态数据手机在StatusManager中,可以通过context获取。

可以在web.xml中引入以下servlet,然后就可以通过对应的url访问如下界面:

<servlet>

<servlet-name>ViewStatusMessages</servlet-name>

<servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>ViewStatusMessages</servlet-name>

<url-pattern>/lbClassicStatus</url-pattern>

</servlet-mapping>

设置日志状态监听器:注册一个状态监听器,可以方便管理logback的内部状态,在没有人工参与的情况下。

代码实现:

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

StatusManager statusManager = lc.getStatusManager();

OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener();

statusManager.add(onConsoleListener);

配置实现(推荐):状态监听器的声明应该在一开始就定义,否则无法收集到声明之前的状态操作

<configuration>

<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

... the rest of the configuration file

</configuration>

jvm参数实现:

java -Dlogback.statusListenerClass=ch.qos.logback.core.status.NopStatusListener ...

logback提供了一个状态监听器的实现

OnConsoleStatusListener:输出到控制台

OnErrorConsoleStatusListener:输出到错误控制台

NopStatusListener:丢弃状态信息

在某些情况下,为了释放logback带来的资源消耗,可以暂停logback context

LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();

loggerContext.stop();

在web应用中,以上功能页可以通过调用servletContextListener的contextDestroyed方法实现,原话如下:

In web-applications the above code could be invoked from within the contextDestroyed method
of ServletContextListener in order to stop logback-classic and release resources.

下面我们来说说Configuration文件的编写格式

这是一个基本的结构图

首先看看他的一些基本规范

  1. 对大小写敏感(建议采用全小写):虽然大小写不明感,但是开/闭标签需要大小写一致,第一个字母除外。
  2. logger通过<logger>标签定义,属性如下:
    1. name:必要,唯一标识一个Logger
    2. level:可选,不设置默认从父logger中继承,logger日志级别,可选值:TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF
    3. additivity:可选,默认为true,表示是否叠加祖宗logger的appender, appender代表一个日志输出地
    4. <appender-ref>:内部元素,至少包含一个,属性ref=“appender”的name。
  3. <root>:只提供一个level属性,因为name=ROOT,additity=false已经规定。

以下是一个例子:

<configuration>

<appender name="STDOUT"

class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

</pattern>

</encoder>

</appender>

<logger name="chapters.configuration" level="INFO" />

<logger name="chapters.configuration.Foo" level="DEBUG" />

<root level="DEBUG">

<appender-ref ref="STDOUT" />

</root>

</configuration>

下面我们再来看看怎么定义<appender>

需要注意是:logger默认的additity为true,代表同时向祖宗logger的appender输出,所以错误设置,可能导致重复的日志记录

如果有需要,这时候就需要声明additity=false

<configuration>

<appender name="FILE" class="ch.qos.logback.core.FileAppender">

<file>foo.log</file>

<encoder>

<pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>

</encoder>

</appender>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>%msg%n</pattern>

</encoder>

</appender>

<logger name="chapters.configuration.Foo"
additivity="false">

<appender-ref ref="FILE" />

</logger>

<root level="debug">

<appender-ref ref="STDOUT" />

</root>

</configuration>

设置context的name:目的是区别当有多个应用程序logging到同一个目的,如何区分来自哪个application

<configuration>

<contextName>myAppName</contextName>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>%d %contextName [%t] %level %logger{36} - %msg%n</pattern>

</encoder>

</appender>

<root level="debug">

<appender-ref ref="STDOUT" />

</root>

</configuration>

定义属性:可以通过定义属性,同一管理一些重复设置的值,获取方式类似于EL表达式,表达式之间可以嵌套。

<configuration>

<property name="USER_HOME" value="/home/sebastien" />

<appender name="FILE" class="ch.qos.logback.core.FileAppender">

<file>${USER_HOME}/myApp.log</file>

<encoder>

<pattern>%msg%n</pattern>

</encoder>

</appender>

<root level="debug">

<appender-ref ref="FILE" />

</root>

</configuration>

当然也可以通过jvm参数设置

java -DUSER_HOME="/home/sebastien" MyApp2

如果属性较多,也可以引入文件系统中单独的属性文件,或classpath路径下的文件

<configuration>

<!--文件系统-->

<property file="src/main/java/chapters/configuration/variables1.properties" />

<!--类路径-->

<property resource="resource1.properties" />

<appender name="FILE" class="ch.qos.logback.core.FileAppender">

<file>${USER_HOME}/myApp.log</file>

<encoder>

<pattern>%msg%n</pattern>

</encoder>

</appender>

<root level="debug">

<appender-ref ref="FILE" />

</root>

</configuration>

定义的属性的范围:

  1. LOCAL
  2. CONTEXT
  3. SYSTEM

<property scope="context" name="nodeId" value="firstNode" />

获取属性值的时候,也可以默认值的方式,当属性未定义,则采用默认值

${aName:-golden}

${id:-${userid}}

如果属性值使用过计算获得,也可以动态定义,实现PropertyDefiner接口的getPropertyValue()

<configuration>

<define name="rootLevel" class="a.class.implementing.PropertyDefiner">

<shape>round</shape>

<color>brown</color>

<size>24</size>

</define>

<root level="${rootLevel}"/>

</configuration>

logback也提供了两个简单的动态定义属性类

Implementation name Description
FileExistsPropertyDefiner Set the named variable to "true" if the file specified by path property exists, to
"false" otherwise.
ResourceExistsPropertyDefiner Set the named variable to "true" if the resource specified by the user is available
on the class path, to "false" otherwise.

当然,有时候我们也需要根据情况适当调整配置:需要注意的是,p("k")相当于property("k"),且当属性未定义,或null时,都同一返回空字符串。这样就可以减少对属性的判断操作

<configuration debug="true">

<if condition=‘property("HOSTNAME").contains("torino")‘>

<then>

<appender name="CON" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>%d %-5level %logger{35} - %msg %n</pattern>

</encoder>

</appender>

<root>

<appender-ref ref="CON" />

</root>

</then>

</if>

<appender name="FILE" class="ch.qos.logback.core.FileAppender">

<file>${randomOutputDir}/conditional.log</file>

<encoder>

<pattern>%d %-5level %logger{35} - %msg %n</pattern>

</encoder>

</appender>

<root level="ERROR">

<appender-ref ref="FILE" />

</root>

</configuration>

我们也可以从JNDI中获取属性值,as 代表属性引入后的名字

<configuration>

<insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />

<contextName>${appName}</contextName>

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>%d ${CONTEXT_NAME} %level %msg %logger{50}%n</pattern>

</encoder>

</appender>

<root level="DEBUG">

<appender-ref ref="CONSOLE" />

</root>

</configuration>

我们也可以将配置文件分片,然后引入,optional属性代表非必须

<configuration>

<include file="src/main/java/chapters/configuration/includedConfig.xml" optional=false/>

<root level="DEBUG">

<appender-ref ref="includedConsole" />

</root>

</configuration>

文件名:src/main/java/chapters/configuration/includedConfig.xml

<included>

<appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<pattern>"%d - %m%n"</pattern>

</encoder>

</appender>

</included>

引入路径也分为三种

  1. file system: <include file=
  2. classpath:<include resource=
  3. url:<include url=
时间: 2024-08-30 00:53:18

阅读Logback文档笔记--Logback的Configuration配置的相关文章

Emacs阅读chm文档

.title { text-align: center; margin-bottom: .2em } .subtitle { text-align: center; font-size: medium; font-weight: bold; margin-top: 0 } .todo { font-family: monospace; color: red } .done { font-family: monospace; color: green } .priority { font-fami

文档笔记说明

2015.4.18始-中级前端交流群日常问题集 注:以下文档基于“js中级前端开发群”日常讨论问题及相应解析进行相关记录. 起源:加入豪哥前端交流群之后,尤其从初级群升到中级群之后,感觉收获很多,成长也很快 .这都是跟规范“群规”引导下的良好的问答氛围以及热情交流的群员帮助是分不开的,使很多新人避免了不少弯路,但同时也暴露出一些问题,没有一份详细的笔记来记录我们的“成长过程”,比如日常讨论经常出现一些“经验性解答”和当前“前端流行趋势”的讨论,故因此想收集起来这些问题和讨论,作为日后所遇问题的查

jquery学习文档笔记

1.未见过的事件: focusin跟focus事件区别在于,他可以在父元素上检测子元素获取焦点的情况. focusout跟blur事件区别在于,他可以在父元素上检测子元素失去焦点的情况. 2.使用wrapAll方法 举例如下 原始代码: <div class="mm"><p>我们在公司</p></div><div class="mv">    <p>我们在公司</p>    <

&lt;&lt;ABP文档 - 框架&gt;&gt; 1.4 启动配置

文档目录 本节内容: 配置ABP 替换内置服务 配置模块 为一个模块创建配置 ABP在启动时,提供基础框架和模型来配置和模块化. 配置ABP 在预初始化事件中进行配置,示例: public class SimpleTaskSystemModule : AbpModule { public override void PreInitialize() { //为你的应用添加语言 Configuration.Localization.Languages.Add(new LanguageInfo("en

php实现word文档在线浏览功能,配置安装手记

一般类似oa或者crm等管理系统可能都会遇到需要再线查看word文档的功能,类似百度文库. 记得去年小组中的一个成员负责的项目就需要这个的功能,后面说是实现比较困难,就将就着用chm格式替代了.今天看到网上一遍文章<LINUX下面PHP文件转换>,介绍怎么样在linux下使用Openoffice 3 , Pdf2Swf tool , Jodconverter , FlexPaper,实现文档在线查看. 自己再ubuntu下进行的尝试安装,步骤如下: 因为ubuntu版本为10.0.4,open

管理员技术(五): 配置文档的访问权限、 配置附加权限、绑定到LDAP验证服务、配置LDAP家目录漫游

一.配置文档的访问权限 问题: 本例要求将文件 /etc/fstab 拷贝为 /var/tmp/fstab,并调整文件 /var/tmp/fstab的权限,满足以下要求: 1>  此文件的拥有者是 root       2> 此文件属于 root 组       3> 此文件对任何人都不可执行       4> 用户 natasha 能够对此文件执行读和写操作       5> 用户 harry 对此文件既不能读,也不能写       6> 所有其他用户(当前的和将来的

1230.2——iOS准备(阅读开发者文档时的笔记)

1.程序启动的过程    .在桌面找到相应的应用的图标 点击图标    .main函数 UIApplication类Every app has exactly one instance of UIApplication每个应用程序都只有一个UIApplication类的实例对象运行起来的应用程序就是一个UIApplication对象. UIApplicationMain创建UIAppication对象的一个单例对象(singleton) The role of your app’s applic

【sphinx】sphinxTrain文档笔记

如果需要训练的模型词汇量只有50-60个,而且你的所有测试词汇都包含在训练词汇中.那么训练基于单词的模型可能比基于音素的会更好. 基于单词的模型训练方法:1)定义的phoneset改为单词列表  2)词典中的map,是单词指向它本身 而如果训练基于音素的,要保证每个连接状态有充足的例子-5~10个的例子 训练之前,确定你要训练的模型需要的资源是否充足         半连续 semi-continue模型的训练----训练 :每个hmm模型要求5个状态,对10000个triphone的模型,要求

转载 - 读网上文档 - 笔记 - JS 编程最佳实践(Best Practice)

原文地址: 1). JavaScript Best Practices: http://www.w3schools.com/js/js_function_closures.asp 2). JavaScript Closures http://www.w3schools.com/js/js_function_closures.asp 3). JavaScript 严格模式 http://blog.csdn.net/supersky07/article/details/14129179 1. 关于全