欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > 魔改log4j2的JsonLayout,支持自定义json格式日志

魔改log4j2的JsonLayout,支持自定义json格式日志

2025/3/12 9:33:14 来源:https://blog.csdn.net/qq_39893313/article/details/143826911  浏览:    关键词:魔改log4j2的JsonLayout,支持自定义json格式日志

        小伙伴们,你们好,我是老寇,我又回来辣,1个多月不见甚是想念啊!!!跟我一起魔改源码吧

1.自定义json格式【PatternLayout

大部分教程都是这个,因此,我就简单给个配置,没啥好说,然后,我们一起看看源码吧

配置

      <PatternLayout><!--注意:真实的生产环境,日志打印的内容是五花八门,日志内容会出现一些莫名其他的特殊符号,导致json无法反序列化因此,可以利用Pattern Layout 提供的标签enc,enc支持4种转义,HTML/XML/JSON/CRLF,默认进行HTML转义目前,只对JSON处理,即%enc{%m}{JSON} => {"msg":"%enc{%m}{JSON}"}--><pattern>{"serviceId":"${SERVICE_ID}", "profile":"test", "dateTime":"%d{yyyy-MM-dd HH:mm:ss.SSS}", "traceId":"%X{traceId}", "spanId":"%X{spanId}", "address":"${sys:ip}:${sys:server.port}]", "level":"%-5level", "thread":"%thread", "logger":"%logger", "msg":"%enc{%m}{JSON}"}%n</pattern></PatternLayout>
{"serviceId":"laokou-sample-websocket","profile":"test","address":"127.0.0.1:9032","dateTime":"2024-11-17 06:37:56.501","packageName":"com.ulisesbocchio.jasyptspringboot.caching.RefreshScopeRefreshedEventListener","threadName":"main","level":"INFO","message":"Refreshing cached encryptable property sources on ServletWebServerInitializedEvent"}

 源码

<PatternLayout/>是来源于 PatternLayout,用于格式化日志输出。因此,我们分析这个类即可

2.自定义json格式【JsonLayout

这个需要魔改JsonLayout源码,因为JsonLayout无法继承,我只能全路径覆盖源码,我们修改一下源码吧

注解【@Plugin

@Plugin 是 Log4j 提供的一个注解,用于注册和配置自定义的插件。Log4j 插件可以是各种类型,例如 Appender(输出目的地)、Layout(格式化日志的方式)等

参数名称参数描述参数值【举例】
name插件名称JsonLayout
category

插件类别,有以下几种常见插件类型,例如:

Core    => 核心插件

Layout => 日志布局

Node.CATEGORY => Log4j内部变量,通常用于解析配置

Node.CATEGORY
elementType定义插件的 XML 配置中对应的元素类型elementType = Layout.ELEMENT_TYPE【表示布局插件】
printObject是否将日志事件以格式化输出true

魔改【全路径覆盖】

@Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class JsonLayout extends AbstractJacksonLayout {// 省略大部分代码// ...@Overridepublic void toSerializable(final LogEvent event, final Writer writer) throws IOException {if (complete && eventCount > 0) {writer.append(", ");}// 判断是否定义<KeyValuePair>if (additionalFields.length > 0) {objectWriter.writeValue(writer, getFieldsMap(event));writer.write(eol);if (includeNullDelimiter) {writer.write('\0');}markEvent();}else {super.toSerializable(event, writer);}}// @formatter:offprivate Map<String, String> getFieldsMap(LogEvent event) {LogEvent evt = convertMutableToLog4jEvent(event);Map<String, String> additionalFieldsMap = resolveAdditionalFields(evt);additionalFieldsMap.putAll(evt.getContextData().toMap());additionalFieldsMap.putAll(Map.of("address", System.getProperty("address", ""),"dateTime", FORMATTER.format(getLocalDateTimeOfTimestamp(evt.getTimeMillis())),"level", evt.getLevel().name(),"threadName", evt.getThreadName(),"packageName", evt.getLoggerName(),"message", evt.getMessage().getFormattedMessage(),"stacktrace", getStackTraceAsString(evt.getThrown())));return additionalFieldsMap;}// @formatter:onprivate String getStackTraceAsString(Throwable throwable) {if (ObjectUtils.isEmpty(throwable)) {return "";}StringWriter stringWriter = new StringWriter();try (PrintWriter printWriter = new PrintWriter(stringWriter)) {throwable.printStackTrace(printWriter);}return stringWriter.toString();}}

 配置

      <JsonLayout complete="false" compact="true" eventEol="true" properties="true" locationInfo="true" includeStacktrace="true" stacktraceAsString="false" objectMessageAsJsonObject="false"><KeyValuePair key="serviceId" value="${SERVICE_ID}"/><KeyValuePair key="profile" value="${PROFILE}" /></JsonLayout>
{"serviceId":"laokou-sample-websocket","profile":"test","threadName":"main","level":"INFO","message":"Skipping PropertySource servletConfigInitParams [class org.springframework.core.env.PropertySource$StubPropertySource","address":"198.18.0.1:9032","dateTime":"2024-11-17 09:37:28.183","packageName":"com.ulisesbocchio.jasyptspringboot.EncryptablePropertySourceConverter"}

标签【JsonLayout 】

参数名称参数描述默认值
complete是否输出完整的 JSON 对象,true作为单独的json文件,false逐行处理false
compact是否紧凑输出json,true单行输出,节省空间,false多行输出方便阅读和调试true
eventEol

如果为 true,每条日志记录后添加换行符,方便逐条处理(推荐开启)。

false
properties如果为 true,输出上下文的键值对(MDC 和 NDC 数据)false
includeStacktrace如果为 false,不包含堆栈跟踪信息(适用于异常日志)true
locationInfo如果为 true,输出日志发生的位置(类名、方法名、行号等信息),可能会影响性能false
charset设置输出文件的字符编码UTF-8
objectMessageAsJsonObject如果为 true,对象消息将直接作为 JSON 对象输出,而不是作为字符串false
stacktraceAsString是否将堆栈跟踪信息作为字符串处理false

已上传GithubGitHub - KouShenhai/KCloud-Platform-IoT: KCloud-Platform-IoT(阻塞式)(老寇IoT云平台)是一个企业级微服务架构的IoT云平台。采用DDD(领域驱动设计)思想,基于Spring Boot 3.4.0、Spring Cloud 2024.0.0、Spring Cloud Alibaba 2023.0.1.3 最新版本开发的云服务多租户IoT平台,家人们,点个star!拜托啦~

我是老寇,我们下次再见

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词