Logback输出json格式日志,及异常信息不在Json串内的原因分析

前言

日志什么场景要输出为json格式,以及关于logback的介绍等,不是本文讨论的重点,所以不再说明。

下面的部分假定你已经熟悉logback了,如果你平常也用logback,但是每次都是从网上随便复制一个配置文件直接用,对其中的标签并不了解,那看这篇文章不能保证很轻松。

日志格式

logback的配置文件中,我们可以指定输出日志的格式,如下是一个特别简单的格式:

xml 复制代码
<appender name="SIMPLE-CONSOLE" class="ch.qos.logback.core.ConsoleAppender">  
    <encoder>  
        <pattern>%level %thread %msg \r\n</pattern>  
        <charset>UTF-8</charset>  
    </encoder>  
</appender>

打印日志的级别、线程、日志信息,最后加上了回车换行符。 这是效果:

至于有哪些字段可以输出,可以看ch.qos.logback.classic.PatternLayout 里面设置的转换器。

json格式

现在想把日志输出为json格式,那也很简单,如下定义:

xml 复制代码
<appender name="JSON-CONSOLE" class="ch.qos.logback.core.ConsoleAppender">  
    <encoder>  
        <pattern>{ "level":"%level", "thread": "%thread", "msg":"%msg" }\r\n</pattern>  
        <charset>UTF-8</charset>  
    </encoder>  
</appender>

打印一下效果:

看起来也是比较预期。

如果抛个异常呢,最开始示例的常规文本输出格式,异常也是会正常打印的,如果是Json格式呢,如下:

异常信息和msg信息是分离的,并不在一个json体内,这就很不预期了,实际期望的应该是msg里面包含着异常信息。

字段转换

如上图所示,定义appender的时候,指定了日志格式,及输出哪些字段。

logback就是将pattern里的字段转换为对应的值,然后按照对应的格式输出。所以我们定义为json格式的时候,logback也是将其中的相关变量字段替换为实际值,对于其中的字面值,比如"{ }"等部分,还是原样拼接成一个字符。

encoder标签默认使用的实现类是ch.qos.logback.classic.encoder.PatternLayoutEncoder类

pattern标签默认使用的实现类是ch.qos.logback.classic.PatternLayout类

打个断点看下这个拼接的过程,这是拼了一半的样子:

这部分的源码,一两句话并不能说清楚,简单来说,就是logback使用对应字段的转换器,将字段转换为对应的值。

异常的输出

各个字段会使用对应的转换器替换为实际的值输出,%msg对应的转换器,实际只是输出原始日志,并不包含异常信息:

而我们实际也没并有要输出异常信息,我们只定义了这三个字段:

xml 复制代码
<pattern>%level %thread %msg \r\n</pattern>  

没有指定异常字段,异常字段是下面这几个:

但是打印日志依然输出了异常,究其原因,是因为logback自动帮我们拼接了一个异常的转换器,可以这样理解,我们定义的是:

perl 复制代码
<pattern>{ "level":"%level", "thread": "%thread", "msg":"%msg" }\r\n</pattern>  

实际上是:

perl 复制代码
<pattern>{ "level":"%level", "thread": "%thread", "msg":"%msg" }\r\n %ex</pattern>  

这个过程,是在new PatternLayout()实例的时候发生的。

所以我们虽然输出Json,却在json串后面打印了一个异常信息。这是相关代码注释,大意是检查定义的转换器链是否处理了异常,如果没有就添加一个到链的末尾:

This implementation checks if any of the converters in the chain handles exceptions. If not, then this method adds a ExtendedThrowableProxyConverter instance to the end of the chain.

这就是最后很突兀的打印异常栈的原因,至于解决办法,下一篇文章进行说明。

相关推荐
张彦峰ZYF10 分钟前
功能齐了不等于能上线:智能工单系统的AI回归测试、安全防护、成本可观测与CI/CD生产部署
后端·企业智能工单系统·评测线·安全线·成本线·部署线
这个昵称不容易13 分钟前
旅游管理系统的设计与实现(SpringBoot + MySQL + Vue 前后端分离)
java·springboot·毕设
Rain的Java大神之路13 分钟前
LeetCode 37 解数独面试攻略:回溯 + 位掩码 + MRV,从暴力到毫秒级求解
java·后端·leetcode
量化分析码农26 分钟前
【Python量化波动率实战 05】你的组合真的分散了吗:滚动相关与分散化收益
后端
IT_陈寒1 小时前
Vue这个奇葩的响应式问题让我加班到凌晨
前端·人工智能·后端
天天被压力1 小时前
【A股分钟级高频数据完全手册 #11】券商实时行情数据接口:实时交易(券商源)接入与字段
java·人工智能·python
天天被压力1 小时前
【A股分钟级高频数据完全手册 #12】股票五档盘口数据接口:买卖五档实时盘口解析
java·人工智能·python
脚本自动化开发8 小时前
存储涨价后,磐镭WO5迷你主机值得买吗
后端
Wang's Blog10 小时前
Java 项目实战: 交友项目 - FastDFS:入门案例
java·开发语言·交友
一只爱撸猫的程序猿10 小时前
我看着一个 AI 引擎在 14 天里,从"记忆"走进了"搜索"
人工智能·后端·架构