乐趣区

关于后端:打印-Logger-日志时需不需要再封装一下工具类

在开发过程中,打印日志是必不可少的,因为日志关乎于利用的问题排查、利用监控等。当初打印日志个别都是应用 slf4j,因为应用日志门面,有助于打印形式对立,即便前面更换日志框架,也十分不便。在《Java 开发手册》中也有相干的规约。

所以在开发中,个别应用上面这种形式来打印日志。

LOGGER.info("print: {}", "this is the log");

不过有的利用会将 LOGGER 再封装一下,最终写成:

LoggerUtil.info(LOGGER, "print: {}", "this is the log");

本文的次要内容是探讨为什么要封装,有没有必要封装,以及怎么封装,如果小伙伴有更好的倡议,能够提出,进行互相学习。

为什么要封装

很多人感觉 slf4j 原本就是日志门面,曾经封装的很好了,为什么要多此一举,再额定封装一个 LoggerUtil 呢?

其实这块也是在开发标准中有阐明的:

如果不进行封装,则会写成上面这种:

if (LOGGER.isInfoEnabled()) {LOGGER.info("print: {}", "this is the log");
}

所以,个别封装是将 if 判断这块逻辑对立封装为一个工具类。

可能到这里还有小伙伴不是很了解为什么要加 if 判断,能够看下上面这段代码:

能够看出转换逻辑这块绝对比较复杂、耗时,在这里只是模仿的场景,理论应用可能会有其余状况,比方打印办法的出参入参、计算耗时等:

LOGGER.info("xxx 办法申请参数为:{}", JSON.toJSONString(req));
LOGGER.info("xxx 执行耗时:{}ms", System.currentTimeMillis() - startTime);

在某些场景下为了进步性能,须要敞开日志,比方大促,秒杀等等。

说到这里置信小伙伴曾经看出问题了,因为这样写的话,当我敞开日志打印时,只是敞开了磁盘输入,然而耗时逻辑仍然会继续执行。

# 日志级别调整到 error
logging.level.com.liuzhihang=error

这也是为什么在开发标准中倡议大家手写判断,尽管日志框架中帮咱们进行了判断,那只是防止了打印输出日志,实际上像组装日志,序列化实例对象等等还是会被执行的。

当然如果以后利用只有个位数的 tps 或者 tpm 那齐全没必要思考这些,也没必要因噎废食,失常应用就行。

该怎么封装

为了防止每次都要 if 判断的问题,会将 if 模块封装为工具类:

下面的封装,无效防止了每次都须要进行判断,只须要将代码中的打印日志换成 LogUtil 即可:

然而这种状况只能防止打印 既有参数 时的 if 判断,对办法类型的没有作用,这里就须要应用 Supplier

理论应用成果:

以上仅为一种封装形式,其余的封装能够自行思考,比方整个日志框架都封装。

其余应用

这部分封装在 log4j-api-2.17.2.jar 中也有所体现,只不过 slf4j 外面并没有封装 Supplier 反对,具体实现能够自行浏览源码。

那为什么 slf4j 不反对,其实也是有探讨的,能够看 issue #70,外面进行了一系列探讨。

最终后果是在 2.0 反对了 Fluent Logging API 语法。

slf4j 2.0 应用

<!-- slf4j 2.0 依赖 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>2.0.0</version>
</dependency>

依照官网文档的应用案例间接应用即可:

logger.atDebug()
    .setMessage("Temperature set to {}. Old value was {}.")
    .addArgument(() -> t16()).addArgument(oldT)
    .log();

为什么要这样写,只能说是人家的 API 设计就是如此,当然也有其余的思考,能够看看 github issue。具体应用哪种,用不必封装等等,这些都是依据本人的理论状况来应用。

本文由 mdnice 多平台公布

退出移动版