(转)java日志框架解析(下)-最佳实践(代码片段)

small-potato small-potato     2022-12-08     585

关键词:

上一篇文章中, 讲了Java常用的日志库以及之间的关系,现在来说说我们在项目中怎么使用日志库。

1. 总是使用Log Facade,而不是具体Log Implementation

正如之前所说的,使用 Log Facade 可以方便的切换具体的日志实现。而且,如果依赖多个项目,使用了不同的Log Facade,还可以方便的通过 Adapter 转接到同一个实现上。如果依赖项目使用了多个不同的日志实现,就麻烦的多了。

具体来说,现在推荐使用 Log4j-API 或者 SLF4j,不推荐继续使用 JCL。

2. 只添加一个 Log Implementation依赖

毫无疑问,项目中应该只使用一个具体的 Log Implementation,建议使用 Logback 或者Log4j2。如果有依赖的项目中,使用的 Log Facade不支持直接使用当前的 Log Implementation,就添加合适的桥接器依赖。具体的桥接关系可以看上一篇文章的图

3. 具体的日志实现依赖应该设置为optional和使用runtime scope

在项目中,Log Implementation的依赖强烈建议设置为runtime scope,并且设置为optional。例如项目中使用了 SLF4J 作为 Log Facade,然后想使用 Log4j2 作为 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,依赖不会传递,这样如果你是个lib项目,然后别的项目使用了你这个lib,不会被引入不想要的Log Implementation 依赖;

Scope设置为runtime,是为了防止开发人员在项目中直接使用Log Implementation中的类,而不适用Log Facade中的类。

4. 如果有必要, 排除依赖的第三方库中的Log Impementation依赖

这是很常见的一个问题,第三方库的开发者未必会把具体的日志实现或者桥接器的依赖设置为optional,然后你的项目继承了这些依赖——具体的日志实现未必是你想使用的,比如他依赖了Log4j,你想使用Logback,这时就很尴尬。另外,如果不同的第三方依赖使用了不同的桥接器和Log实现,也极容易形成环。

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

比如阿里的JStorm就没有很好的处理这个问题,依赖jstorm会引入对Logback和log4j-over-slf4j的依赖,如果你想在自己的项目中使用Log4j或其他Log实现的话,就需要加上excludes:

<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>

 

5. 避免为不会输出的log付出代价

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

先看两个有问题的写法:

logger.debug("start process request, url: " + url);
logger.debug("receive request: ", toJson(request));

 

第一条是直接做了字符串拼接,所以即使日志级别高于debug也会做一个字符串连接操作;第二条虽然用了SLF4J/Log4j2 中的懒求值方式来避免不必要的字符串拼接开销,但是toJson()这个函数却是都会被调用并且开销更大。

推荐的写法如下:

logger.debug("start process request, url:", url); // SLF4J/LOG4J2
logger.debug("receive request: ", () -> toJson(request)); // LOG4J2
logger.debug(() -> "receive request: " + toJson(request)); // LOG4J2
if (logger.isDebugEnabled())  // SLF4J/LOG4J2
    logger.debug("receive request: " + toJson(request)); 

 

6. 日志格式中最好不要使用行号,函数名等字段

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

最后, log中不要输出稀奇古怪的字符!

部分开发人员为了方便看到自己的log,会在log语句中加上醒目的前缀,比如:

logger.debug("========================start process request=============");

 

虽然对于自己来说是方便了,但是如果所有人都这样来做的话,那log输出就没法看了!正确的做法是使用grep 来看只自己关心的日志。

转载自:https://zhuanlan.zhihu.com/p/24275518

java基础学习总结(203)——生成唯一id打印日志记录最佳实践(代码片段)

原因几乎所有的Java项目中的默认日志框架都会选择slf4j,在打印日志时,每行数据都有一个请求ID,这样会方便追踪日志。也可以使用一些链路追踪框架来实现这种目的。实现slf4j里有一个MDC类,是ThreadLocal的实现,保存在这里的... 查看详情

最佳实践|什么是好的日志记录实践?(代码片段)

作为软件开发人员,我们在使用某些库或框架时都遇到过那些烦人的、不太有用的错误消息:“无法解析配置文件”、“缺少此操作的权限”等。好的,好的,所以显然出了点问题;但究竟是什么?什么配置文件?哪些权限?你... 查看详情

flinkonyarn实时日志收集最佳实践(代码片段)

...控Flink 最新的模板背景在Flinkonyarn的模式下,程序运行的日志会分散的存储在不同的DN上,当Flink任务发生异常的时候,我们需要查看日志来定位问题,一般我们会选择通过FlinkUI上面的logs来查看日志,或者登录到对 查看详情

java基础学习总结(203)——生成唯一id打印日志记录最佳实践(代码片段)

原因几乎所有的Java项目中的默认日志框架都会选择slf4j,在打印日志时,每行数据都有一个请求ID,这样会方便追踪日志。也可以使用一些链路追踪框架来实现这种目的。实现slf4j里有一个MDC类,是ThreadLocal的实现,保存在这里的... 查看详情

日志采集最佳实践(代码片段)

概述本文介绍如何利用腾讯云容器服务TKE的日志功能对日志进行采集、存储与查询,分析各种功能用法与场景,给出一些最佳实践建议。注:本文仅适用于TKE集群。如何快速上手?TKE的日志功能入口在集群运维-日志规则,更多关于... 查看详情

kotlin最佳实践(代码片段)

为什么写此文Kotlin很烦,Gralde很烦,还都是升级狂,加一块更烦。几个月不接触Kotlin,再次上手时便一片迷茫。所以记录此文,以便再次上手时查阅。使用Gradle创建Kotlin项目mkdirhellokt创建项目文件夹cdhellokt切换到项目根目录gradle... 查看详情

elasticsearchelasticsearch日志场景最佳实践(代码片段)

1.概述转载:Day12-Elasticsearch日志场景最佳实践相似文章:【Elasticsearch】Elasticsearch最佳实践系列之分片恢复并发故障Elasticsearch可广泛应用于日志分析、全文检索、结构化数据分析等多种场景,大幅度降低维护多套专用... 查看详情

五年java经验,面试还是说不出日志该怎么写更好?——日志规范与最佳实践篇(代码片段)

...上一篇文章可以扫描文章下方的二维码,点击往期回顾-日志系列即可查看所有相关文章开发人员在开发过程中需要输出一些变量方便调试,正确的做法是使用日志来输出(使用整个系统大部分时间都是运维人员来维护,日志可... 查看详情

springboot之logback日志最佳实践

一、SpringBoot日志介绍  SpringBoot对所有内部日志记录使用了CommonsLogging,但是底层日志实现是开放的。为JavaUtil日志记录、Log4J2和Logback提供了缺省配置。在每种情况下,日志记录器都预先配置为使用控制台输出和可选的文件输... 查看详情

java导出excel最佳实践,大文件excel避免oom(内存溢出)框架-02-api

...加方便。设计简单,注释完整。方便大家学习改造。变更日志变更日志v0.0.4主要变化引入ExcelBs引导类,优化使用体验 查看详情

Laravel 数据库日志 - 最佳实践是啥

】Laravel数据库日志-最佳实践是啥【英文标题】:LaravelDatabaseLog-whatisthebestpracticeLaravel数据库日志-最佳实践是什么【发布时间】:2014-11-1215:25:59【问题描述】:我认为我有一个很常见的问题,但我找不到任何“最佳实践”的答案... 查看详情

转web程序优化的最佳实践:javascript和css篇

Yahoo!的ExceptionalPerformance团队为改善Web性能带来最佳实践。他们为此进行了一系列的实验、开发了各种工具、写了大量的文章和博客并在各种会议上参与探讨。最佳实践的核心就是旨在提高网站性能。ExcetionalPerformance团队总结出... 查看详情

云原生架构下日志服务数据预处理

...家国际教育机构为例,为大家详细介绍云原生架构下日志服务数据预处理以及对应的解决方案和最佳实践操作手册,方便用户快速对号入座,解决云原生架构下的常见日志难题。直达最佳实践:【https://bp.aliyun.com/... 查看详情

云原生架构下日志服务数据预处理

...家国际教育机构为例,为大家详细介绍云原生架构下日志服务数据预处理以及对应的解决方案和最佳实践操作手册,方便用户快速对号入座,解决云原生架构下的常见日志难题。直达最佳实践:【https://bp.aliyun.com/... 查看详情

springboot实践总结(转)

pringBoot是最流行的用于开发微服务的Java框架。在本文主要分享的是在专业开发中使用SpringBoot所采用的最佳实践。这些内容是基于个人经验和一些熟知的SpringBoot专家的文章。 在本文中重点介绍SpringBoot特有的实践(大多数时... 查看详情

基于海量日志和时序数据的质量建设最佳实践

...从开发、测试、到上线的整个过程中,会产生大量的日志、指标、事件以及告警等数据,这也给企业质量平台建设带来了很大的挑战。本议题主要通过可观测性的角度来讨论基于海量日志和时序数据的质量建设最佳实践... 查看详情

基于海量日志和时序数据的质量建设最佳实践

...从开发、测试、到上线的整个过程中,会产生大量的日志、指标、事件以及告警等数据,这也给企业质量平台建设带来了很大的挑战。本议题主要通过可观测性的角度来讨论基于海量日志和时序数据的质量建设最佳实践... 查看详情

serilog最佳实践(代码片段)

Serilog最佳实践概述Serilog[1]是Microsoft.NET的结构化日志记录库,并已成为Checkout.com上NET的首选日志记录库。它支持各种日志记录目的地(称为接收器[2])包从标准控制台和基于文件的接收器到日志服务,如Datadog。本... 查看详情