SpringBoot+log4j日志管理

关于日志

Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J, Log4J2和Logback。每种Logger都可以通过配置使用控制台或者文件输出日志内容。Springboot帮我们整合了这些最常用的日志框架,只需要简单的按照约定配置即可在项目中很快的配置日志相关。

常用的日志框架(也称为日志门面库)有apache commons logging和slf4j,常用的日志系统(也称为日志实现库)有log4j,log4j2,JUL,logback等。
日志框作为门面,日志系统要搭配日志框架来使用,日志框架调用日志系统,在分布式中,还会有专门的分布式日志收集系统,在集群的多个分布式机器中将日志收集并整理的框架有:apache flume,facebook scribe等。

早期Java项目使用最多的日志门面是commons-logging,log4j是推荐的日志实现库,需要的jar包为commons-logging.jar、log4j.jar。

springboot中默认使用的也是commons logging+logback的组合,我们需要排除并且导入log4j的jar包

现今java项目推荐的日志门面是slf4j,log4j仍是推荐的日志实现库,需要的jar包为slf4j-api.jar、slf4j-log4j12.jar、log4j.jar,其中绑定包slf4j-log4j12.jar指定了要使用的实现库。

commons-logging存在osgi问题,但早期项目多使用其作为日志门面,为保证兼容仍使用其作为日志门面,但通过slf4j的静态绑定技术来加载具体的日志库log4j,需要的jar包为commons-logging.jar、jcl-over-slf4j.jar、slf4j-api.jar、slf4j-log4j12.jar、log4j.jar,其中jcl-over-slf4j.jar将日志的接口重定向到slf4j。

slf4j+log4j组合使用模式:

  1. slf4j-api-1.5.11.jar
  2. slf4j-log4j12-1.5.11.jar
  3. log4j-1.2.15.jar
  4. log4j.properties(也可以是 log4j.xml)

JCL+Log4J组合使用模式(即commons-logging+log4j):

  1. commons-logging-1.1.jar
  2. log4j-1.2.15.jar
  3. log4j.properties

不同的获取logger的方式

log4j:(单独使用)
import org.apache.log4j.Logger;
Logger logger= Logger.getLogger(xx.class);

slf4j+log4j:(借助LogFactory)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger logger = LoggerFactory.getLogger(xx.class);

jcl+log4j:(借助LogFactory)
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
private static Log log = LogFactory.getLog(xx.class);

可以参考:https://blog.csdn.net/xydds/article/details/51606010 根据使用场景的不同我们采用不同的日志框架+日志系统。

总的来说,slf4j与commons-logging只是一个日志门面,实际还是要依赖真正的日志库log4j,虽然slf4j和commons-loggins自带了日志库,但是毕竟log4j才是日志系统(主要功能)。

现今java项目推荐的日志门面是slf4j,log4j仍是推荐的日志实现库,需要的jar包为slf4j-api.jar、slf4j-log4j12.jar、log4j.jar,其中绑定包slf4j-log4j12.jar指定了要使用的实现库。
commons-logging存在osgi问题,但早期项目多使用其作为日志门面,为保证兼容仍使用其作为日志门面,但通过slf4j的静态绑定技术来加载具体的日志库log4j,需要的jar包为commons-logging.jar、jcl-over-slf4j.jar、slf4j-api.jar、slf4j-log4j12.jar、log4j.jar,其中jcl-over-slf4j.jar将日志的接口重定向到slf4j。

在日志系统中,主要分为三个配置,appenders,layouts和loggers,一般我们做项目时日志记录的历程是这样的,loggers负责记录事假,将事件记录到后转发给合适的appenders,然后appenders使用layouts将事件记录进行格式化,并将其发送给控制台,文件或其他目录位置。

在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用的日志操作类外, Apache 为我们提供了一个强有力的日志操作包 -Log4j 。  
Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j ,我们可以控制日志信息输送的目的地是控制台、文件、 GUI 组件、甚至是套接口(socket)服务器、 NT 的事件记录器、 UNIX Syslog 守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就 是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。  
此外,通过 Log4j 其他语言接口,您可以在 C 、 C+ + 、 .Net 、 PL/SQL 程序中使用 Log4j ,其语法和用法与在 Java 程序中一样,使得多语言分布式系统得到一个统一一致的日志组件模块。而且,通 过使用各种第三方扩展,您可以很方便地将 Log4j 集成到 J2EE 、 JINI 甚至是 SNMP 应用中。

logo

核心理解为:一个logger可以对应多个appender,一个appender只能对应一个layout。
因为logger捕抓到消息后,可以在各种地方输出(控制台,文件,硬盘甚至数据库),一个输出只能对应一种输出格式。

1.appenders负责输出到目标位置,日志输出目的地,负责日志的输出 (输出到什么 地方)
2.layouts负责日志信息的格式化,以什么形式展现
3.loggers负责捕抓事件给相应的appenders,如何处理日志

Log4j提供的layout有以下几种(一般在工作中常用)
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

常用的集中appender有:(一般在工作中常用,也可以支持自定义appender)
org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender((文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

例如:
默认的日志输出如下:
2016-04-13 08:23:50.120 INFO 37397 — [ main] org.hibernate.Version : HHH000412: Hibernate Core {4.3.11.Final}

输出内容元素具体如下:(包括这些)

时间日期 — 精确到毫秒
日志级别 — ERROR, WARN, INFO, DEBUG or TRACE
进程ID
分隔符 — — 标识实际日志的开始
线程名 — 方括号括起来(可能会截断控制台输出)
Logger名 — 通常使用源代码的类名
日志内容

级别

在Spring Boot中默认配置了ERROR、WARN和INFO级别的日志输出到控制台。

这里要说明一下日志的级别:(共分为5级),级别也就是反映出一种status的意思,我们根据关键字可以看出程序运行后记录的状态,看这个级别参数,知道是错误,警告还是正确运行。

level为logger服务,用来定义日志的级别,他的值可以是: OFF(关闭)FATAL(致命的) ERROR(错误)WARN(警告) INFO(信息)DEBUG (调试) ALL(所有),输出日志的策略由此Level决定,例如:如果logger的Level设置为INFO,那么系统只输出INFO以及以上(WARN、ERROR、FATAL)信息。如果当前logger没有设定Level,那么它在输出日志时采用的策略是:它会使用它继承的Logger的Level作为它自己的Level来处理。如果它的上级也没有设置Level,那么就找上上级,几次类推,直到root为止,(root的Level是不能设为空的,所以最终一定会找到一个Level)。默认root的Level是INFO,其他logger的Level默认都是null,需要手动指定。

【level】日志输出级别(由小到大,级别最高为DEBUG)
    FATAL 0 
    ERROR 3 严重错误
    WARN  4 一般警告
    INFO  6 一般显示信息
    DEBUG 7 程序调试信息

可以设置级别: debug>info>error
debug :显示 debug 、 info 、 error
info :显示 info 、 error
error :只 error
也就是说只显示比大于等于当前级别的信息

如果我们不指定appenders输出到哪个文件,那么springboot是默认将信息输入到控制台的,ERROR是产生严重错误的级别,这个在我们产生错误导致程序不运行时显示的,WARN则是警告的情况,INFO则是正常信息的输出,程序正常运行。
我们可以通过两种方式切换至DEBUG级别:

在运行命令后加入–debug标志,如:$ java -jar myapp.jar –debug
在application.properties中配置debug=true,该属性置为true的时候,核心Logger(包含嵌入式容器、hibernate、spring)会输出更多内容,但是你自己应用的日志并不会输出为DEBUG级别。

这是springboot启动的三种方式:
第一种是cmd到项目目录然后命令行mvn spring-boot:run启动项目,

第二种是运行Application.java入口类方法,

第三种是使用mvn install 生成jar后运行,先到项目根目录
mvn install
cd target
java -jar xxxx.jar

上诉改debug也是通过在项目目录下输入指令来设置debug开启。。。

在Spring Boot中只需要在application.properties文件中进行配置完成日志记录的级别控制。
配置格式:logging.level.=LEVEL
logging.level:日志级别控制前缀,
为包名或Logger名
LEVEL:选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF

举例:
logging.level.com.didispace=DEBUG:com.didispace包下所有class以DEBUG级别输出
logging.level.root=WARN:root日志以WARN级别输出

其中, level 是日志记录的优先级,分为 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 ALL 或者您定义的级别。 Log4j 建议只使用四个级别 ,优先级从高到低分别是 ERROR 、 WARN 、 INFO 、 DEBUG 。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定 义了 INFO 级别,则应用程序中所有 DEBUG 级别的日志信息将不被打印出来 。

控制台输出

控制台选项
Threshold=DEBUG:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
Target=System.err:默认情况下是:System.out,指定输出控制台
FileAppender 选项
Threshold=DEBUF:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
RollingFileAppender 选项
Threshold=DEBUG:指定日志消息的输出最低层次。
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
File=mylog.txt:指定消息输出到mylog.txt文件。
Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。
MaxBackupIndex=2:指定可以产生的滚动文件的最大数。

文件输出

我们日常工作中经常要进行日志记录,并输出到响应位置的文件夹,甚至是mongoDB数据库(文件储存数据库)中,用于存放数据,我们要怎么用springboot内集成的框架来完成日志记录呢?

Spring Boot默认配置只会输出到控制台,并不会记录到文件中,但是我们通常生产环境使用时都需要以文件方式记录。

若要增加文件输出,需要在application.properties中配置logging.file或logging.path属性。

logging.file,设置文件,可以是绝对路径,也可以是相对路径。如:logging.file=my.log
logging.path,设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:logging.path=/var/log

日志文件会在10Mb大小的时候被截断,产生新的日志文件,默认级别为:ERROR、WARN、INFO
也就是说每产生一个10mb大小的日志就会新建一个新的日志用于记录。

自定义输出日志的格式

在Spring Boot中可以通过在application.properties配置如下参数控制输出格式:

logging.pattern.console:定义输出到控制台的样式(不支持JDK Logger)
logging.pattern.file:定义输出到文件的样式(不支持JDK Logger)

一般来说是在日志的自定义文件中配置的:

如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:
日志信息格式中几个符号所代表的含义:
-X号: X信息输出时左对齐;
%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%r: 输出自应用启动到输出该log信息耗费的毫秒数
%c: 输出日志信息所属的类目,通常就是所在类的全名
%t: 输出产生该日志事件的线程名
%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main (TestLog4.Java:10)
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像Java servlets这样的多客户多线程的应用中。
%%: 输出一个”%”字符
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信息
%n: 输出一个回车换行符,Windows平台为”\r\n”,Unix平台为”\n”输出日志信息换行
可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
1)%20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,”-“号指定左对齐。
3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
4)%20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边较远输出的字符截掉。

比如:%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n 的格式意思就是说:

时间{指定时间格式} (%p就是表INFO) 所在类(%c{1}只表示类名不是全限定名):显示调用logger的代码行 - 指定消息及回车(一般最后都会加一个%n)

具体规范参考:https://blog.csdn.net/reserved_person/article/details/52849505
http://logging.apache.org/

自定义日志文件配置

由于日志服务一般都在ApplicationContext创建前就初始化了,它并不是必须通过Spring的配置文件控制。因此通过系统属性和传统的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。

根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:

Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
Log4j2:log4j2-spring.xml, log4j2.xml
JUL (Java Util Logging):logging.properties

Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml)

讲讲springboot+log4j

在POM中引入:

<!-- 如果要使用Log4j来记录,要先把springboot默认的logback给排除掉
本身 spring-boot-starter就是包含在spring-boot-starter-web中的,我们
要把它重新声明出来去排除spring-boot-starter-logging(默认的Commons Logging日志框架)
改用SLF4j日志框架来记录-->
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion> 
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 引入log4j的相关jar包 -->
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-log4j</artifactId>
      <version>1.3.8.RELEASE</version>
</dependency>

新建log4j.properties文件,是log4j的自定义配置文件

例:
//root是控制整个工程的日志,rootLogger就是根记录器级别,配置根Logger

// 此句为将等级为INFO的日志信息输出到stdout和file这两个目的地,
// console和file的定义在下面的代码,可以任意起名。
// 等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,
// 如果配置OFF则不打出任何信息,如果配置为INFO这样只显示INFO, WARN, ERROR的log信息,
// 而DEBUG信息不会被显示,具体讲解可参照第三部分定义配置文件中的logger。
// 弃用:log4j.rootCategory=[level],appenderName1,appenderName2...
// 改用:log4j.rootLogger = [ level ] , appenderName1 , appenderName2 , …
// 级别后面写的就是各appender的名称
// 需要分别配置

//但是根据最新版本的lig4j来看,log4j.rootCategory仿佛已经被弃用了,取而代之的是rootLogger
//这个类拓展了Category这个类,即生成Category对象时同样也生成一个LOgger,所以,建议用rootLogger
//log4j.rootCategory=INFO, console, file
log4j.rootLogger=INFO, console, file

// 控制台输出
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

// root日志输出
// 输出到logs/all.log文件中
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.file=D:\\logs\\all.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

// 出来上述的全局输出以外,还有工作中常用的分类输出
// 即可以定义一个具体的包的日志输出
// 假设在com.mybatis包下设置日志输出
//如果是rootCategory,则是控制整个工程
log4j.category.com.mybatis=DEBUG,didifile

log4j.appender.didifile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.didifile.file=D:\\logs\\my.log
log4j.appender.didifile.DatePattern='.'yyyy-MM-dd
log4j.appender.didifile.layout=org.apache.log4j.PatternLayout
log4j.appender.didifile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n

// 除了对包分类,还可以针对级别进行分类
// 比如发生了ERROR或者WARN可以输出到不同的文件中
//这个算是专门输出异常的文件
log4j.logger.error=errorfile
// error日志输出
log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorfile.file=D:\\logs\\error.log
log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd
log4j.appender.errorfile.Threshold = ERROR  ## 输出ERROR级别以上的日志!!
log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout
log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n

下面是一段log4j官方对于logger与category的区别:
原话是:
public class Categoryextends java.lang.Objectimplements AppenderAttachableThis class has been deprecated and replaced by the Logger subclass. It will be kept around to preserve backward compatibility until mid 2003.
Logger is a subclass of Category, i.e. it extends Category. In other words, a logger is a category. Thus, all operations that can be performed on a category can be performed on a logger. Internally, whenever log4j is asked to produce a Category object, it will instead produce a Logger object. Log4j 1.2 will never produce Category objects but only Logger instances. In order to preserve backward compatibility, methods that previously accepted category objects still continue to accept category objects.
For example, the following are all legal and will work as expected.
// Deprecated form: Category cat = Category.getInstance(“foo.bar”) // Preferred form for retrieving loggers: Logger logger = Logger.getLogger(“foo.bar”) The first form is deprecated and should be avoided.
There is absolutely no need for new client code to use or refer to the Category class. Whenever possible, please avoid referring to it or using it.
See the short manual for an introduction on this class.
See the document entitled preparing for log4j 1.3 for a more detailed discussion.

Author:
Ceki Gülcü, Anders Kristensen

足以解释这个问题了,logger代替了category这个类的功能,并且比其更加强大和好用。
//弃用形式:Category cat = Category.getInstance(“foo.bar”)//用于检索记录器的首选表单:Logger logger = Logger.getLogger(“foo.bar”)第一种形式已被弃用,应该避免。
绝对不需要新的客户端代码来使用或引用Category类。只要有可能,请避免提及或使用它。

下面我们再举一个LOG4J日志配置的例子,将这个日志同时在控制台,文件,回滚文件,发送日志邮件,输出到数据库日志表并且自定义标签等全套功能配置:

LOG4J 的配置之简单使它遍及于越来越多的应用中了: Log4J 配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。择其一二使用就够用了,

//设置级别和多个目的地
log4j.rootLogger=DEBUG,CONSOLE,A1,im
log4j.addivity.org.apache=true

//应用于控制台

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
//log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t//[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n

// 应用于文件

log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
// Use this layout for LogFactor 5 analysis

// 应用于文件回滚

log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log // 文件位置 , 也可以用变量 ${java.home} 、 rolling.log
log4j.appender.ROLLING_FILE.Append=true //true: 添加 false: 覆盖
log4j.appender.ROLLING_FILE.MaxFileSize=10KB // 文件最大尺寸
log4j.appender.ROLLING_FILE.MaxBackupIndex=1 // 备份数
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
// 应用于 socket
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true

// Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n

// Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000

// 发送日志给邮件

log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
www.wuset.com “>log4j.appender.MAIL.From=web@www.wuset.com
log4j.appender.MAIL.SMTPHost=www.wusetu.com
log4j.appender.MAIL.Subject=Log4J Message
www.wusetu.com “>log4j.appender.MAIL.To=web@www.wusetu.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

// 用于数据库
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=294823013
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (‘[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n’)
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH’.log4j’
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout

// 自定义 Appender

log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender

log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net

log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

在代码中使用Logger

以上说了那么多的日志配置,那么当我们配置好后,如何去使用呢?

  1. 得到记录器
    使用 Log4j ,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:
    public static Logger getLogger( String name)
    通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。 Name 一般取本类的名字,比如:
    static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

这里注意,看你需要的日志框架是什么来确定你获取Logger对象的方式:

// slf4j接口使用
// getLogger内调用slf4j-log4j.jar的StaticLoggerBinder类的getLogger,获取对应的log4j
private static final Logger logger = LoggerFactory.getLogger(LogTest.class);

// commons-logging接口使用
// 与slf4j基本一样,一个用Logger,一个用Log
private static final Log logger = LoggerFactory.getLogger(LogTest.class);

  

  1. 读取配置文件
    当获得了日志记录器之后,第二步将配置 Log4j 环境,其语法为:
    BasicConfigurator.configure () : 自动快速地使用缺省 Log4j 环境。
    PropertyConfigurator.configure ( String configFilename) :读取使用 Java 的特性文件编写的配置文件。
    DOMConfigurator.configure ( String filename ) :读取 XML 形式的配置文件。    
  2. 插入记录信息(格式化日志信息)
    当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:
    Logger.debug ( Object message ) ;
    Logger.info ( Object message ) ;
    Logger.warn ( Object message ) ;
    Logger.error ( Object message ) ;

例如:

//可以作为基类logger,需要的类可以直接继承
//似乎只需要声明其Logger对象就可以使用了。。。
public abstract class HelloDao {  
    private static Logger logger = Logger.getLogger(HelloDao.class);   
    public static void main(String[] args) {  
        // 记录debug级别的信息  
        logger.debug("This is debug message from Dao.");  
        // 记录info级别的信息  
        logger.info("This is info message from Dao.");  
        // 记录error级别的信息  
        logger.error("This is error message from Dao.");  
    }  
}

如果这个类作为基类,如J2EE中的BaseDao、BaseAction、BaseService等等,则我们可以将各层的日志信息分类输出到各个文件。

为了提高效率,我们可以在写日志前增加判断:

// 记录debug级别的信息  
if (logger.isDebugEnabled()) {  
    logger.debug("This is debug message from Dao.");  
}    
// 记录info级别的信息  
if (logger.isInfoEnabled()) {  
    logger.info("This is info message from Dao.");  
}  
// 记录error级别的信息  
logger.error("This is error message from Dao.");  

具体完整的配置可以参考:https://blog.csdn.net/anlina_1984/article/details/5313023
http://www.iteye.com/topic/378077

Spring Boot中对log4j进行多环境不同日志级别的控制

根据开发-测试-生产阶段的多环境log配置,SpringBoot也为此量身打造了基于多环境的级别控制

开发-测试-生产环境的级别控制

创建多环境配置文件
application-dev.properties:开发环境
application-test.properties:测试环境
application-prod.properties:生产环境
application.properties中添加属性:spring.profiles.active=dev(默认激活application-dev.properties配置)
application-dev.properties和application-test.properties配置文件中添加日志级别定义:logging.level.com.didispace=DEBUG
application-prod.properties配置文件中添加日志级别定义:logging.level.com.didispace=INFO

通过上面的定义,根据logging.level.com.didispace在不同环境的配置文件中定义了不同的级别,但是我们已经把日志交给了log4j管理,看看我们log4j.properties中对com.didispace包下的日志定义是这样的,固定定义了DEBUG级别,并输出到名为didifile定义的appender中。

// LOG4J配置
log4j.category.com.didispace=DEBUG, didifile   

那么,要如何动态的改变这个DEBUG级别呢?用到参数调用,用SPEL表达式来实现动态替换

// 动态LOG4J配置
log4j.category.com.didispace=${logging.level.com.didispace}, didifile 

对于不同环境的使用人员也不需要改变代码或打包文件,只需要通过执行命令中参加参数即可,比如我想采用生产环境的级别,那么我可以这样运行应用:更改对应环境配置文件即可,而不是去大费周章的修改代码了。

java -jar xxx.jar --spring.profiles.active=prod

Springboot使用slf4j+logback

我们添加spring-boot-starter-web这个包后,spring-boot-starter-web依赖spring-boot-starter,而spring-boot-starter其内部有一个jar包是spring-boot-starter-logging包含的就是slf4j-api.jar和logback-core.jar。

所以说我们若决定用slf4j+logback的组合,那么就添加这个spring-boot-starter-web包即可。

logo

我们在日志冲突中若决定使用其他日志框架或其他日志系统的时候,只需要更改jar包即可,若是我们想采用log4j的话,那我们就需要把这个spring-boot-starter-logging给exclusion掉才能使用。
比如我们要使用slf4j+log4j的组合的话,那么要去掉spring-boot-starter-logging,添加spring-boot-starter-log4j,里面包含了slf4j-api+log4j的相关jar包。

无论从设计上还是实现上,Logback相对log4j而言有了相对多的改进。不过尽管难以一一细数,这里还是列举部分理由为什么选择logback而不是log4j。牢记logback与log4j在概念上面是很相似的,它们都是有同一群开发者建立。所以如果你已经对log4j很熟悉,你也可以很快上手logback。如果你喜欢使用log4j,你也许会迷上使用logback。

基于我们先前在log4j上的工作,logback 重写了内部的实现,在某些特定的场景上面,甚至可以比之前的速度快上10倍。在保证logback的组件更加快速的同时,同时所需的内存更加少。

Logback 历经了几年,数不清小时数的测试。尽管log4j也是测试过的,但是Logback的测试更加充分,跟log4j不在同一个级别。我们认为,这正是人们选择Logback而不是log4j的最重要的原因。人们都希望即使在恶劣的条件下,你的日记框架依然稳定而可靠。

所以这才是我们考虑用springboot原生集成的WEB开发包spring-boot-starter-web,里面就天然集成了slf4j+logback

日志记录相关依赖,首选Spring-Boot”原生态”的logback,也就是说我们在实际开发中,现在直接使用spring-boot-starter-web自带的slf4j+logback即可。

Logback是由 log4j创始人设计的又一个开源日志组件

logback当前分成三个模块:
logback-core
logback- classic
logback-access

logback-core是其它两个模块的基础模块

logback-classic 非常自然的实现了SLF4J,logback-classic 包下包括了logback-core+slf4j,我们不用额外导入。

logback-classic中的登陆类自然的实现了SLF4J。当你使用 logback-classic作为底层实现时,涉及到LF4J日记系统的问题你完全不需要考虑。更进一步来说,由于 logback-classic强烈建议使用SLF4J作为客户端日记系统实现,如果需要切换到log4j或者其他,你只需要替换一个jar包即可,不需要去改变那些通过SLF4J API 实现的代码。这可以大大减少更换日记系统的工作量。

关于logback的配置

使用XML配置文件或者Groovy(Gradle区别于maven所建工程,Gradle基于Groovy语言,而maven基于xml)

配置logback的传统方法是通过XML文件。在文档中,大部分例子都是是用XML语法。但是,对于logback版本0.9.22,通过Groovy编写的配置文件也得到支持。相比于XML,Groovy风格的配置文件更加直观,连贯和简短的语法。

现在, 已经有一个工具自动把logback.xml文件迁移至logback.groovy。

若是我们要使用groovy构造工程的话,要在eclipse对应版本上安装groovy的集成开发环境,以为这是和maven类似的第三方集成库工程系统。

这些就不明说了,关于如何构建groovy工程,在专门的文章中有阐述。

不过这里不能像log4j那样直接使用properties文件来配置,我觉得有点麻烦。。。

先来看看logback中的日志配置与log4j又有那些不一样

如果配置文件 logback-test.xml 和 logback.xml 都不存在,那么 logback 默认地会调用BasicConfigurator ,创建一个最小化配置。最小化配置由一个关联到根 logger 的ConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 的 PatternLayoutEncoder 进行格式化。root logger 默认级别是 DEBUG。

在springboot中默认查找logback.xml和logback-spring.xml文件。

logback.xml配置如下:

<configuration>      
    <!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索引【从数字0开始递增】,,, -->      
    <!-- appender是configuration的子节点,是负责写日志的组件。 -->  
    <!-- ConsoleAppender:把日志输出到控制台 -->  
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">      
        <encoder>      
            <pattern>%d %p (%file:%line\)- %m%n</pattern>    
            <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->  
            <charset>UTF-8</charset>     
        </encoder>      
    </appender>      
    <!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
    <!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是sys.log -->  
    <!--             2.如果日期没有发生变化,但是当前日志的文件大小超过1KB时,对当前日志进行分割 重命名-->  
    <appender name="syslog"      
        class="ch.qos.logback.core.rolling.RollingFileAppender">      
        <File>log/sys.log</File>      
        <!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->  
        <!-- TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->  
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">      
            <!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->  
            <!-- 文件名:log/sys.2017-12-05.0.log -->  
            <fileNamePattern>log/sys.%d.%i.log</fileNamePattern>   
            <!-- 每产生一个日志文件,该日志文件的保存期限为30天 -->   
            <maxHistory>30</maxHistory>     
            <timeBasedFileNamingAndTriggeringPolicy  class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">      
                <!-- maxFileSize:这是活动文件的大小,默认值是10MB,本篇设置为1KB,只是为了演示 -->    
                <maxFileSize>1KB</maxFileSize>      
            </timeBasedFileNamingAndTriggeringPolicy>      
        </rollingPolicy>      
        <encoder>      
            <!-- pattern节点,用来设置日志的输入格式 -->  
            <pattern>      
                %d %p (%file:%line\)- %m%n    
            </pattern>      
            <!-- 记录日志的编码 -->  
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->     
        </encoder>      
    </appender>      
    <!-- 控制台输出日志级别 -->  
    <root level="info">      
        <appender-ref ref="STDOUT" />      
    </root>      
    <!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->  
    <!-- com.appley为根包,也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->  
    <!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE  -->  
    <logger name="com.appleyk" level="DEBUG">      
        <appender-ref ref="syslog" />      
    </logger>      
</configuration> 

可以看出,logback在configuration标签中进行配置,包含3个最主要的子标签appender,logger和root
可以这样描述配置文件的基本结构:以开头,后面有零个或多个元素,有零个或多个元素,有最多一个元素。

1.根节点,包含下面三个属性:
-scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
-scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
-debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

例如:

<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
  <!--其他配置省略--> 
</configuration>

2.子节点

-:用来设置上下文名称,每个logger都关联到logger上下文,默认上下文名称为default。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
其实就是用于标记这个logback配置文件,作为一个全局名称来使用

myAppName

-子节点:用来定义变量值,它有两个属性name和value,通过定义的值会被插入到logger上下文中,可以使“${}”来使用变量。
就是自定义配置参数的意思,用户可以通过这个xml文件来修改参数。
name: 变量的名称
value: 的值时变量定义的值

例如:

<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
 <property name="APP_Name" value="myAppName" /> 
 <contextName>${APP_Name}</contextName> 
 <!--其他配置省略--> 
</configuration>

-子节点:获取时间戳字符串,他有两个属性key和datePattern
key: 标识此 的名字;
datePattern: 设置将当前时间(解析配置文件的时间)转换为字符串的模式,遵循java.txt.SimpleDateFormat的格式。
例如:

<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
 <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/> 
 <contextName>${bySecond}</contextName> 
 <!-- 其他配置省略--> 
</configuration>

-主要子节点:负责写日志的组件,它有两个必要属性name和class。name指定appender名称,class指定appender的全限定名

(1)ConsoleAppender 把日志输出到控制台,有以下子节点:

:对日志进行格式化。(具体参数稍后讲解 )

:字符串System.out(默认)或者System.err(区别不多说了)

 <configuration> 
      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
      <encoder> 
        <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern> 
      </encoder> 
      </appender> 
<!--root用于指定级别 ref指向对应的appender的name属性值-->
      <root level="DEBUG"> 
        <appender-ref ref="STDOUT" /> 
      </root> 
 </configuration>

上述配置表示把>=DEBUG级别的日志都输出到控制台

(2)FileAppender:把日志添加到文件,有以下子节点:
 :被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
      :如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。
      :对记录事件进行格式化。(具体参数稍后讲解 )
      :如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认是 false。
例如:

<configuration> 
  <appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
     <file>testFile.log</file> 
     <append>true</append> 
     <encoder> 
       <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
     </encoder> 
  </appender> 
    <!-- DEBUG以上的级别都会被输出 ref指向对应的appender的name属性值-->
  <root level="DEBUG"> 
      <appender-ref ref="FILE" /> 
  </root> 
</configuration>

上述配置表示把>=DEBUG级别的日志都输出到testFile.log

(3)RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。有以下子节点:

:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。

:当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名。属性class定义具体的滚动策略类
class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。有以下子节点:
:必要节点,包含文件名及“%d”转换符,“%d”可以包含一个java.text.SimpleDateFormat指定的时间格式,如:%d{yyyy-MM}。
如果直接使用 %d,默认格式是 yyyy-MM-dd。RollingFileAppender的file字节点可有可无,通过设置file,可以为活动文件和归档文件指定不同位置,当前日志总是记录到file指定的文件(活动文件),活动文件的名字不会改变;
如果没设置file,活动文件的名字会根据fileNamePattern 的值,每隔一段时间改变一次。“/”或者“\”会被当做目录分隔符。
:
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每个月滚动,且是6,则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除。

class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”: 查看当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动。只有一个节点:
:这是活动文件的大小,默认值是10MB。
:当为true时,不支持FixedWindowRollingPolicy。支持TimeBasedRollingPolicy,但是有两个限制,1不支持也不允许文件压缩,2不能设置file属性,必须留空。

: 告知 RollingFileAppender 合适激活滚动。
class=”ch.qos.logback.core.rolling.FixedWindowRollingPolicy” 根据固定窗口算法重命名文件的滚动策略。有以下子节点:
:窗口索引最小值
:窗口索引最大值,当用户指定的窗口过大时,会自动将窗口设置为12。
:必须包含“%i”例如,假设最小值和最大值分别为1和2,命名模式为 mylog%i.log,会产生归档文件mylog1.log和mylog2.log。还可以指定文件压缩选项,例如,mylog%i.log.gz 或者 没有log%i.log.zip

例如:


  
     
       logFile.%d{yyyy-MM-dd}.log
       30
     

     
       %-4relative [%thread] %-5level %logger{35} - %msg%n
     

  


  
     
  



上述配置表示每天生成一个日志文件,保存30天的日志文件。
        

  
     test.log

       tests.%i.log.zip
       1
       3
     
     <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
       <maxFileSize>5MB</maxFileSize> 
     </triggeringPolicy> 
     <encoder> 
       <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> 
     </encoder> 
  </appender> 

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

上述配置表示按照固定窗口模式生成日志文件,当文件大于20MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。

      :对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。
PatternLayoutEncoder 是唯一有用的且默认的encoder ,有一个节点,用来设置日志的输入格式。使用“%”加“转换符”方式,如果要输出“%”,则必须用“\”对“\%”进行转义。

(4) 还有SocketAppender、SMTPAppender、DBAppender、SyslogAppender、SiftingAppender,并不常用,这里就不详解了。
大家可以参考官方文档(http://logback.qos.ch/documentation.html),还可以编写自己的Appender。

-子节点:用来设置某一个包或具体的某一个类的日志打印级别、以及指定仅有一个name属性,一个可选的level和一个可选的addtivity属性。

可以包含零个或多个元素,标识这个appender将会添加到这个loger
name: 用来指定受此loger约束的某一个包或者具体的某一个类。
level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前loger将会继承上级的级别。
addtivity: 是否向上级loger传递打印信息。默认是true。同一样,可以包含零个或多个元素,标识这个appender将会添加到这个loger。

常用loger配置有:

<!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" />
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" />
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />

<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>

-子节点:它也是元素,但是它是根loger,是所有的上级。只有一个level属性,因为name已经被命名为”root”,且已经是最上级了。
level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,不能设置为INHERITED或者同义词NULL。 默认是DEBUG。

基本上常用的子节点已经介绍完了,再给个常用的DEMO吧:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="/home" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>

<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

对应的JAVA代码应该怎么记录呢?

import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;
public class App {

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

    public static void main(String[] args) {
      logger.info("logback-info 成功了");
      logger.error("logback-error 成功了");
      logger.debug("logback-debug 成功了");
    }
}

与Log4j的不同,是用LoggerFactory的getLogger(getClass())来获取Logger对象的,这里要注意,若是用logback则用这种方式。

参考: https://blog.csdn.net/haidage/article/details/6794509/
https://www.cnblogs.com/warking/p/5710303.html
https://blog.csdn.net/liuweixiao520/article/details/78900779

springboot整合slf4j+log4j2

相当于又把logback的缺点重新改进,过程可以说是很有意思的,又log4j在性能上的缺失–》演变到使用性能更好的logback–》又演变到更好的log4j2框架上,可以说,选择很多种。。。

Log4j 升级Log4j 2 后的性能简单比较:

logo

可见在同步日志模式下, Logback的性能是最糟糕的.
而log4j2的性能无论在同步日志模式还是异步日志模式下都是最佳的.

其根本原因在于log4j2使用了LMAX, 一个无锁的线程间通信库代替了, logback和log4j之前的队列. 并发性能大大提升。关于LMAX,可以单独总结。

关于log4j2的新特性

-丢数据这种情况少,可以用来做审计功能。而且自身内部报的exception会被发现,但是logback和log4j不会。
-log4j2使用了disruptor技术,在多线程环境下,性能高于logback等10倍以上。
-(garbage free)之前的版本会产生非常多的临时对象,会造成GC频繁,log4j2则在这方面上做了优化,减少产生临时对象。尽可能少的GC
-利用插件系统,使得扩展新的appender,filter,layout等变得容易,log4j不可以扩展 插件????
-因为插件系统的简单性,所以在配置的时候,可以不用具体指定所要处理的类型。class
-可以自定义level
-Java 8 lambda support for lazy logging
-Support for Message objects
-对filter的功能支持的更强大
-系统日志(Syslog)协议supports both TCP and UDP
-利用jdk1.5并发的特性,减少了死锁的发生。
-Socket LogEvent SerializedLayout
-支持kafka queue

第一步:按照上面所说的,springboot本身默认集成的是logback,我们若是想用其他的,需要修改pom

去掉spring-boot-starter-logging

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
</dependency>

添加Log4j2

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

第二步:由于本身的properties默认配置对log4j不太友好,所以依然采用XML的外部文件配置形式
然后需要在resource下面添加log4j2.xml配置文件,当然了如果你不添加,springboo会提示你没有对应文件,并使用默认的配置文件,这个时候级别可以在application.properties中配置。

logging.level.root=error

当然了,使用配置文件,配置可以多样化,下面是默认的log4j2配置,log4j2支持xml、json、yml格式的配置
logo

例如:

<?xml version="1.0" encoding="UTF-8"?>  
<configuration status="OFF">  
  <appenders>  
    <Console name="Console" target="SYSTEM_OUT">  
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>  
    </Console>  
  </appenders>  
  <loggers>  
    <root level="error">  
      <appender-ref ref="Console"/>  
    </root>  
  </loggers>  
</configuration>

大体上与log4j没什么区别。

appenders里设置日志的输出方式、级别和格式
loggers里设置全局的级别和绑定appenders里的name

File 日志输出到文件,可配置覆盖还是追加
RollingFile “滚动文件”可作为按日输出日志的方式
Console 控制台日志

PatternLayout 格式化输出日志

ThresholdFilter“阈值筛选器” 可单独设置appender的输出级别

loggers里需要匹配每个appender的名称 name

我的服务一般放在linux服务器上跑,可能要实时查看日志,现有这个需求“我要打印到控制台的日志级别为Error,日志文件里保存的是INFO级别的日志”这样在产生错误的时候,就不会被大量无用的代码干扰。
要使用ThresholdFilter,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %M() @%L - %msg%n"/>
        </Console>
        <File name="ERROR" fileName="logs/error.log" append="false">
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %M() @%L - %msg%n"/>
        </File>
        <!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFile" fileName="logs/app.log"
                     filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %M() @%L - %msg%n"/>
            <SizeBasedTriggeringPolicy size="5MB"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <appender-ref ref="ERROR" />
            <appender-ref ref="RollingFile"/>
            <appender-ref ref="Console"/>
        </Root>
    </Loggers>
</Configuration> 

三个appender:Console、File、RollingFile

  • Console 通过ThresholdFilter过滤规则只输出ERROR级别的错误(onMatch=”ACCEPT” onMismatch=”DENY” 匹配到的接受,没有匹配的走人)
  • File 也通过ThresholdFilter的方式输出到日志,当然了append=”false” 会在服务每次启动的时候清空日志(覆盖)
  • RollingFile 因为日志全局设置的为INFO,所以不需要ThresholdFilter,这里只需要指定filePattern和SizeBasedTriggeringPolicy就行了

多环境分别使用不同的log4j2的配置文件

在多环境中(开发-测试-生产),有不同的properties文件,每个文件对应的日志配置不一样,那么我们如何均衡这种关系。
logo

主properties配置文件中激活指定的properties配置文件,如激活 dev的properties文件只需添加“spring.profiles.active=dev ”即可,这是进入”application-dev.properties”配置文件,在该文件中添加“logging.config=classpath:log4j2-dev.xml”,这时候dev开发环境将使用“log4j2-dev.xml”配置信息来输出日志。
这样就对应了每个环境下的配置文件能够对应不同的日志系统

参考:https://www.oschina.net/translate/reasons-to-prefer-logbak-over-log4j
https://blog.csdn.net/liuweixiao520/article/details/78900779
https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticConfiguration

坚持原创技术分享,您的支持将鼓励我继续创作!
+