slf4j 记录日志文件

SLF4J是一个非常流行的日志记录外观,但是,就像我们使用的所有库一样,我们有可能以错误的方式或至少以一种非最佳方式使用它。

在本教程中,我们将列出常见的日志记录错误以及如何使用FindBugs检测到它们。 我们还将在相关时提及PMD和Sonar Squid检查。

我们将使用两个外部FindBugs插件,它们将日志记录检测器添加到FindBugs。

第一个是Kengo Toda的SLF4J only插件 ,其中仅包含SLF4J检测器。

第二个插件是流行的FB Contrib ,其中包含许多测井仪。

有关如何使用FindBugs插件的信息,请参阅以下文章:

  • [Maven]( https://gualtierotesta.wordpress.com/2015/06/14/tutorial-using-findbugs-with-maven/ )
  • [NetBeans]( https://gualtierotesta.wordpress.com/2015/06/07/findbugs-plugins/ )

注意:在所有示例中,我们将假定以下导入:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

1.记录仪定义

错误的方法:

W1a. Logger log = LoggerFactory.getLogger(MyClass.class);
W1b. private Logger logger = LoggerFactory.getLogger(MyClass.class);
W1c. static Logger LOGGER = LoggerFactory.getLogger(AnotherClass.class);

正确方法:

C1a. private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
C1b. private final Logger logger = LoggerFactory.getLogger(getClass());

一般规则 :记录器应该是最终的且私有的,因为没有理由与其他课程共享或重新分配记录器。

相反,对于记录器是否应该是静态的,并没有普遍的共识。 SLF4J插件支持非静态版本(C1b),而PMD(“ LoggerIsNotStaticFinal”规则)和Sonar(鱿鱼规则S1312)更喜欢静态记录器(C1a),因此这两个选项均应视为有效。

附加信息:

  • [SLF4J常见问题解答]( http://slf4j.org/faq.html#declared_static )
  • [Apache Commons静态日志]( http://wiki.apache.org/commons/Logging/StaticLog )。

请注意:

  • 在静态版本(C1a)中,记录器名称通常使用大写字母作为所有常量字段。 否则,PMD将报告“ VariableNamingConventions”违规行为。
  • 在这两种情况下,建议的名称都是“ logger / LOGGER”而不是“ log / LOG”,因为某些命名约定会避免使用太短的名称(少于四个字符)。 而且log是动词,更适合于方法名。
  • W1c是错误的,因为我们指的是一个类(AnotherClass),它不是定义记录器的类。 在99%的情况下,这是由于从一类复制到另一类而导致的。

相关的FindBugs(SLF4J插件)检查:

  • SLF4J_LOGGER_SHOULD_BE_PRIVATE
  • SLF4J_LOGGER_SHOULD_BE_NON_STATIC
  • SLF4J_LOGGER_SHOULD_BE_FINAL
  • SLF4J_ILLEGAL_PASSED_CLASS

2.格式字符串

错误的方法:

W2a. LOGGER.info("Obj=" + myObj);
W2b. LOGGER.info(String.format(“Obj=%s”, myObj));

正确方法:

C2. LOGGER.info("Obj={}",myObj);

一般规则 :格式字符串(第一个参数)应为常量,没有任何字符串串联。 动态内容(示例中的myObj值)应使用占位符(“ {}”)添加。

动机很简单:无论是否记录消息,我们都应在记录器建立延迟记录消息的创建,具体取决于当前的记录级别。 如果我们使用字符串连接,则无论采用哪种日志记录级别,都会以任何方式构建消息,这会浪费CPU和内存资源。

相关的FindBugs(SLF4J插件)检查:

  • SLF4J_FORMAT_SHOULD_BE_CONST格式应为常数
  • SLF4J_SIGN_ONLY_FORMAT格式字符串不应仅包含占位符

相关的FindBugs(FB Contrib插件)检查:

  • LO_APPENDED_STRING_IN_FORMAT_STRING方法将串联的字符串传递给SLF4J的格式字符串

3.占位符参数

错误的方法:

W3a. LOGGER.info("Obj={}",myObj.getSomeBigField());
W3b. LOGGER.info("Obj={}",myObj.toString());
W3c. LOGGER.info("Obj={}",myObj, anotherObj);
W3d. LOGGER.info("Obj={} another={}",myObj);

正确方法:

C3a. LOGGER.info("Obj={}",myObj);
C3b. LOGGER.info("Obj={}",myObj.log());

一般规则 :占位符应该是对象(C3a),而不是方法返回值(W3a),以便在记录级别分析后推迟对其求值(请参见上一段)。 在W3a示例中,无论日志记录级别如何,都会始终调用方法getSomeBigField()。 出于同样的原因,我们应该避免在语义上与C3a等效的W3b,但是它总是在toString()方法调用中产生。

解决方案W3c和W3d是错误的,因为格式字符串中的占位符数量与占位符参数数量不匹配。

解决方案C3b可能在某种程度上具有误导性,因为它包含方法调用,但是每当myObj包含多个字段(例如,它是一个大型JPA实体)但我们不想记录其所有内容时,它就很有用。

例如,让我们考虑以下类:

public class Person {
private String id;
private String name;
private String fullName;
private Date birthDate;
private Object address;
private Map<String, String> attributes;
private List phoneNumbers;

它的toString()方法很可能会包含所有字段。 使用解决方案C3a,所有它们的值都将打印在日志文件中。

如果不需要所有这些数据,则定义如下的帮助方法将很有用:

public String log() {
return String.format("Person: id=%s name=%s", this.id, this.name);
}

仅打印相关信息。 此解决方案的CPU和内存也比toString()轻。

有什么关系? 它取决于应用程序和对象类型。 对于JPA实体,我通常在log()方法中包括ID字段(以便在需要所有列数据时让我在数据库中找到记录),并且可能是一个或两个重要字段。

毫无疑问,应该记录密码字段和/或敏感信息(电话号码,...)。 这是不使用toString()登录的另一个原因。

相关的FindBugs(SLF4J插件)检查:

  • SLF4J_PLACE_HOLDER_MISMATCH

4.调试消息

重要提示:规则4(请参阅5条规则文章 )指导我们使用受保护的调试日志记录

if (LOGGER.isDebugEnabled()) {
LOGGER.debug(“Obj={}”, myObj);
}

使用SLF4J,如果占位符参数是对象引用(请参阅解决方案C3a / C3b),则可以使用if来避免代码混乱。

因此,使用以下内容是安全的:

LOGGER.debug(“Obj={}”, myObj);

5.例外

适当的异常日志记录是问题分析的重要支持,但很容易忽略它的用处。

错误的方法:

W5a. catch (SomeException ex) { LOGGER.error(ex);}..
W5b. catch (SomeException ex) { LOGGER.error("Error:" + ex.getMessage());}..

正确方法:

C5. catch (SomeException ex) { LOGGER.error("Read operation failed: id={}", idRecord, ex);}..`

一般规则

  1. 不要使用getMessage()(请参阅W5b)而不是完整的异常来删除堆栈跟踪信息。 堆栈跟踪通常包括问题的真正原因,很容易是底层代码引发的另一个异常。 仅记录消息将阻止我们发现问题的真正原因。
  2. 确实在日志消息中显示了重要的信息(对于将要分析日志文件的人员),该信息显示了一个文本,解释了在引发异常(不是异常种类或诸如“错误”之类的消息)时我们想要执行的操作:我们已经知道有些不良情况发生了)。 我们需要知道的是我们在做什么以及在哪些数据上。

C5示例告诉我们,我们正在尝试读取具有特定ID的记录,该ID的值已与消息一起写入了日志。

请注意,C5在格式字符串中使用一个占位符,但是有两个附加参数。 这不是错误,而是一种特殊的模式,SLF4J将其识别为异常记录案例:最后一个参数(在C5示例中为ex)被SLF4J视为Throwable(异常),因此不应将其包含在格式字符串中。

相关的FindBugs(SLF4J插件)检查:

  • SLF4J_MANUALLY_PROVIDED_MESSAGE:消息不应基于异常getMessage()

翻译自: https://www.javacodegeeks.com/2016/02/tutorial-correct-slf4j-logging-usage-check.html

slf4j 记录日志文件

slf4j 记录日志文件_教程:正确的SLF4J日志记录用法以及如何检查它相关推荐

  1. 教程:正确的SLF4J日志记录用法以及如何检查它

    SLF4J是一个非常流行的日志记录外观,但是,就像我们使用的所有库一样,我们有可能以错误的方式或至少以非最佳方式使用它. 在本教程中,我们将列出常见的日志记录错误以及如何使用FindBugs检测到它们 ...

  2. 安装程序未能打开日志文件_工地开工,安全日志记录这样写才规范!

    一.安全日志的理解 施工安全日志是从工程开始到竣工,由专职安全员对整个施工过程中的重要生产和技术活动的连续不断的详实记录.是项目每天安全施工的真实写照,也是工程施工安全事故原因分析的依据,施工安全日记 ...

  3. 两个组件连线_如何正确的使用日志组件 Log4j、SLF4J、Logback

    来源:http://t.cn/EVpprGI 相信目前大多数情况下,不管是开源框架或是平时工作编码中都离不开一种框架,它就是日志框架,本文了解一下我们常用日志框架的区别及如何正确的使用. 1.Comm ...

  4. ncl如何添加线shp文件_教程合集 | 地图数据找不到?家园都有解决方案!

    原标题:教程合集 | 地图数据找不到?家园都有解决方案! 本栏目为气象家园各类优质教程的合集,每期一个主题. 各位小伙伴在画图的时候是否曾经因为地图问题而头秃呢?第一期将从地图数据部分开始,打好小旗子 ...

  5. slf4j绑定器_用于ADFLogger的SLF4J绑定–缺少的部分

    slf4j绑定器 由于最好的原因,在我的日常工作中,我希望为ADF Logger Oracle ADF提供一个SLF4J适配器. 毫不奇怪,slf4j没有用于ADFLogger的适配器,但是由于ADF ...

  6. 使用log4j记录日志_使用log4j2免费分配日志记录

    使用log4j记录日志 介绍 最近,我正在为一个客户端工作,试图为大型精心制作的Java系统消除一些GC暂停. 经过分析后,我意识到大部分垃圾都是通过日志记录产生的! 是否有一种简单的方法来删除所有分 ...

  7. SLF4j使用、统一系统中所有的日志记录到slf4j

    SLF4j使用 在系统中使用SLF4j 开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法:给系统导入slf4的jar和logback的实现jar import ...

  8. ncl如何添加线shp文件_教程合集 | NCL与GrADS地图绘制合集

    小编在整理过程中,发现有很多小伙伴在画图过程中,由于不注意设置投影方式,常常会出现地图和数据偏离的情况,用GrADS作图的小伙伴千万要记得检查投影方式哦!还有什么问题想讨论?欢迎移步气象家园~ 家园的 ...

  9. mysql下日志_浅谈mysql下日志记录

    1,如何查看mysql执行命令历史 #.mysql_history     此文件记录了在mysql中执行命令的历史 2,事务日志: transaction log:事务型存储引擎自行的管理和使用. ...

最新文章

  1. 解决IDEA中进行maven install报:系统资源不足的问题
  2. linux系统调用挂钩方法总结
  3. VTK:隐式函数之ImplicitDataSet
  4. JavaFX技巧14:StackPane子项-隐藏但不消失
  5. shell [] [[]]的区别(转)
  6. linux yum安装redis5.0,CentOS 7安装Redis 5.0.5并加入Systemd服务
  7. 一览众山小的上一句是什么,怎么理解一览众山小的意思?
  8. 关于《啊哈!算法》相关资源
  9. 有赞实时任务优化:Flink Checkpoint 异常解析与应用实践
  10. 数据分块算法java_分块查询算法(JAVA)
  11. 戴尔微型计算机7050配置,戴尔 Dell OptiPlex 7060 微型机体验分享 - 1升的迷你小钢炮...
  12. 上海臻图信息3DGIS+BIM技术助力智慧城市地下综合管廊建设
  13. github协同工作流程(一)
  14. private的使用
  15. 谷歌admob测试设备测试流程
  16. 暂时解决Xmarks无法同步
  17. 在useEffect中使用了setState,报错
  18. 你知道为什么zip始终不兼容rar吗?
  19. 2021年红包封面小程序源码独立后台无限裂变线上线下引流工具微信流量主小程序
  20. 对1976年Diffie和Hellman的文章《New Direction in Cryptography》的中文翻译

热门文章

  1. 洛谷P4727:图的同构计数(Polya引理)(dfs)
  2. 模板:快速莫比乌斯变换(FMT)+快速沃尔什变换(FWT)(多项式)
  3. Loj#3130-「COCI 2018.12」Praktični【线性基】
  4. 牛客挑战赛43C-最优公式【二分】
  5. P3470 [POI2008]BBB-BBB【线段树,贪心】
  6. ssl2648-线段树练习5【线段树】
  7. 【spfa】假期计划(jzoj 3936)
  8. 纪中C组模拟赛总结(2019.8.9)
  9. GYM 101908F - Music Festival
  10. 4、mybatis通过配置类Configuration 实现初始化