为什么说这么一个标题,其实还是有点故事的,其实说是故事还不如说是事故,庆幸的是还好没有造成什么大的问题,既然说删了两台服务器,上个月确实是操作删了两台服务器。由于测试环境有问题,客户就一直让我们在正式环境上开发,所以有时候就会造成一些问题,总之很刺激,也很危险。
简单说一下是怎么个情况吧,上个月客户让我测一个接口,但是那个接口只能在线上测,所以我就点了一个释放资源,那个资源里面就是下发下去的两台服务器,由于没有很好的日志记录所以当时也不知道到底是谁释放的,当然了,不是我死不承认,而是我也不知道,然后他们查出来我的电脑IP,直接找过来了,可吓坏我了,还好人家那两台服务器没有投入使用,让我以后操作小心一点。是不是很刺激。
看了这个问题,其实我想说一个问题,就是我们的项目当时没有很好的日志管理,以至于谁删了服务器都不知道,还要去追查一周才能定位到是谁干的,很慢,那么如果有良好的日志记录,谁干了什么翻翻日志,是不是就可以很清楚的知道是谁操作的,所以我们今天来聊聊日志。
一、日志级别
在了解日志之前我们首先要知道有哪些日志级别,开发中我们使用哪个级别,正式的线上环境我们又使用哪个级别。
off 最高等级,用于关闭所有的日志记录;
fatal 具有严重的错误时间,可能导致程序退出;
error 可能存在错误时间的发生,但是不会影响程序的运行;
warn 存在潜在的错误;
info 记录程序运行的过程;
debug 会记录所有的日志信息,比info打印的东西更为全面,一般做调试非常好用;
all 等级最低,用于打开所有的日志记录;
这就是我们日志的级别,分别从高到低,日志级别越高,记录的日志信息就越详细,那么在实际的开发中,我们一般使用debug级别, 因为我们要看很多的日志信息,因为可能存在一些东西,我们要通过日志去进行查看,那么在线上的话,我们就一般使用error级别,因为我们只需要去记录一些错误的东西,一些其他没用的信息没必要记录下来,记录下来会比较影响我们的系统的性能。
二、简单的配置
接下来我们介绍一下,如果配置我们的log4j日志信息,我们输出的那些东西,究竟是如何进行配置的。
首先我们说一下文件追加器:
org.apache.log4j.ConsoleAppender (控制台);
org.apache.log4j.FileAppender (文件);
org.apache.log4j.DailyRollingFileAppender (每天产生一个日志文件);
其实文件追加器不止这3种,但是我们这里只说常用的集中,通过追加器我们就可以把日志输出在控制台上,但是输出在控制台上当我们清掉控制台后,日志就不见了,所以我们可以通过配置文件追加器把日志写进文件中,方便以后的查阅。
日志如何输出到文件:
上面已经写过了,这里我就写一个实例;
log4j.appender.I.File = logs/info/info_
这是我项目中配置的,那么这个日志的输出位置就是在我项目下面的logs文件夹下面有个info文件夹,就在info_这个文件中记录着。
还有一个输出控制台的配置,通过这个配置,我们就可以把日志输出到控制台上
log4j.appender.C.Target = System.out
再就是布局方式,其实有好集中,但是在开发中我们常规的是使用下面这种
log4j.appender.C.layout = org.apache.log4j.PatternLayout
这个配置的意思就是,我们的日志是追加到原有的日志文件中去的,如果不设置为true,那么每次产生的日志文件都会覆盖原来的日志文件
log4g.appender.I.Append = true
其实所有的日志记录在一个文件中也不是一个特别好的办法,如果日志很多,找起来特别麻烦,也很影响系统的性能,所以我们可以通过配置,让他一天生成一个日志文件
log4j.appender.I.DatePattern=yyyy-MM-dd'.log '
这个其实就是你打印在控制台和记录在文件中的日志格式
log4j.appender.I.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm} method:%l\%n%m%n
看个例子:
这个是控制台打印的信息
这个是日志文件记录的信息
这样你就可以比较清晰的看到我们的日志信息是什么级别的日志,什么时间,哪个类,多少行,你还可以配置你想要的日志格式,我把一些参数放在下面。
log4j.appender.C.layout.ConversionPattern = %d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
%d 输出日志时间点的日期或时间。默认格式为ISO8601,也可以在其后指定格式。比如:%d{yyy MMM dd HH:mm:ss , SSS},输出类似:2002年10月18日 22:10:28, 921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
还有一点就是下面这个配置,上面的有些C I E D可能大家不知道是什么意思,其实它就是一个变量,变量前面的debug就是我们日志输出的级别。
log4j.rootLogger = debug,C,I,E,D
所谓变量其实就是通过它配置我们的日志信息,下面分别定义了两个变量I和E,下面有个log4j.append.E.Threshold = error这样一个配置,其实就是通过E这个变量去定义E,这个变量记录的是error级别的日志,那么有关error的信息,那么都会写进这个对应的文件中
最后把我写的日志文件信息完整版放在最后,欢迎大家参考交流:
# C 变量
log4j.rootLogger = debug,C,I,E,D
log4j.appender.C = org.apache.log4j.ConsoleAppender
# 日志输出位置,也可以指定为文件
log4j.appender.C.Target = System.out
# 布局方式,一般选择自由方式布局
log4j.appender.C.layout = org.apache.log4j.PatternLayout
# 日志输出格式
log4j.appender.C.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm} method:%l\%n%m%n
log4j.appender.I = org.apache.log4j.DailyRollingFileAppender
log4j.appender.I.DatePattern=yyyy-MM-dd-HH'.log '
log4j.appender.I.File = logs/info/info_
log4g.appender.I.Append = true
log4j.appender.I.Threshold = info
log4j.appender.I.layout = org.apache.log4j.PatternLayout
log4j.appender.I.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm} method:%l\%n%m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.DatePattern=yyyy-MM-dd-HH'.log '
log4j.appender.E.File = logs/error/error_
log4g.appender.E.Append = true
log4j.appender.E.Threshold = error
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm} method:%l\%n%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.DatePattern=yyyy-MM-dd-HH'.log '
log4j.appender.D.File = logs/debug/debug_
log4g.appender.D.Append = true
log4j.appender.D.Threshold = debug
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm} method:%l\%n%m%n