日志基础

定义

a logfile is a file that records either events that occur in an operating system or other software runs, or messages between different users of a communication software .
日志文件是记录在操作系统或其他软件运行中发生的事件或者在通信软件的不同用户之间的消息的文件。

分类

  • 系统日志
  • 应用服务器日志
  • 应用日志
  • 用户日志

1. 系统日志

记录操作系统上发生的各种事件,包括用户的登陆,服务的启动与关闭,进程的崩溃等时间,可以通过系统日志定额为相关故障产生原因并进行修复、 目前,象Windows的系统日志已经具有完善的图形化界面,用户可以很方便的对日织金县查看与分析

windows系统日志

windows系统日志2

2. 应用服务器日志

这里指的包括Nginx,Apache也包括tomcat等服务器 服务器会将平日的运行信息进行记录,当出现自身不可修复的异常时,运维等人员便可通过日志将异常进行定位,再现异常场景或者进行原因分析

3. 应用日志

应用自身负责记录的日志,存储自身事件
(in order to provide an audit trail that can be used to understand the activity of the system and to diagnose problems..) 同样应该重点关心的是系统产生的异常事件(WARN级别以上的日志),对于普通事件(info级别)我们可以只进行记录而不进行存储,而且需要将应用日志与用户日志进行区别,应用日志只针对应用自身产生的事件进行记录,不关注用户的行为,而且应用日志一般存储在服务器端。

4. 用户日志
用户日志更加关注的是用户的行为,一般来说用户日志和应用日志的数量有很大的数量级上的差距,用户日志主要春初在客户端,服务提供者通过分析用户日志可以得到用户画像,从而可以对用户进行分析,完成相关内容推荐

Java日志体系

Java使用了一种自定义的、可扩展的方法来输出日志。虽然Java通过java.util.logging包提供了一套基本的日志处理API,但你可以很轻松的使用一种或者多种其它日志解决方案。这些解决方案尽管使用不同的方法来创建日志数据,但它们的最终目标是一样的,即将日志从你的应用程序输出到目标地址。

Java日志组件

Java日志API由以下三个核心组件组成:

  • Loggers:Logger负责捕捉事件并将其发送给合适的Appender。
  • Appenders:也被称为Handlers,负责将日志事件记录到目标位置。在将日志事件输出之前,Appenders使用Layouts来对事件进行格式化处理。
  • Layouts:也被称为Formatters,它负责对日志事件中的数据进行转换和格式化。Layouts决定了数据在一条日志记录中的最终形式。 当Logger记录一个事件时,它将事件转发给适当的Appender。然后Appender使用Layout来对日志记录进行格式化,并将其发送给控制台、文件或者其它目标位置。另外,Filters可以让你进一步指定一个Appender是否可以应用在一条特定的日志记录上。在日志配置中,Filters并不是必需的,但可以让你更灵活地控制日志消息的流动。

日志框架

在Java中,输出日志需要使用一个或者多个日志框架,这些框架提供了必要的对象、方法和配置来传输消息。Java在java.util.logging包中提供了一个默认的框架。除此之外,还有很多其它第三方框架,包括Log4j、Logback以及tinylog。还有其它一些开发包,例如SLF4J和Apache Commons Logging,它们提供了一些抽象层,对你的代码和日志框架进行解耦,从而允许你在不同的日志框架中进行切换。

如何选择一个日志解决方案,这取决于你的日志需求的复杂度、和其它日志解决方案的兼容性、易用性以及个人喜好。Logback基于Log4j之前的版本开发(版本1),因此它们的功能集合都非常类似。然而,Log4j在最新版本(版本2)中引用了一些改进,例如支持多API,并提升了在用Disruptor库的性能。而tinylog,由于缺少了一些功能,运行特别快,非常适合小项目。

另外一个考虑因素是框架在基于Java的各种不同项目上的支持程度。例如Android程序只能使用Log4j、Logback或者第三方包来记录日志, Apache Tomcat可以使用Log4j来记录内部消息,但只能使用版本1的Log4j。

1. java.util.logging

默认的Java日志框架将其配置存储到一个名为 logging.properties 的文件中。在这个文件中,每行是一个配置项,配置项使用点标记(dot notation)的形式。Java在其安装目录的lib文件夹下面安装了一个全局配置文件,但在启动一个Java程序时,你可以通过指定 java.util.logging.config.file 属性的方式来使用一个单独的日志配置文件,同样也可以在个人项目中创建和存储 logging.properties 文件。

下面的示例描述了如何在全局的logging.properties文件中定义一个Appender:

# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XmlFormatter

2. Log4j

Log4j版本1使用的语法和 java.util.logging 的语法很类似。使用了Log4j的程序会在项目目录中寻找一个名为 log4j.properties 的文件。默认情况下,Log4j配置会将所有日志消息输出到控制台上。Log4j同样也支持XML格式的配置文件,对应的配置信息会存储到 log4j.xml 文件中。

Log4j版本2支持XML、JSON和YAML格式的配置,这些配置会分别存储到 log4j2.xml、log4j2.json 和 log4j2.yaml 文件中。和版本1类似,版本2也会在工程目录中寻找这些文件。你可以在每个版本的文档中找到相应的配置文件示例。

3.LogBack

对于Logback来说,大部分配置都是在 logback.xml 文件中完成的,这个文件使用了和Log4j类似的XML语法。Logback同时也支持通过Groovy语言的方式来进行配置,配置信息会存储到 logback.groovy 文件中。你可以通过每种类型配置文件的链接找到对应的配置文件示例。

日志的使用

几点建议

1.记录技术性异常而不是用户异常

用户异常(如:“登录用户名已经存在”)除了显示给用户,要么什么都别管,要么根本就不是异常(“用户尚未认证”)。技术性异常(如:“文件存储不够,没法订阅此产品”)才是你需要调试而为此做出反应的,如果你记录所有事情很有可能因日志实体太长而不能真正有意义的反映到你所记录异常日志中。你应该查明日志文件中的每个异常找到其原因(“是bug吗”),过多的异常将使你草率地对待异常(“额,仅仅是一个普通异常”)。
PS:这点在上面的用户日志与应用日志里谈到了,这里补充一下,对于用户某些行为比如密码错误,验证码错误,系统本神并不需要关注,它对系统基本没有价值,而对于某些用户的行为则可能需要记录,比如用户访问一个不存在的url导致404,因为此时肯呢过是某些攻击者在尝试破解你的系统,需要详细记录用户信息。而对于用户行为导致的500等异常则尤其需要重点关注

2.把数据存储在异常中以便更易于记录

试着在日志记录异常时带上产生的数据,比如当某个request处理时产生了500异常,记录request的参数有利于对于不过进行定位修复并测试

3. 记录异常的描述信息

糟糕的例子来自于Sun:ClassCastException不能显示什么类你想要转换。 现在甚至可以发现:

final String s = "Hello";
final int x = (Integer) s;

在编译时就告诉你:

T.java:4: inconvertible types
found : java.lang.String
required: java.lang.Integer
final Integer x = (Integer) s; 在运行期间Java抛出的异常

Exception in thread "main" java.lang.ClassCastException:
java.lang.String cannot be cast to java.lang.Integer

4. 输出导致异常的原因

如果在异常中有一个包装的方式作为异常的起因,那么记录所有的原因。一些日志框架已经帮你这样做了,有些还没有,因此要确保异常的所有原因记录在日志文件中,保证所有相关的堆栈追踪信息的开始处记录在你的文件中,而不是杂乱无章的。

选择合理的日志级别

Java中共有7个日志级别,对于info以下的日志级别,并不予以记录,因此我们需要选择合适的日志级别

  • TRACE 一般情况下我会用来记录业务日志
  • WARN 我一般会在出现了异常情况,但是又在业务的合理范围之类的时候我会适应warn
  • INFO 一般非常重要的日志,关键系统参数的回显、后台服务的初始化状态、需要开发者确认的信息我都会适应INFO这个级别。
  • DEBUG 详细的记录流程的关键路径,这种级别的日志是为了方便我们开发和调试系统功能的,在生产环境默认是关闭的。
  • ERROR 系统出现了异常情况的时候时候
  • FATAL 说实话我没有用过,我都用ERROR代替了

不要记录后又重新向外抛出

这样将会导致一个 反模式,导致日志被重复记录

日志是可读的

因此我们需要选择合适的格式化器(formatter),过滤不必要的信息,保存有用的信息(时间,原因等),使日志整体简单易读

日志的存储与分析

你需要考虑

  • 什么日志需要被保存
  • 日志保存时间为多长
  • ....

日志展示这里推荐elk,即elasticsearch + logstash + kibana,这是一套成熟的日志展示及分析平台,有兴趣的小伙伴可以一起来玩!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

文献参考

  1. Java日志终极指南l 原文链接: loggly 翻译: ImportNew.com - Wing

  2. 记录日志的7条规则 英文原文:Codemonkeyism,编译:ImportNew - 刘志军

zbyte

Read more posts by this author.

分享一下

查看评论