Log4j2 频繁爆雷给出几点日志使用建议,注意收藏,记得点赞-Java-E先生的博客
Java
MySQL
大数据
Python
前端
黑科技
大语言模型
    首页 >> 互联网 >> Java

Log4j2 频繁爆雷给出几点日志使用建议,注意收藏,记得点赞

[导读]:日志体系概述 日志接? JCL:Apache 基金会所属的项?,是一套 Java 日志接?,之前叫 Jakarta Commons Logging,后更名为 Commons Logging,简称 JCL。 SLF4J:英文全称 Simple Logging Facade for Java,缩写 Slf4j,是?套简易 Java ?志?面,只提供相关...

日志体系概述
日志接?
JCL:Apache 基金会所属的项?,是一套 Java 日志接?,之前叫 Jakarta Commons Logging,后更名为 Commons Logging,简称 JCL。
SLF4J:英文全称 Simple Logging Facade for Java,缩写 Slf4j,是?套简易 Java ?志?面,只提供相关接?,和其他日志工具之间需要桥接。

日志实现
JUL:JDK 中的?志工具,也称为 jdklog、jdk-logging,? Java1.4 以来 Sun 的官方提供。
Log4j:?属于 Apache 基金会的一套日志框架,现已不再维护。
Log4j2:Log4j 的升级版本,与 Log4j 变化很大,且不兼容。
Logback:?个具体的?志实现框架,和 Slf4j 是同一个作者,性能很好。
 

1. ?面约束

  • 使??面,?不是具体实现

使用 Log Facade 可以?方便便的切换具体的日志实现。?且,如果依赖多个项目,使?了不同的 Log Facade,还可以?方便便的通过 Adapter 转接到同一个实现上。如果依赖项目直接使用了多个不同的日志实现,会非常糟糕。

经验之谈:日志?面,?般现在推荐使用 Log4j-API 或者 SLF4J,不推荐继续使用 JCL。

  • 单?原则,只添加一个日志实现

项?中应该只使用一个具体的 Log Implementation,如果在依赖的项?中,使?的 Log Facade 不支持当前 Log Implementation,就添加合适的桥接器。

经验之谈:jul 性能一般,log4j 性能也有问题而且不再维护,建议使用 Logback 或者 Log4j2。

2. 依赖约束

  • 日志实现坐标应该设置 optional 并使? runtime scope

在项?中,Log Implementation 的依赖强烈建议设置为 runtime scope,并且设置为 optional。例如项?中使用了 SLF4J 作为 Log Facade,然后想使用 Log4j2 作为 Log Implementation,在使用 maven 添加依赖的时候设置如下:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>${log4j.version}</version>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>${log4j.version}</version>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

设置 optional 为 true,依赖不会传递,这样如果你是个 lib 项?,然后别的项目使?了你这个 lib,不会被引入不想要的 Log Implementation 依赖;

scope 设置为 runtime,是为了防?开发?员在项?中直接使? Log Implementation 中的类,强制约束开发人员使? Facade 接口。

3. 避免传递

  • 尽量用 exclusion 排除依赖的第三?库中的?志坐标

依赖约束 所说,第三?库的开发者却未必会把具体的?志实现或者桥接?的依赖设置为 optional, 然后你的项目就会被迫传递引入这些依赖,?这些日志实现未必是你想要的,比如他依赖了 Log4j,你想使用 Logback,这时就很尴尬。另外,如果不同的第三方依赖使?了不同的桥接?和 Log 实现,极有可能会形成环。

这种情况下,推荐的处理方法,是使用 exclude 来排除所有的这些 Log 实现和桥接?的依赖,只保留第三?库?面对 Log Facade 的依赖。

示例:如依赖 jstorm 会引入 Logback 和 log4j-over-slf4j,如果在你?己的项?中使用 Log4j 或其他 Log 实现的话,就需要加上exclusion:

<dependency>
    <groupId>com.alibaba.jstorm</groupId>
    <artifactId>jstorm-core</artifactId>
    <version>2.1.1</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
        </exclusion>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4. 注意写法

  • 避免为不会输出的 log 买单

Log 库都可以灵活的设置输出级别,所以每一条程序中的 log,都是有可能不会被输出的。这时候就要注意不要额外的付出代价。示例如下:

logger.debug("this is debug: " + message);
logger.debug("this is json msg: {}", toJson(message));

第一条语句的字符串拼接,即使日志级别?于 debug 不会打印,依然会做字符串连接操作;

第二条语句虽然?了 SLF4J/Log4j2 中的占位符输出(懒求值方式),但是 toJson() 这个函数却是总会被调用并且开销更大。推荐的写法如下:

// SLF4J/LOG4J2
logger.debug("this is debug:{}", message);
// LOG4J2
logger.debug("this is json msg: {}", () -> toJson(message));
// SLF4J/LOG4J2
if (logger.isDebugEnabled()) {
    logger.debug("this is debug: " + message);
}

5. 减少分析

  • 输出的日志中尽量不要使?行号、函数名等信息

原因:为了获取语句所在的函数名,或者?号,log 库的实现都是获取当前的 stacktrace,然后分析取出这些信息,而获取 stacktrace 的代价是很昂贵的。如果有很多的?志输出,就会占用?量的 CPU。在没有特殊需要的情况下,建议不要在?志中输出这些字段。

6. 精简?上

  • log 中尽量不要输出稀奇古怪的字符,这是个习惯和约束问题

有人习惯写如下这样的语句:

logger.debug("===============================>:{}",message);

输出了?量?关字符,虽然?己?时痛快一直爽,但是如果所有?都这样写的话,那 log 输出就没法看了!正确的写法是日志只输出必要信息,如果要过滤,后期可以使用 grep 命令来筛选,只查看自己关心的日志即可。

本文来自E先生的博客,如若转载,请注明出处:https://www.javajz.cn

留言区

联系人:
手   机:
内   容:
验证码:

历史留言

欢迎加Easy的QQ