打印 Logger 日志时,需不需要再封装一下工具类?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 在开发过程中,打印日志是必不可少的,因为日志关乎于应用的问题排查、应用监控等。现在打印日志一般都是使用 slf4j,因为使用日志门面,有助于打印方式统一,即使后面更换日志框架,也非常方便。在 《Java 开发手册》中也有相关的规约。

在开发过程中,打印日志是必不可少的,因为日志关乎于应用的问题排查、应用监控等。现在打印日志一般都是使用 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

这也是为什么在开发规范中建议大家手写判断,虽然日志框架中帮我们进行了判断,那只是避免了打印输出日志,实际上像组装日志,序列化实例对象等等还是会被执行的。

logback 框架中的判断逻辑

当然如果当前应用只有个位数的 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。具体使用哪种,用不用封装等等,这些都是根据自己的实际情况来使用。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
9月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——使用Logger在项目中打印日志
本文介绍了如何在项目中使用Logger打印日志。通过SLF4J和Logback,可设置不同日志级别(如DEBUG、INFO、WARN、ERROR)并支持占位符输出动态信息。示例代码展示了日志在控制器中的应用,说明了日志配置对问题排查的重要性。附课程源码下载链接供实践参考。
1018 0
|
11月前
|
存储 人工智能 JSON
RAG Logger:专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、性能监控
RAG Logger 是一款专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、检索结果记录、LLM 交互记录和性能监控等功能。
468 7
RAG Logger:专为检索增强生成(RAG)应用设计的开源日志工具,支持查询跟踪、性能监控
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
124 3
|
消息中间件 监控 搜索推荐
OpenFeign日志组件Logger原理与应用
该文章详细解释了如何在OpenFeign中配置并使用请求和响应的GZIP压缩功能。
|
Java
OpenFeign 各种用法、 logger 日志记录
OpenFeign 各种用法、 logger 日志记录
236 0
|
监控 安全 API
orhanobut/logger - 强大的Android日志打印库
orhanobut/logger - 强大的Android日志打印库
844 1
|
监控 Linux 数据处理
深入了解Linux的logger命令:日志记录与监控
`logger`命令在Linux中用于向系统日志发送消息,便于记录系统事件和应用程序状态。它与`syslogd`配合,允许用户指定优先级、标识符和内容。简单易用,灵活适应不同日志需求。示例:`logger -p user.warning -t MYAPP &quot;A warning occurred.&quot;`。注意选择合适优先级,使用有意义的标识符,并结合其他工具如`logrotate`进行日志管理。
|
7月前
|
监控 容灾 算法
阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化
本文探讨了如何高效、经济且可靠地将海外应用与基础设施日志统一采集至阿里云日志服务(SLS),解决全球化业务扩展中的关键挑战。重点介绍了高性能日志采集Agent(iLogtail/LoongCollector)在海外场景的应用,推荐使用LoongCollector以获得更优的稳定性和网络容错能力。同时分析了多种网络接入方案,包括公网直连、全球加速优化、阿里云内网及专线/CEN/VPN接入等,并提供了成本优化策略和多目标发送配置指导,帮助企业构建稳定、低成本、高可用的全球日志系统。
808 54
|
12月前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
342 9

热门文章

最新文章