Java编码常见的Log日志打印问题
前言
本文总结了作者在Java代码检视中遇到的一些关于日志打印的问题,并给出修改建议。因能力有限,难免存在错漏,欢迎指正。
一. 不规范的异常打印
使用slf4j日志组件时,logger.error(与log.warn)接受Throwable参数,以打印异常名和详细的堆栈信息(可能内部调用e.printStackTrace())。
但书写打印语句时,需要注意格式。例如:
logger.error("Best print: ", e);
logger.error("Good print: {}", e); //a.
logger.error("Bad print: " + e); //b. 或 + e.toString()
logger.error("Bad print: " + e.getMessage()); //c. 或: {}", e.getMessage())
a句仍可打印异常名和堆栈信息,但多输出一对花括号"{}";b句仅打印异常名;c句打印异常消息字符串。以空指针异常(Runtime异常)为例,b句打印"java.lang.NullPointerException",c句打印"null"(过于简陋)。
可使用如下正则表达式排查Java代码里不规范的异常打印:
^\s*[Ll][Oo][Gg](ger|GER)*\.(error|warn)\("(.+?)"\s*\+\s*(e|ex|e.getMessage\(\))\s*\);.*
该正则表达式可排查出形如上文b、c句的打印缺陷。考虑到实际代码书写风格的差异,会存在少量的漏判和误判。此外应注意,某些异常(如SQL或IO异常)可能泄露敏感信息,打印异常堆栈之前应根据网络安全要求做必要的”加工”。
二. 不规范的变量打印
使用slf4j日志组件打印变量时,建议使用”{}”占位符风格(C风格),而不是”+”拼接符(C++风格)。例如:
logger.error("Country: {}, Province: {}, City: {}", ctry, prov, city); //占位符
logger.error("Country: "+ctry+", Province:" +prov +", City: "+city); //拼接符
显然,占位符风格更直观,而且不容易出现笔误——上面的拼接符语句有问题,谁能发现?
但最常见的变量打印问题,是打印时未使用占位符或拼接符:
logger.error("print cannotBePrinted: ", cannotBePrinted); //Wrong
logger.error("print canBePrinted: " + canBePrinted); //Good
logger.error("print canBePrinted: {}", canBePrinted); //Better
注意,cannotBePrinted或canBePrinted为非Throwable的变量。亦即,异常变量e不适用上述规则,但e.getMessage()适用。
可使用如下正则表达式排查Java代码里不规范的变量打印:
^\s*[Ll][Oo][Gg](ger|GER)*\.[a-zA-Z]{4,5}\("([^({})]+?)"\s*\,\s*([^e\s]|\w{2,})\s*\);.*
考虑到实际代码书写风格的差异,该正则表达式会存在漏判和误判。例如,"logger.error("Best print: ", ex);"会被误判。
三. 多余的DEBUG级别判断
使用slf4j日志组件以Debug级别打印时,debug()方法内部会调用isDebugEnabled()判断调试级别。因此,下述代码里的判断没有必要:
if(logger.isDebugEnabled())
{
logger.debug("handleChanges end:{}:{}(ms) ", new Object[] {changes, useTime});
}
四. 日志对象logger的声明
一般建议日志对象logger声明为private static final。声明为private可防止logger对象被其他类非法使用。声明为static可防止重复new出logger对象,造成资源浪费;还可以防止logger被序列化,造成安全风险。声明为final是因为在类的生命周期内无需变更logger。
然而,实际编码中可根据使用场景稍作变通。例如,static final成员变量通常要求大写(如LOGGER),如果觉得大写别扭,可以去除final修饰。又如,期望logger对象可复用时,可如下定义:
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
这样,子类可以直接使用继承来的logger对象打印输出,而无需再次getLogger()获取日志对象。
五. 日志级别应合理
如果日志不分级别或级别不合理,则定位问题时就无法快速有效地屏蔽大量低级别信息,给快速定位带来难度。建议与具体实现有关的日志使用debug级,一般的业务处理日志用info级,不影响业务进行的错误用warn级,而记录异常或重要错误的日志应为error级。
Java编码常见的Log日志打印问题的更多相关文章
- android的Log日志打印管理工具类(一)
android的Log日志的打印管理工具类: package com.gzcivil.utils; import android.util.Log; /** * 日志打印管理 * * @author ...
- 超高逼格Log日志打印
代码地址如下:http://www.demodashi.com/demo/12646.html 前言 Log日志的打印一直是一个比较头疼的事,怎样才能让自己的log显示更多信息,怎样才能让自己的log ...
- Javascript 将 console.log 日志打印到 html 页面中
如何将 console.log() 打印的日志输出到 html 页面中 (function () { var old = console.log; var logger = document.getE ...
- 树莓派 log 日志 打印到 TXT
#include<stdio.h> #include <stdarg.h> #include <unistd.h> #include <stdint.h> ...
- java最简单实现Log打印和生成日志文件
导包 1.commons-logging.jar包 下载 2.log4j.jar包 下载 配置log4j 1.在src根目录下创建一个log4j.properties文件. 文件全部内容如下: log ...
- 大数据项目中js中代码和java中代码(解决Tomcat打印日志中文乱码)
Idea2018中集成Tomcat9导致OutPut乱码找到tomcat的安装目录,打开logging.properties文件,增加一行代码,覆盖默认设置,将日志编码格式修改为GBK.java.ut ...
- Xposed框架Hook Android应用的所有类方法打印Log日志
本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80954759 在进行Android程序的逆向分析的时候,经常需要Android程 ...
- java log日志的输出。
在Spring框架中添加日志功能: pom.xml <dependency> <groupId>log4j</groupId> <artifactId> ...
- java中关于log日志
博:http://zhw2527.iteye.com/blog/1006302 http://zhw2527.iteye.com/blog/1099658 在项目开发中,记录错误日志是一个很有必要功能 ...
随机推荐
- Codeforces Round #428 (Div. 2) D. Winter is here 容斥
D. Winter is here 题目连接: http://codeforces.com/contest/839/problem/D Description Winter is here at th ...
- python之函数第一篇
一.为什么用函数: 解决代码重用问题 统一维护 程序的组织结构清晰,可读性强二.定义函数 先定义后使用!! def funcname(arg1,arg2,...): """ ...
- flask之基础知识点
本篇导航: 路由系统 视图函数 请求与响应 模版语法 session 蓝图(blueprint).闪现 (flash) 扩展 一.路由系统 1.可传入参数: @app.route('/user/< ...
- MediaInfo代码阅读
MediaInfo是一个用来分析媒体文件的开源工具. 支持的文件非常全面,基本上支持所有的媒体文件. 最近是在做HEVC开发,所以比较关注MediaInfo中关于HEVC的分析与处理. 从Meid ...
- [Web 前端] mobx教程(二)-mobx主要概念
cp from : https://blog.csdn.net/smk108/article/details/84960159 通过<Mobx教程(一)-Mobx简介>我们简单理解了Mob ...
- too much recursion(太多递归)Uncaught RangeError: Maximum call stack size exceeded BootstrapValidator报错
在BootstrapValidator中已默认遵守Bootstrap规则,form里的每个输入项目必需包含在类为form-group的标签里,否则BootstrapValidator中定义的field ...
- 【问题与解决】Mac OS通过 npm 安装 React Native 报错(checkPermissions Missing write access to /usr/local/lib/node_modules)
报错情况: 当Mac OS通过 npm 安装 React Native 报错,警告文字为:checkPermissions Missing write access to /usr/local/lib ...
- SSE图像算法优化系列二十四: 基于形态学的图像后期抗锯齿算法--MLAA优化研究。
偶尔看到这样的一个算法,觉得还是蛮有意思的,花了将近10天多的时间研究了下相关代码. 以下为百度的结果:MLAA全称Morphological Antialiasing,意为形态抗锯齿是AMD推出的完 ...
- WPF参考
web 调用本地exe 程序,传入参数https://www.cnblogs.com/anjou/p/10045177.html WPF常用控件样式https://www.cnblogs.com/s0 ...
- PL/SQL学习笔记程序单元
一:程序单元组成 一个PL/SQL程序单元主要包括三部分: 声明与定义部分:声明变量.常量.类型等:定义过程.函数等: 执行部分:执行PL/SQL语句:调用过程.参数:处理游标等: 异常处理部分:处理 ...