Java日志体系

摘要:
日志在系统中扮演着重要的角色,特别是对于已经上线的系统,这是定位的关键。因此,开发了以下日志框架。为了方便日志系统的迁移,Java的日志框架提出了一种模仿JDBC的Java外观,但尚未统一。每个框架都有自己的外观。通常,日志框架由API+Imp组成。通过这种方式,市场上出现了不同的日志框架。为了统一,Jakarta提取了一个统一的接口javacommons logging。本项目中使用的日志框架依赖于<dependency><groupId>org。slf4j</groupId><artifactId>slf4j api</authenticationId><version>1.7.21</version><dependency><deposition><groupId>ch.qos。logback</groupId><artifactId>logback class</authenticationId><version>1.1.7</version><dependency><deposition><groupId>ch.qos。logback</groupId></groupId><artifactId>logback core</artifactId><version>1.1.7</version></adependency>bridge Rely on。将jul和log4j重定向到slf4j,这样在该项目中使用的实际日志就是slf4j+logback日志框架<!

日志在系统中举足轻重,特别是对于已经上线的系统,是定位问题的关键。日常开发中可以使用System.out打印日志快速查看运行时信息,可以对于线上系统来说,需要更多的信息如:时间、打印日志所在的类名和方法名和统一控制日志打印开关,System.out显然无法满足要求。于是发展出了以下的日志框架,为了方便日志体系的迁移,Java的日志框架模仿JDBC提出了Java facade,但是并没有达成统一,每个框架都有自己的facade,一般日志框架都是由API+Imp两个部分组成。

日志发展

1. Apache Log4j

Apache Log4j 2 is an upgrade to Log4j that provides significant improvements over its predecessor, Log4j 1.x, and provides many of the improvements available in Logback while fixing some inherent problems in Logback’s architecture.

Log4j是Apache公司产品,主流版本是 Log4j 2,有自己的logging facade:log4j-api,因此使用需要如下依赖

<dependencies>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.13.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.13.0</version>
  </dependency>
</dependencies>

详细配置可从官网查找,使用如下:

import org.apache.log4j.Logger;
...
Logger logger = Logger.getLogger(Test.class);
logger.trace("trace");

2. Commons-Logging

Sun为了与Apache竞争,也开发了日志工具,内置于JDK中的java.util.logging包下,一般简称为JCL。这样市面上就出现了不同的日志框架,为了统一,Jakarta 向上抽取了一个统一的接口java commons logging。日志框架开发者面向此Facade编程实现,日志框架使用者代码中调用此Facade(类似JDBC),在Runtime时,根据配置的不同执行不同日志实现。

Java日志体系第1张

3. Logback+slf4j

逐渐地,Log4j满足不了需求,原作者又开发了新的日志实现LogBack和Log Facade slf4j

1.依赖

<!-- LogBack -->
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.1.7</version>
</dependency>

2.配置logback.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>
    <logger name="com.chanshuyi" level="TRACE"/>
 
    <root level="warn">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

3.调用

import org.slf4j.Logger; 	// 注意导入的包是slf4j
import org.slf4j.LoggerFactory;
...
    Logger logger = LoggerFactory.getLogger(Slf4jJDKLog.class);
	logger.trace("Trace Level.");
    logger.info("Info Level.");
    logger.warn("Warn Level.");
    logger.error("Error Level.");

至此市面上主流的Java日志框架是Log4j+Log4j-api和logback+slf4j

最佳实践

对于新项目来说,一般会使用logback+slf4j日志框架。那对于依赖的第三方使用了log4j或者jul的怎么办,如何统一输出?答案是桥接器

Java日志体系第2张

  1. 本项目使用的日志框架依赖

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.21</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.7</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.1.7</version>
    </dependency>
    
  2. 桥接器依赖,将jul和log4j重定向到slf4j,这样真实使用的日志就是本项目中的slf4j+logback日志框架

    <!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.7.25</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
        <version>1.7.25</version>
    </dependency>
    

以上是项目技术选型是logback+slf4j,如果是其他呢?

只需要

  1. 确定日志Facade,一般就是slf4j
  2. 确定日志实现框架,不同的日志框架针对slf4j都提供绑定器,也就是说slf4j可以配合大部分日志实现使用
    • slf4j-jdk14:slf4j到jdk-logging的桥梁
    • slf4j-log4j12:slf4j到log4j1的桥梁
    • log4j-slf4j-impl:slf4j到log4j2的桥梁这是apache实现,依赖的log4j版本较新。slf4j-log4j12这是slf4j中实现,依赖的log4j版本较低。实验可以互相替代,但是注意配置文件的不同。
    • logback-classic:slf4j到logback的桥梁
    • slf4j-jcl:slf4j到commons-logging的桥梁
  3. 管理依赖项目中的日志框架,拦截且重定向到slf4j中
    • jul-to-slf4j:jdk-logging到slf4j的桥梁
    • log4j-over-slf4j:log4j1到slf4j的桥梁
    • jcl-over-slf4j:commons-logging到slf4j的桥梁

案例二:如何让Spring以log4j2形式输出

spring默认使用的是jcl输出日志

Java日志体系第3张

而你的应用中,采用了slf4j+log4j-core,即log4j2进行日志记录

Java日志体系第4张

方案一:jcl-over-slf4j适配器

Java日志体系第5张

方案二:JUL to SLF4J bridge

Java日志体系第6张

但是注意需要在调用日志之前执行以下代码,才能正常工作。

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();

循环引用问题

想象这样一种情况,通过桥接器将log4j的日志全部重定向到slf4j,然后slf4j又再次绑定到了log4j实现。死循环了。

Java日志体系第7张

参考:
1 Java日志框架那些事儿
2 带你弄清混乱的JAVA日志体系
3 apache log4j官网
4 slf4j

免责声明:文章转载自《Java日志体系》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Dockerfile执行shell脚本报错No such file or directory(又名 Dockerfile中sh脚本格式引发的灾难)k8s学习笔记之五:volume,PV ,PVC下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

svn 基础 入门 (Good!)

前言: 软件不能完全解决因沟通造成的问题。 什么是 svnsubversion的版本库是一种文件服务器,它记录每一次改变,每个文件的改变,甚至是目录树本身的改变,例如文件和目录的添加、删除和重新组织。一般情况下,客户端从版本库中获取的数据是文件系统树中的最新数据。但是客户端也具备查看文件系统树以前任何一个状态的能力。举个例子,客户端有时会对一些历史性问题感...

Vue项目上线后刷新报错404问题(apache,nginx,tomcat)

一、 Vue项目打包发布apache报错: route,配置一个覆盖所有的路由情况 1、需要修改router/index.js中new Router 配置,加一个base: '/htcm_front/', 它指定应用的基路径,该应用是服务于localhost/htcm_front路径下,所以必须加base配置,否则应用会展示404页面 2、需要修改conf...

Apache Htpasswd生成和验证密码

Assuming you create the password using the following command and "myPassword" as the passwordhtpasswd -c /usr/local/apache/passwd/passwords usernameThis will create a file that loo...

Log4J配置文件详解

前文讲解了在与《Java日志工具之java.util.logging.Logger》对比中讲解了如何使用Log4J,本文来详细讲解下配置文件。 配置文件格式 Log4J配置文件的基本格式如下: #配置根Logger log4j.rootLogger = [ level ] , appenderName1 , appenderName2 ,...

配置Nginx和Apache允许指定域名CORS跨域访问

 前后端分离开发,导致前端项目需要跨域请求后端接口,解决方法有很多,本文只介绍两个: 1. 修改后端程序代码实现允许跨域请求 2. 修改服务器配置文件实现允许跨域请求 正文: 方法1:修改后端程序代码实现允许跨域请求  以ThinkPHP为例,为了一劳永逸,直接在入口文件index.php中加入代码: header("Access-Control-Allo...

分布式系统详解--基础知识(概论)

  一、 引言         由于网上介绍的分布式的系统讲解并没有多少,所以在这儿就希望可以写一套系统的分布式的详解,未来也结合springboot的搭建分布式系统进行详细构建。也愿意坚持写下去,写给自己也分享给大家,希望大家可以提出宝贵的意见,一同长进。哈哈。。第一篇文章,开个头。 二、分布式定义。   了解起来分布式呢,顺便也介绍一下集群,这两个概念...