目录
log4j2是什么?
log4j2可以用干什么?解决什么问题?
log4j、slf4j、log4j2、logback之间的关系
相关配置说明
配置文件优先级
代码下载:https://gitee.com/hong99/spring/issues/I1N1DF
代码实现
项目代码结构(非spring纯log4j2)
简单配置文件(基于xml的简单配置)
将日志写入文件中
代码下载:https://gitee.com/hong99/spring/issues/I1N1DF
最后
相关文献:
Log4j2是Apache的一个开源项目,通过使用Log4j2,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
可参考:https://baike.baidu.com/item/log4j/480673?fr=aladdin
log4j2主要用来打印系统中重要的日志信息,解决在系统运营过程中出现的错误日志的记录,可以在不需要修改业务代码,重启web服务,需要修改配置文件就能进行日志拦截的修改。
API文档:http://logging.apache.org/log4j/2.x/log4j-api/apidocs/index.html
slf4j:slf4j是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体的日志框架实现配合使用(如log4j、logback、log4j2)。
log4j:log4j是apache实现的一个开源日志组件。
logback:logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现。
log4j2:Log4j2是log4j 1.x和logback的改进版,据说采用了一些新技术(无锁异步等),使得日志的吞吐量、性能比log4j 1.x提高了10倍,并解决了一些死锁的bug,而且配置更加简单灵活。
log4j、log4j2、logback的性能比对:
Appenders
Appender负责将LogEvents传递到目的地。每个Appender都必须实现Appender接口。大多数Appender继承自AbstractAppender,它增加了Lifecycle和Filterable支持。生命周期允许组件在配置完成后完成初始化并在关闭期间执行清理。Filterable接口允许组件附加过滤器,在事件处理期间对其进行筛选。Appender通常只负责将事件数据写入目标目标。在大多数情况下,他们将格式化事件的责任委托给布局。一些appender包装其他appender,以便他们可以修改LogEvent,处理Appender中的故障,根据高级Filter条件将事件路由到从属Appender
(1)AsyncAppender:引用其他Appender,被引用的Appender可以做到异步输出日志。
(2)CassandraAppender:可以将消息写入Cassandra数据库。
(3)ConsoleAppender:日志写入到标准输出,如System.out或System.error
(4)FailoverAppender:引用一组Appender,如果主的Appender失败则备用Appender开始起作用,直到主Appender恢复正常。
(5)FileAppender:将日志写入文件,比较常用。
(6)FlumeAppender:将日志以event的形式写入flume。
有三种模式:
a.远程客户端模式:模拟flume远程客户端,以avro_event的方式向agent发送消息。
b.内置flume agent模式:直接将event写入flume channel。
c.persist模式:将event写入本地BerkeleyDB,然后通过异步的方式将event发送到flume。
(7)JDBCAppender:使用JDBC连接将数据写入传统数据库。
(8)JMS Appender:将格式化后的日志写入JMS Destination。
(9)HttpAppender:发送日志到一个Http服务,必须使用Layout来格式化日志。
(10)KafkaAppender:将数据发送到kafka的topic,log4j的event对应kafka的record。
(11)MemoryMappedFileAppender:是一种特殊的日志写入方式,将日志写入内存以减少读写磁盘带来的IO开销,提升性能。
(12)NoSQLAppender:可以将数据写入nosql数据库,目前支持MongoDB和CouchDb。
(13)RandomAccessFileAppender:和FileAppender类似,但是使用了ByteBuffer+RandomAccessFile的方式来代替BufferedOutputStream
(14)RewriteAppender:允许LogEvent在其他appender处理之前先由RewriteAppender处理。
(15)RollingFileAppender:配置文件滚动生成策略,按照策略生成新的日志文件。
(16)RollingRandomAccessFileAppender:和RollingFileAppender类似,使用了ByteBuffer+RandomAccessFile的方式代替BufferedOutputStream。
(17)RoutingAppender:路由appender,可以分发Logevent到多个子Appender。
(18)SMTPAppender:将日志以邮件的形式发送,用在错误监控或者报警上。
(19)SocketAppender:将logevent发送到远程机器上,可以使用TCP或者UDP协议。
Layout
layout是指输出Logevent的布局,常见的比如输出日志的级别、时间、类名、线程等信息。Log4j2支持的Layout有如下几种:
(1)CSV Layouts。日志输出为csv文件,如log.info(a,b,c)会输出到csv文件对应的三列。
(2)HTML Layout。将日志输出为html页面,每个Logevent对应table里面的一行。
(3)JSON Layout。将日志输出为json格式。
(4)Pattern Layout。较为常用,通过使用一些匹配规则来确定日志输出格式。
(5)RFC5424 Layout。消息型的Appender经常用这种layout。
(6)Serialized Layout。使用java自身的序列化工具将Logevent序列化成byte array,但因为java固有的安全性问题,这种方式不再被推荐。
(7)Syslog Layout。将日志格式化为BSD syslog格式。
(8)XML Layout。格式化为xml。
log4j2.properties>log4j2.yaml>log4j2.json>log4j2.xml>defaultConfiguration
引入相关JAR包(版本为最新)
org.apache.logging.log4j
log4j-api
2.13.3
org.apache.logging.log4j
log4j-core
2.13.3
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* @Auther: csh
* @Date: 2020/7/26 14:17
* @Description:纯log4j2打印
*/
public class Log4j2App {
private static final Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
public static void main(String[] args) {
logger.trace("trace message");
logger.debug("debug message");
logger.info("info message");
logger.warn("warn message");
logger.error("error message");
logger.fatal("fatal message");
}
}
结果
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
15:22:53.174 [main] ERROR - error message
15:22:53.176 [main] FATAL - fatal message
由于上面没有配置log4j2的相关配置,所以打印了 ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
简单配置文件(基于File)
simple-log4j.xml
/**
* @Auther: csh
* @Date: 2020/7/29 15:58
* @Description:通过java读取配置文件
*/
public class SimpleXmiLog4j {
public static void main(String[] args) throws Exception{
//TODO 注意该路基在每台电脑上面可能不一样!
File file =new File("D:\\ideaWorkSpace\\spring\\src\\main\\resources\\log4j\\simple-log4j.xml");
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
final ConfigurationSource source = new ConfigurationSource(in);
Configurator.initialize(null, source);
Logger logger = LogManager.getLogger("myLogger");
logger.trace("trace message");
logger.debug("debug message");
logger.info("info message");
logger.warn("warn message");
logger.error("error message");
logger.fatal("fatal message");
}
}
结果
15:59:59.491 [main] INFO myLogger - info message
15:59:59.494 [main] WARN myLogger - warn message
15:59:59.495 [main] ERROR myLogger - error message
15:59:59.495 [main] FATAL myLogger - fatal message
项目结构
导入maven包
org.apache.logging.log4j
log4j-core
2.13.3
org.apache.logging.log4j
log4j-web
2.13.3
simple-log4j.xml
配置 web.xml
Spring MVC Application
log4jConfiguration
classpath:log4j/simple-log4j.xml
org.apache.logging.log4j.web.Log4jServletContextListener
log4jServletFilter
org.apache.logging.log4j.web.Log4jServletFilter
log4jServletFilter
/*
REQUEST
FORWARD
INCLUDE
ERROR
HelloWeb
org.springframework.web.servlet.DispatcherServlet
1
HelloWeb
/
@Controller
@RequestMapping("/")
public class HomeController {
private static Logger log = LogManager.getLogger(HomeController.class.getName());
@RequestMapping(value = "",method = RequestMethod.GET)
public String home(ModelMap model) {
log.info("进入了首页!");
model.addAttribute("message","Hello home");
return "home";
}
}
14:45:28.468 [http-nio-80-exec-1] INFO com.hong.spring.mvc.controller.HomeController - 进入了首页!
14:45:28.468 [http-nio-80-exec-1] INFO com.hong.spring.mvc.controller.HomeController - 进入了首页!
14:45:29.143 [http-nio-80-exec-2] INFO com.hong.spring.mvc.controller.HomeController - 进入了首页!
14:45:29.143 [http-nio-80-exec-2] INFO com.hong.spring.mvc.controller.HomeController - 进入了首页!
14:45:29.473 [http-nio-80-exec-3] INFO com.hong.spring.mvc.controller.HomeController - 进入了首页!
14:45:29.473 [http-nio-80-exec-3] INFO com.hong.spring.mvc.controller.HomeController - 进入了首页!
新增log4j2-now.xml(将日志写入d盘中)
spring
D:/logs/${APP_NAME}
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n
${PATTERN_FORMAT}
${PATTERN_FORMAT}
${PATTERN_FORMAT}
修改web.xml
log4jConfiguration
classpath:log4j/log4j2-now.xml
结果
[2020-07-31 03:17:39,714] Artifact spring:war: Artifact is deployed successfully
[2020-07-31 03:17:39,714] Artifact spring:war: Deploy took 6,880 milliseconds
2020-07-31 15:17:40.019 INFO com.hong.spring.mvc.controller.HomeController 17 home - 进入了首页!
2020-07-31 15:17:40.041 ERROR com.hong.spring.mvc.controller.HomeController 18 home - error进入了首页!
2020-07-31 15:17:40.649 INFO com.hong.spring.mvc.controller.HomeController 17 home - 进入了首页!
2020-07-31 15:17:40.650 ERROR com.hong.spring.mvc.controller.HomeController 18 home - error进入了首页!
2020-07-31 15:17:40.933 INFO com.hong.spring.mvc.controller.HomeController 17 home - 进入了首页!
2020-07-31 15:17:40.934 ERROR com.hong.spring.mvc.controller.HomeController 18 home - error进入了首页!
在企业中都是通过一些SLF4J 或commons-loggingp这些门面框架,而不是直接使用log4j或者log4j2这样可以减少因为框架升级或者修改其他日志框架而导致发生大批量代码修改的问题。日志框架对于系统的问题根据和记录非常重要,特别在系统在排除一些异常过程中,通过日志来跟踪异常起到关键性作用,所以日志框架极其重要,比较成熟规模的互联网公司会将日志放到统一的日志分析平台如:kibana或elk等。本文只是关于spring相关,涉及log4j2还是比较浅,后续再统一深入。
http://logging.apache.org/
https://blog.csdn.net/edward0830ly/article/details/8250412
https://juejin.im/post/5c11c831e51d4511624d1b59
http://www.slf4j.org/manual.html