日志作用
一般在程序上线之后,一旦发生异常,第一件事
就是要弄清楚当时发生了什么
。用户
当时做了什么操作
,环境有无影响
,数据有什么变化
,是不是反复发生
等,然后再进一步的确定大致是哪个方面的问题
。确定是程序的问题之后再交由开发人员去复现
、研究
、提出解决方案
。这时,日志就给我们提供了第一手的资料。
1、 记录用户操作的审计日志,甚至有的时候就是监管部门的要求
2、 快速定位问题的 根源
3、 追踪程序执行的 过程
4、 追踪 数据的变化
5、 数据 统计 和 性能 分析
6、 采集 运行环境 数据
Log4j
Log4j的组成
三个重要的组成构成:日志记录器(Loggers)
,输出端(Appenders)
和日志格式化器(Layout)
Logger
控制要 启用 或 禁用 哪些日志记录语句,并对日志信息进行 级别限制
Appenders
指定了 日志将打印到 控制台 还是 文件中
Layout
控制日志信息的 显示格式
日志级别
log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:off、fatal、error、warn、info、debug、trace、 all。
Log4j 建议 只使用 四个级别,优先级 从高到低 分别是
DEBUG < INFO < WARN < ERROR
-
ALL
:最低等级的,用于打开所有日志记录
。 -
TRACE
: designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用
,TRACE一般跟踪的是函数的调用
,并且TRACE不应该含有变量参数
,而仅能提示函数的调用关系
-
DEBUG
: 指出细粒度信息事件
对调试应用程序
是非常有帮助的,主要用于开发过程中打印一些运行信息
。 -
INFO
: 消息在粗粒度级别上突出强调应用程序的运行过程
。打印一些你感兴趣的或者重要的信息
,这个可以用于生产环境中输出程序运行的一些重要信息
,但是不能滥用,避免打印过多的日志
。 -
WARN
: 表明会出现潜在错误
的情形,该级别表示程序会自动调整到正常的状态
,类似参数未传入
,使用了默认的参数
,仍符合
程序员预期之内
的情况。 -
ERROR
: 指出虽然发生错误事件
,但仍然不影响系统的继续运行
。打印错误和异常信息
,如果不想输出太多的日志
,可以使用这个级别。一般在WARN之后的级别
在打印错误时
,应该同时打印错误码
-
FATAL
: 指出每个严重的错误事件将会导致应用程序的退出
。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。 -
OFF
: 最高等级的,用于关闭所有日志记录
。
如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来
。
级别关系
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来,也是说大于等于的级别的日志才输出。
例如,如果设置优先级为 WARN,那么 OFF、FATAL、ERROR、WARN 4个级别的 log 能正常输出,而 INFO、DEBUG、TRACE、 ALL 级别的log则会被忽略
。
从实验的结果可以看出,log4j默认的优先级为 ERROR 或者 WARN(实际上是ERROR
)。
撰写日志的要求
日志的可读性
日志时给人读的,不仅仅是让自己明白,也要让没有接触过我们源代码的其他程序员也能够一目了然。
不要打印特殊的标识符号
,例如“++++++++++”, “===========”,“—————”
,这些符号令人眼花缭乱
另外,把日志分类输出到不同的文件
也有利于排除干扰
,迅速
找到需要的信息
最好在打印日志时输出英文
,防止中文不支持而打印出乱码
的情况
日志的性能
写到文件还是数据库
,都需要消耗IO资源
。
适当的控制日志的输出
也有利于提高程序的性能
例如:
尽量 避免在在 大的循环 中 打印意义不大 的 日志内容
输出日志之前最好能 判断日志的级别 (例如. debug前先调用isDebugEnabled()作出判断)
占用磁盘空间
把日志写入磁盘上的日志文件
中。适当的使用滚动日志
并且定时清除旧文件
。避免日志文件占满磁盘空间
导致程序运行错误
日志的时效性
有的时候不能及时的发现问题
。需要追溯之前的日志
。所以需要保留一段时间
以内的日志便于追溯
日志内容
尽量使用业务相关的描述
。程序是实现某种业务的,那么就最好能描述清楚这个时候走到了业务过程的哪一步
。
避免
在日志中输出一些敏感信息
,例如用户名和密码
。
要保持编码的一致
。如果不能保证就尽量使用英文而不是中文
日志格式
日志应含有的信息包括日期、时间、日志级别、代码位置、日志内容、错误码
等信息
2022-05-22 15:35:53.850 TRACE TDWZLog [0x00001b10] <36> <TDWZProtocol::Init>,TDWZProtocol::Init
2022-05-22 15:35:53.850 TRACE TDWZLog [0x00001b10] <89> <TDWZProtocol::Init>,End in processing TDWZProtocol::Init
2022-05-22 15:35:53.853 TRACE TDWZLog [0x00001b10] <142> <TDWZProtocol::Connect>,Connect Execute finish
2022-05-22 15:35:53.853 TRACE TDWZLog [0x00002f10] <149> <GetAlarmEventPro>,Enter GetAlarmEventPro func
2022-05-22 15:39:36.382 WARN TrackLog [0x000029fc] - [ internal WARN htrace_server_convert_msgstring_to_contextintls(493) ] detect input id error, trace_id span_id,this chain may not be tracked.
2022-05-22 15:39:36.383 WARN TrackLog [0x000029fc] - [ internal WARN htrace_server_receive(195) ] can not detect trace_id in context, this chain may not be tracked.
2022-05-22 15:39:36.383 TRACE TDWZLog [0x000029fc] <231> <TDWZProtocol::DisConnect>,TDWZProtocol::DisConnect
2022-05-22 15:39:37.502 TRACE TDWZLog [0x00002f10] <225> <GetAlarmEventPro>,End Get AlarmEventPro Func
2022-05-22 15:39:37.503 TRACE TDWZLog [0x000029fc] <241> <TDWZProtocol::DisConnect>,close socket
2022-05-22 15:39:37.503 TRACE TDWZLog [0x000029fc] <242> <TDWZProtocol::DisConnect>,Execute DisConnect function succeed.
日志指定颜色打印
log.info(color + "xxx" + color + "xxx");
System.out.println(ConsoleColors.RED + "RED COLORED" +ConsoleColors.RESET + " NORMAL");
log.info(ConsoleColors.RED + "RED COLORED" +ConsoleColors.RESET + " NORMAL");
public class ConsoleColors {
// Reset
public static final String RESET = "\033[0m"; // Text Reset
// Regular Colors
public static final String BLACK = "\033[0;30m"; // BLACK
public static final String RED = "\033[0;31m"; // RED
public static final String GREEN = "\033[0;32m"; // GREEN
public static final String YELLOW = "\033[0;33m"; // YELLOW
public static final String BLUE = "\033[0;34m"; // BLUE
public static final String PURPLE = "\033[0;35m"; // PURPLE
public static final String CYAN = "\033[0;36m"; // CYAN
public static final String WHITE = "\033[0;37m"; // WHITE
// Bold
public static final String BLACK_BOLD = "\033[1;30m"; // BLACK
public static final String RED_BOLD = "\033[1;31m"; // RED
public static final String GREEN_BOLD = "\033[1;32m"; // GREEN
public static final String YELLOW_BOLD = "\033[1;33m"; // YELLOW
public static final String BLUE_BOLD = "\033[1;34m"; // BLUE
public static final String PURPLE_BOLD = "\033[1;35m"; // PURPLE
public static final String CYAN_BOLD = "\033[1;36m"; // CYAN
public static final String WHITE_BOLD = "\033[1;37m"; // WHITE
// Underline
public static final String BLACK_UNDERLINED = "\033[4;30m"; // BLACK
public static final String RED_UNDERLINED = "\033[4;31m"; // RED
public static final String GREEN_UNDERLINED = "\033[4;32m"; // GREEN
public static final String YELLOW_UNDERLINED = "\033[4;33m"; // YELLOW
public static final String BLUE_UNDERLINED = "\033[4;34m"; // BLUE
public static final String PURPLE_UNDERLINED = "\033[4;35m"; // PURPLE
public static final String CYAN_UNDERLINED = "\033[4;36m"; // CYAN
public static final String WHITE_UNDERLINED = "\033[4;37m"; // WHITE
// Background
public static final String BLACK_BACKGROUND = "\033[40m"; // BLACK
public static final String RED_BACKGROUND = "\033[41m"; // RED
public static final String GREEN_BACKGROUND = "\033[42m"; // GREEN
public static final String YELLOW_BACKGROUND = "\033[43m"; // YELLOW
public static final String BLUE_BACKGROUND = "\033[44m"; // BLUE
public static final String PURPLE_BACKGROUND = "\033[45m"; // PURPLE
public static final String CYAN_BACKGROUND = "\033[46m"; // CYAN
public static final String WHITE_BACKGROUND = "\033[47m"; // WHITE
// High Intensity
public static final String BLACK_BRIGHT = "\033[0;90m"; // BLACK
public static final String RED_BRIGHT = "\033[0;91m"; // RED
public static final String GREEN_BRIGHT = "\033[0;92m"; // GREEN
public static final String YELLOW_BRIGHT = "\033[0;93m"; // YELLOW
public static final String BLUE_BRIGHT = "\033[0;94m"; // BLUE
public static final String PURPLE_BRIGHT = "\033[0;95m"; // PURPLE
public static final String CYAN_BRIGHT = "\033[0;96m"; // CYAN
public static final String WHITE_BRIGHT = "\033[0;97m"; // WHITE
// Bold High Intensity
public static final String BLACK_BOLD_BRIGHT = "\033[1;90m"; // BLACK
public static final String RED_BOLD_BRIGHT = "\033[1;91m"; // RED
public static final String GREEN_BOLD_BRIGHT = "\033[1;92m"; // GREEN
public static final String YELLOW_BOLD_BRIGHT = "\033[1;93m";// YELLOW
public static final String BLUE_BOLD_BRIGHT = "\033[1;94m"; // BLUE
public static final String PURPLE_BOLD_BRIGHT = "\033[1;95m";// PURPLE
public static final String CYAN_BOLD_BRIGHT = "\033[1;96m"; // CYAN
public static final String WHITE_BOLD_BRIGHT = "\033[1;97m"; // WHITE
// High Intensity backgrounds
public static final String BLACK_BACKGROUND_BRIGHT = "\033[0;100m";// BLACK
public static final String RED_BACKGROUND_BRIGHT = "\033[0;101m";// RED
public static final String GREEN_BACKGROUND_BRIGHT = "\033[0;102m";// GREEN
public static final String YELLOW_BACKGROUND_BRIGHT = "\033[0;103m";// YELLOW
public static final String BLUE_BACKGROUND_BRIGHT = "\033[0;104m";// BLUE
public static final String PURPLE_BACKGROUND_BRIGHT = "\033[0;105m"; // PURPLE
public static final String CYAN_BACKGROUND_BRIGHT = "\033[0;106m"; // CYAN
public static final String WHITE_BACKGROUND_BRIGHT = "\033[0;107m"; // WHITE
}