日志规范化落地方案

栏目: IT技术 · 发布时间: 4年前

内容简介:程序日志规范化的必要性,相信很多人早就意识到了,但是接下来马上就会面临如何快速简单的落地日志规范的问题。本文主要介绍一下我们是如何解决这个问题的当然首先需要一个日志规范,我们收集了最常用的字段,最后定的规范如下表:这个日志格式设计具有如下特点:

日志规范化落地方案

问题背景

程序日志规范化的必要性,相信很多人早就意识到了,但是接下来马上就会面临如何快速简单的落地日志规范的问题。本文主要介绍一下我们是如何解决这个问题的

规范

当然首先需要一个日志规范,我们收集了最常用的字段,最后定的规范如下表:

序号 字段名 类型 说明 Elasticsearch存储
1 LogAt DateTime 日志时间 iso8601
2 TraceId string 跟踪Id 不分词
3 Department string 部门 不分词,统一小写
4 Team string 团队 不分词,统一小写
5 Project string 项目名称 不分词,统一小写
6 Host string 域名 不分词,统一小写
7 ServerIP string 服务器IP 不分词,统一小写
8 ContextPath string 虚拟目录 不分词,统一小写
9 UriStem string url主干 不分词,统一小写
10 QueryString string GET参数 分词
11 FormString string POST参数 分词
12 UserAgent string UserAgent 分词
13 Level string 日志级别 不分词,统一大写
14 Class string 记录日志所在类名 不分词
15 Method string 记录日志所在方法名 不分词
16 MethodParams string 抛出自定义异常方法参数 分词
17 Line int 行号 整数
18 Logger string 日志名 不分词
19 IOType string 自定义异常io类型 不分词
20 ExceptionType string 异常类型 不分词
21 ExceptionMessage string 异常信息 分词
22 CustomMessage string 自定义信息 分词
23 StackTrace string 堆栈信息 分词
24 HawkKey string Key 不分词

这个日志格式设计具有如下特点:

  • 异常消息(ExceptionMessage)和自定义消息(CustomMessage)分离
  • 异常类型(ExceptionType),异常堆栈(StackTrace),异常消息(ExceptionMessage)相互分离
  • 扩展了Web相关字段。域名(Host), url主干(UriStem)等

这些设计都是为了后面方便日志搜索和监控报警。

另外我们发现很多同事打日志害怕异常信息和堆栈丢失,喜欢把异常消息,堆栈和自定义消息拼接到一起,例如:

logger.error("my message, " + ex.toString, ex);

造成异常信息,堆栈丢失的原因是因为原先的日志里没有自动把异常信息,堆栈,包含到格式里。这也是我们顺带需要解决的一个问题。

规范化实现

我们团队统一使用的是slf4j + log4j2来打日志,log4j2本身提供了非常友好的插件扩展, 这样我们就可以扩展一个自己的Layout出来,将日志格式规范内化到Layout里,这样使用者 只需要应用我们的Layout,无需关心日志格式,打出来就是规范的日志格式,这样推广就会 简单很多,而且还可以方便的扩展字段,顺便解决掉异常消息和堆栈丢失的问题。

我们扩展的Layout实现类名为: Autolog4jCsvLayout, 以下配置就可以实现日志规范化。

<RollingFile name="ProgramError" ignoreExceptions="false"
                     fileName="${sys:log.path}/project_error.log"
                     filePattern="${sys:log.path}/project_error.log_%d{yyyy-MM-dd}">
    <Autolog4jCsvLayout charset="UTF-8" department="${sys:department}" team="${sys:team}" project="${sys:project}" />
    <Policies>
        <TimeBasedTriggeringPolicy interval="1" modulate="true" />
    </Policies>
    <EnumFilter allowLevels="WARN,ERROR,FATAL" />
</RollingFile>

<RollingFile name="ProgramRun" ignoreExceptions="false"
             fileName="${sys:log.path}/project_run.log"
             filePattern="${sys:log.path}/project_run.log_%d{yyyy-MM-dd}">
    <Autolog4jCsvLayout charset="UTF-8" department="${sys:department}" team="${sys:team}" project="${sys:project}" />
    <Policies>
        <TimeBasedTriggeringPolicy interval="1" modulate="true" />
    </Policies>
    <EnumFilter allowLevels="TRACE,DEBUG,INFO" />
</RollingFile>

这里将错误日志和INFO日志分开写入。另外我们发现log4j2的日志级别过滤器很难理解,所以实现了一种直接枚举日志级别的过滤器(EnumFilter),简单好懂。 解决了异常信息堆栈丢失的问题,大家就可以开心的使用如下方式打日志:

logger.error("my message", ex);

打出的文本日志举例:

"2018-04-20T15:18:59.773+08:00"	"-"	"dealer"    "dealer.arch"	"projectname"	"-"	"10.1.1.1"	"-"	"-"	"-"	"-"	"-"	"ERROR"	"org.springframework.test.context.TestContextManager"	"prepareTestInstance"	"-"	"234"	"org.springframework.test.context.TestContextManager"	"unknown"	"java.lang.IllegalStateException"	"Failed to load ApplicationContext"	"Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@17a756db] to prepare test instance [com.autohome.daimon.job.service.integration.HawkeyeServiceTest@2d10160a]"	"java.lang.IllegalStateException: Failed to load ApplicationContext
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hawkeyeService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'redisDao' is expected to be of type 'RedisDao' but was actually of type 'RedisDao$$EnhancerBySpringCGLIB$$17f5ad58'
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:321)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1268)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
	... 24 more
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'redisDao' is expected to be of type 'IRedisDao' but was actually of type 'RedisDao$$EnhancerBySpringCGLIB$$17f5ad58'
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:384)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	... 40 more
"	"b83539ac4a40de0d"

目前,我们已经把日志扩展类库开源,希望对别人也有所帮助。github地址: autolog4j

另外日志规范只是日志建设的第一步,我们还开源了基于Elasticsearch数据的开源日志监控系统, 欢迎使用。 github地址: frostmourne(霜之哀伤)


以上所述就是小编给大家介绍的《日志规范化落地方案》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

移动风暴

移动风暴

[美]弗雷德·沃格尔斯坦 / 朱邦芊 / 中信出版社 / 2014-1-1 / 39

也许,除了伟大的乔布斯,每一位奋力改变世界的硅谷英雄,都值得我们肃然起敬。苹果与谷歌十年博弈,关于这场移动平台战争的报道早已铺天盖地,而这是第一次,我们能听到幕后工程师的真实声音。两大科技巨人用智能手机和平板电脑颠覆了电脑产业。它们位处变革的中心,凭借各自的经营哲学、魅力领袖和商业敏感度,把竞争变成了残酷对决。商业记者沃格尔斯坦报道这场对抗已逾十载,在《移动风暴》中,他带领我们来到一间间办公室和会......一起来看看 《移动风暴》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具