怎么写出干净有用的日志

阅读更多
这个话题并不新鲜,Google一下“Logging Best Practices”会发现很多相关的资料。日志Log在开发中是非常重要的程序的一部分,如何写出Clean、Readable、Helpful、Descriptive的日志是程序员的基本功!

对于普通开发人员来说,如果程序遇到问题,第一个想到的肯定是看日志Log,可以通过查看日志Log发现出了什么错,便于开发,调试程序,试想如果程序crash了,没有日志Log,发生了什么将一无所知。

很多人忽略日志的重要性,日志可以记录程序的运行状况,出现问题时以便分析。日志不仅是给程序员自己看的,对于系统管理员来说也可以通过写脚本来分析日志,提取对系统运维有用的东西。系统运维相关工具的依据就是日志Log,所以自动监视系统、系统运维人员、系统管理员、开发人员等等,都需要日志Log。

(1)日志种类
根据程序的类型不同,日志种类又很多,比如:
  • 操作系统的Log(Windows的Event Log)
  • 各个应用程序的Log
  • Web服务器的访问日志(Apache的access_log、Nginx的access.log)
  • Web应用的日志
等等
很多应用在出现致命错误的时候,其实都会把相应的日志文件上传到服务器去以便分析。

(2)日志工具
基于Java的应用,可选的Logger有很多,而且很多开源框架使用的也不同。
比如Guava使用JUL、Spring和Apache的框架都是用Apache Commons Logging、
  • Apache Log4j (1999-2008)
  • Apache Commons Logging (JCL, ACL) (2002)
  • java.util.logging (JUL) (2002)
  • Logback (2006-)
  • SLF4J (2007-)
  • Apache Log4j2 (2012-)
  • Netflix Blitz4j (2012-)
不要使用原始的System.out.println("Hello world!");

(3)基础知识
  • 输出Log时避免自己出错
  • 过多的日志会拖慢系统
  • 日志至少应该包含描述和数据
  • 重要的日志应该添加特殊的可搜索字符
  • 不要输出密码、个人信息、信用卡信息等敏感数据
  • 输出重要方法的参数和返回值
  • 输出重要方法的开始和结束(异常时是否输出结束日志?)
  • 如果和外部系统链接,需要输出INPUT和OUTPUT
  • 合理输出异常信息(不要主动输出异常,合理通过框架、共通代码输出;避免异常被输出多次)
  • 考虑数据的输出格式,最好输出多种格式利用人看或者工具分析
  • 合理输出二进制文件信息(name、size)

(4)输出形式
1) 键值对
引用
key1=value1, key2=value2, key3=value3 . . .

2) JSON
引用
{ "sender" : "michael" "recipient": { "name" : "michael", "name" : "andrea", "name" : "itay" } subject:"I heart logs" }

对于一个Bean对象来说,需要注意他的输出形式,比如对象的Serialization、或者覆写toString()、commons-lang的ToStringBuilder、Arrays#deepToString、Beanutils#collect等等,都可以提高可读性。

(5)日志级别
可能你知道INFO、WARN、ERROR、DEBUG、TRACE,但是90%的开发人员在输出日志的时候就没考虑过日志的级别,只是简单的使用统一级别。
系统上线后会被调整的最优化的级别,而且不同的人会看不同的日志。

(6)配置日志Log
输出格式pattern:
引用
%d{HH:mm:ss.SSS} %-5level [%thread][%logger{0}] %m%n

Apache
引用
192.168.56.6 - - [24/Sep/2012:11:11:11 +0900] "GET /info.php HTTP/1.0" 200 9 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:10.0.7) Gecko/20120829 Firefox/10.0.7"

Ngnix
引用
192.168.21.198 - - [06/Mar/2015:18:19:06 +0900] "GET /index.php HTTP/1.1" 200 87243 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.3.4000 Chrome/30.0.1599.101 Safari/537.36"


设置级别:

Rotate日志文件:
日志文件会占用大量的磁盘空间,所以必须rotate日志文件

(7)常见错误
  • 设置错误的日志级别
  • Catch异常后再Throw
  • 日志输出到stderr 或 stdout (System.out.println / e.printStackTrace)
  • 复杂的日志代码
引用
Diagnostic Contexts
Contextual logging (e.g. thread name, userId)
Available on log4j, logback, and log4j2
Two different types: Nested & Mapped

NDC
Nested Diagnostic Contexts are stacks
NDC.push(“x”);
NDC.pop();
Useful for debugging looping or recursive structures

MDC
Mapped Diagnostic Context
key-value pairs
MDC.put(“userId”, user.getId())
Usually what you’ll use
Show up in Graylog using the Graylog Appender


怎么写出干净有用的日志_第1张图片
怎么写出干净有用的日志_第2张图片

参考:
Java日志终极指南
Good Logging Practices
10 Tips for Proper Application Logging
Benchmarking Java Logging Frameworks
Java Logging API
Ultimate Guide for Logging
Log4j Best Practices
  • 怎么写出干净有用的日志_第3张图片
  • 大小: 50.7 KB
  • 怎么写出干净有用的日志_第4张图片
  • 大小: 21.5 KB
  • 查看图片附件

你可能感兴趣的:(怎么写出干净有用的日志)