文档章节

How to log in Spring with SLF4J and Logback

perfectspr
 perfectspr
发布于 2014/11/19 16:21
字数 1641
阅读 1089
收藏 9
点赞 0
评论 0

1. Introduction

1.1. Simple Logging Facade for Java(SL4J)

The  SLF4J serves as a simple facade or abstraction for various logging frameworks, such as java.util.logging, logback and log4j. SLF4J allows the end-user to plug in the desired logging framework at deployment time. Note that SLF4J-enabling your library/application implies the addition of only a single mandatory dependency, namely slf4j-api-x.x.x.jar.

1.2. Logback

From Logback’s official documentation:

“Logback is intended as a successor to the popular log4j project, picking up where log4j leaves off.

Logback’s architecture is sufficiently generic so as to apply under different circumstances. At present time, logback is divided into three modules, logback-core, logback-classic and logback-access.

The logback-core module lays the groundwork for the other two modules. The logback-classic module can be assimilated to a significantly improved version of log4j. Moreover, logback-classic natively implements the SLF4J API so that you can readily switch back and forth between logback and other logging frameworks such as log4j or java.util.logging (JUL).

The logback-access module integrates with Servlet containers, such as Tomcat and Jetty, to provide HTTP-access log functionality. Note that you could easily build your own module on top of logback-core.”

1.3.  Spring

Spring is using by default Jakarta Commons Logging, but in the blog post Logging Dependencies in Spring from Spring.io it says “if we could turn back the clock and start Spring now as a new project it would use a different logging dependency. Probably the first choice would be the Simple Logging Facade for Java (SLF4J)

2. Configuration

To use SLF4J with Spring you need to replace the commons-logging dependency with the SLF4J-JCL bridge. Once you have done that, then logging calls from within Spring will be translated into logging calls to the SLF4J API, so if other libraries in your application use that API, then you have a single place to configure and manage logging.

2.1. Spring

2.1.1. Exclude commons-logging

To switch off commons-logging, the commons-logging dependency mustn’t be present in the classpath at runtime. If you are using maven like me, you can simply exclude it from the spring-context artifact:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
    <exclusions>
       <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
       </exclusion>
    </exclusions>            
</dependency>


2.1.2. Required libraries

Because I am using LogBack, which implements SLF4J directly, you will need to depend on two libraries (jcl-over-slf4j and logback):

<!-- LogBack dependencies --> 
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>${logback.version}</version>
</dependency>
<dependency>                                    
    <groupId>org.slf4j</groupId>                
    <artifactId>jcl-over-slf4j</artifactId>     
    <version>${jcloverslf4j.version}</version>  
</dependency>

Note: You might also want to exclude the slf4j-api depedency from other external dependencies, besides Spring, to avoid having more than one version of that API on the classpath.

Code tip:
All dependencies required for the projects can be found on GitHub in the  pom.xml  file.

2.2. Logback

To configure Logback all you have to do is place the file logback.xml in the classpath.

2.1. logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <Pattern>.%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %n
            </Pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>TRACE</level>
        </filter>
    </appender>
      <appender name="dailyRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>c:/tmp/rest-demo.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover -->
            <FileNamePattern>rest-demo.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!-- keep 30 days' worth of history -->
            <maxHistory>30</maxHistory>            
        </rollingPolicy>
        <encoder>
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n</Pattern>
        </encoder>         
      </appender>
      <appender name="minuteRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- rollover every minute -->
            <FileNamePattern>c:/tmp/minutes/rest-demo-minute.%d{yyyy-MM-dd_HH-mm}.log</FileNamePattern>
            <!-- keep 30 minutes' worth of history -->
            <maxHistory>30</maxHistory>            
        </rollingPolicy>
        <encoder>
            <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</Pattern>
        </encoder>         
      </appender>      
    <logger name="org.codingpedia" additivity="false">
        <level value="DEBUG" />
        <appender-ref ref="dailyRollingFileAppender"/>
        <appender-ref ref="minuteRollingFileAppender"/>
        <appender-ref ref="consoleAppender" />
    </logger>
    <root>
        <level value="INFO" />
        <appender-ref ref="consoleAppender" />
    </root>
</configuration>

Logback uses appenders , which are components Logback delegates the task of writing logging events to. 

2.1.1. ConsoleAppender

As the name says it, this appender logs to the console. It has an encoder property - encoders are responsible for transforming an incoming event into a byte array and writing out the resulting byte array onto the appropriate OutputStream.

Note: Until logback version 0.9.19, many appenders relied on the Layout instances to control the format of log output. Since then encoders are the standard – encoders are assigned the type of ch.qos.logback.classic.encoder.PatternLayoutEncoder by default.

The PatternLayoutEncoder wraps instances of PatternLayout - this takes a logging event and returns a String, which you can customize by using PatternLayout’s conversion pattern.

From Logaback’s documentation:
The conversion pattern of PatternLayout is closely related to the conversion pattern of the printf() function in the C programming language. A conversion pattern is composed of literal text and format control expressions calledconversion specifiers. You are free to insert any literal text within the conversion pattern. Each conversion specifier starts with a percent sign ‘%’ and is followed by optional format modifiers, a conversion word and optional parameters between braces. The conversion word controls the data field to convert, e.g. logger name, level, date or thread name. The format modifiers control field width, padding, and left or right justification.”

You can find below a short explanation of the the conversion specifiers used in the example:

  • %d{HH:mm:ss.SSS} - Used to output the date of the logging event.

  • %thread- outputs the name of the thread that generated the logging event

  • %-5level - means the level of the logging event should be left justified to a width of five characters

  • %logger{36}  - outputs the name of the logger at the origin of the logging event. It takes an integer as parameter. This specifies the length the converter’s algorithm  will shorten the logger name to.

  • %msg – outputs the application-supplied message associated with the logging event.

  • %n – outputs the platform dependent line separator character or characters.

  • %relative – outputs the number of milliseconds elapsed since the start of the application until the creation of the logging event

The result looks something like this:

10:12:51.012 [qtp231719230-45] DEBUG o.c.d.r.util.LoggingResponseFilter

1

10:12:51.012 [qtp231719230-45] DEBUG o.c.d.r.util.LoggingResponseFilter

 or

102662 [qtp1790106082-48] DEBUG o.c.d.r.dao.PodcastDao.getPodcasts

1

102662 [qtp1790106082-48] DEBUG o.c.d.r.dao.PodcastDao.getPodcasts

2.1.2. RollingFileAppender

The RollingFileAppender extends FileAppender with the capability to rollover log files. In the example, the RollingFileAppender will log to a file named rest-demo.log file and, once a certain condition (every day and every minute) is met, change its logging target to another file.

There are two important sub-components that interact with RollingFileAppender. The first RollingFileAppender sub-component, namely RollingPolicy, is responsible for undertaking the actions required for a rollover. A second sub-component of RollingFileAppender, namely TriggeringPolicy, will determine if and exactly when rollover occurs. Thus, RollingPolicy is responsible for the what and TriggeringPolicy is responsible for the when.

To be of any use, a RollingFileAppender must have both a RollingPolicy and a TriggeringPolicy set up. However, if its  RollingPolicy also implements the TriggeringPolicy interface, then only the former needs to be specified explicitly – this is exactly the case in the example, where TimeBasedRollingPolicy is used. This assumes the responsibility for rollover as well as for the triggering of said rollover, by implementing both RollingPolicy and TriggeringPolicy interfaces.

In the example the rollover occurs daily and every minute.  For the “daily”-appender, the file property is set to rest-demo.log: During today (March 21th, 2014), logging will go to the file c:/temp/rest-demo.log. At midnight, the rest-demo.log will be renamed to c:/rest-demo.2014-03-21.log and a new c:/temp/rest-demo.log will be created and for the rest of March 22th logging output will be redirected to rest-demo.log.

Note:
The file property in 
RollingFileAppender (the parent of TimeBasedRollingPolicy) can be either set or omitted. By setting the file property of the containing FileAppender, you can decouple the location of the active log file and the location of the archived log files.

3. Integration in code

To use SLF4J in code is pretty easy – you just have to get a logger, and then on that logger you can log messages at the different logging levels (TRACE, DEBUG, INFO, WARN, ERROR).

For demonstration purposes I created a special logging filter LoggingResponseFilter (didn’t want the REST facade cluttered with logging code) in the REST content, that will log

  • input – the HTTP method used + the relative path called of the REST resource

  • output – a pretty print of the response entities in JSON format

package org.codingpedia.demo.rest.util;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoggingResponseFilter
        implements ContainerResponseFilter {
    private static final Logger logger = LoggerFactory.getLogger(LoggingResponseFilter.class);
    public void filter(ContainerRequestContext requestContext,
            ContainerResponseContext responseContext) throws IOException {
        String method = requestContext.getMethod();
        logger.debug("Requesting " + method + " for path " + requestContext.getUriInfo().getPath());
        Object entity = responseContext.getEntity();
        if (entity != null) {
            logger.debug("Response " + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(entity));
        }
    }
}

So you I am just getting the “LoggingResponseFilter ” logger  and on that, I will log messages at DEBUG level and upwards.

Well, that’s it! I would like to use this opportunity once again to thank the people who have developed and documented these wonderful frameworks. To name a few Dave Syer, Ceki Gülcü, Sébastien Pennec, Carl Harris . Thank you guys and keep up the good work!

4. Resources

4.1. Source code

4.1. Codingpedia

4.3. Web


本文转载自:http://www.codingpedia.org/ama/how-to-log-in-spring-with-slf4j-and-logback/#2_Configuration

共有 人打赏支持
perfectspr
粉丝 4
博文 42
码字总数 1198
作品 0
大连
技术主管
Java混乱的日志体系(logback)(转)

作为一名 Java 程序员,日常开发工作中肯定会接触日志系统,但是众多的框架,包括 Log4j、Log4j2、Logback、Slf4j、Apache Common logging 等等,引用的 maven 依赖众多,到底可以去掉哪些,...

easonjim ⋅ 2017/12/27 ⋅ 0

Java日志框架-logback的介绍及配置使用方法(纯Java工程)(转)

说明:内容估计有些旧,2011年的,但是大体意思应该没多大变化,最新的配置可以参考官方文档。 一、logback的介绍 Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块...

easonjim ⋅ 2017/11/07 ⋅ 0

slf4j 是怎么绑定具体的日志框架的

SLF4J 英文全称是 Simple Logging Facade for Java, 是一个门面(外观)接口或者说各种日志框架的抽象,比如 java.util.logging, logback, log4j 等;使用这货,我们可以不用关心具体的实现...

holysu ⋅ 05/13 ⋅ 0

Log4j 2.0在开发中的高级使用详解

log4j与slf4j、logback比较 而log4j slf4j logback就是目前主流的日志框架。但后两者效率高是第一个。推荐使用:slf4j 或者 logback(spring-boot默认日志实现) log4j是apache实现的一个开源日...

spinachgit ⋅ 04/22 ⋅ 0

Spring Boot中日志每日分割

问题 想使用Spring Boot中日志输出,这样以后遇到问题,就可以翻看日志数据,看看程序运行的过程,便于排查错误。 logback基础配置 logback-spring.xml application.properties 上面两步,主...

亚林瓜子 ⋅ 06/12 ⋅ 0

Spring Boot中Starter是什么

比如我们要在Spring Boot中引入Web MVC的支持时,我们通常会引入这个模块spring-boot-starter-web,而这个模块如果解压包出来会发现里面什么都没有,只定义了一些POM依赖。 经过研究,Start...

easonjim ⋅ 2017/09/30 ⋅ 0

SLF4J: Multiple bindings were found on the class path

众所周知,SLF4J是一个日志门面框架,它的作用是用于定义统一的日志接口,而具体的日志实现是由各个日志框架实现的,比如log4j,logback等。 问题 在使用SLF4J时,当class path同时包含了多个...

勇敢的飞石 ⋅ 05/17 ⋅ 0

Spring Boot日志集成实战

Spring Boot日志框架 Spring Boot支持Java Util Logging,Log4j2,Lockback作为日志框架,如果你使用starters启动器,Spring Boot将使用Logback作为默认日志框架。无论使用哪种日志框架,Sprin...

Java技术栈 ⋅ 06/08 ⋅ 0

log4j升级版日志框架logback的使用以及配置详解

一、logback的介绍   Logback是由log4j创始人设计的另一个开源日志组件,官方网站: http://logback.qos.ch。它当前分为下面下个模块:   logback-core:其它两个模块的基础模块   log...

java_龙 ⋅ 2016/09/28 ⋅ 0

解决log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader)

spring项目经常在启动tomcat时报如下警告信息: log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).log4j:WARN Please initialize the l......

Iceberg_XTY ⋅ 05/07 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

6.1 压缩打包介绍 6.2 gzip压缩工具 6.3 bzip2压缩工具 6.4 xz压缩工具

压缩打包介绍 使用压缩工具的好处: 使用压缩文件,不仅可以节省磁盘空间,而且在传输时还能节省网络宽带。 我们通常讲的家用宽带和机房宽带100M是有区别的: 机房宽带的上行和下行都是100M,...

Linux_老吴 ⋅ 15分钟前 ⋅ 0

SpringBoot热部署加持

概述 进行SpringBoot的Web开发过程中,我们很多时候经常需要重启Web服务器才能保证修改的 源代码文件、或者一些诸如xml的配置文件、以及一些静态文件生效,这样耗时又低效。所谓的热部署指的...

CodeSheep ⋅ 22分钟前 ⋅ 0

OSChina 周六乱弹 —— 假如你被熊困到树上

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @小小编辑:推荐歌曲《如果写不出好的和弦就该在洒满阳光的钢琴前一起吃布丁》 《如果写不出好的和弦就该在洒满阳光的钢琴前一起吃布丁》- 谢...

小小编辑 ⋅ 53分钟前 ⋅ 5

vbs 取文件大小 字节

dim namedim fs, s'name = Inputbox("姓名")'msgbox(name)set fs = wscript.createobject("scripting.filesystemobject") 'fs为FSO实例if (fs.folderexists("c:\temp"))......

vga ⋅ 今天 ⋅ 1

高并发之Nginx的限流

首先Nginx的版本号有要求,最低为1.11.5 如果低于这个版本,在Nginx的配置中 upstream web_app { server 到达Ip1:端口 max_conns=10; server 到达Ip2:端口 max_conns=10; } server { listen ...

算法之名 ⋅ 今天 ⋅ 0

Spring | IOC AOP 注解 简单使用

写在前面的话 很久没更新笔记了,有人会抱怨:小冯啊,你是不是在偷懒啊,没有学习了。老哥,真的冤枉:我觉得我自己很菜,还在努力学习呢,正在学习Vue.js做管理系统呢。即便这样,我还是不...

Wenyi_Feng ⋅ 今天 ⋅ 0

博客迁移到 https://www.jianshu.com/u/aa501451a235

博客迁移到 https://www.jianshu.com/u/aa501451a235 本博客不再更新

为为02 ⋅ 今天 ⋅ 0

win10怎么彻底关闭自动更新

win10自带的更新每天都很多,每一次下载都要占用大量网络,而且安装要等得时间也蛮久的。 工具/原料 Win10 方法/步骤 单击左下角开始菜单点击设置图标进入设置界面 在设置窗口中输入“服务”...

阿K1225 ⋅ 今天 ⋅ 0

Elasticsearch 6.3.0 SQL功能使用案例分享

The best elasticsearch highlevel java rest api-----bboss Elasticsearch 6.3.0 官方新推出的SQL检索插件非常不错,本文一个实际案例来介绍其使用方法。 1.代码中的sql检索 @Testpu...

bboss ⋅ 今天 ⋅ 0

informix数据库在linux中的安装以及用java/c/c++访问

一、安装前准备 安装JDK(略) 到IBM官网上下载informix软件:iif.12.10.FC9DE.linux-x86_64.tar放在某个大家都可以访问的目录比如:/mypkg,并解压到该目录下。 我也放到了百度云和天翼云上...

wangxuwei ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部