slf4j+logback使用LoggingEventCompositeJsonEncoder输出json乱码

sw11112 2017-05-22 05:08:27
先贴配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" >
<property name="file_path" value="D:/home/" />
<property name="save_day" value="30" />

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${file_path}dms.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${file_path}dms.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>${save_day}</maxHistory>
</rollingPolicy>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"createTime": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
"flag":"%X{flag}",
"logIp":"%X{ip}",
"msg":"%msg",
"cacheOpt":"%X{cacheOpt}",
"cacheValSize":"%X{cacheValSize}",
"className":"%X{className}",
"clientIp":"%X{clientIp}",
"clientType":"%X{clientType}",
"connCount":"%X{connCount}",
"costTime":"%X{costTime}",
"isErr":"%X{isErr}",
"errName":"%X{errName}",
"keyOrSql":"%X{keyOrSql}",
"methodName":"%X{methodName}",
"restUrl":"%X{restUrl}",
"step":"%X{step}",
"traceId" : "%X{X-B3-TraceId:-}",
"parentSpanId" : "%X{X-B3-ParentSpanId:-}",
"spanId" : "%X{X-B3-SpanId:-}",
"sysName": "${springAppName:-}",
"logLever": "%level",
"thread": "%thread",
"stack_trace": "%exception{5}"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>

<logger name="com.candao.dms" level="INFO" additivity="true">
<appender-ref ref="rollingFile" />
</logger>

<!-- TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF -->
<root level="INFO">
<appender-ref ref="console" />
</root>
</configuration>



%X{AAA}中AAA为自定义输出字段
MDC中put:
MDC.put("cacheOpt", logEvent.cacheOpt==null?"":logEvent.cacheOpt.toString());
MDC.put("cacheValSize", "" + logEvent.cacheValSize);
MDC.put("className", logEvent.className == null ? "" : logEvent.className);
MDC.put("clientIp", logEvent.clientIp);
MDC.put("clientType", "" + logEvent.clientType);
MDC.put("connCount", "" + logEvent.connCount);
MDC.put("costTime", "" + logEvent.costTime);
MDC.put("isErr", "" + logEvent.isErr);
MDC.put("errName", logEvent.errName == null ? "" : logEvent.errName);
MDC.put("flag", "" + logEvent.flag);
MDC.put("ip", logEvent.logIp == null ? "" : logEvent.logIp);
MDC.put("keyOrSql", logEvent.keyOrSql == null ? "" : logEvent.keyOrSql);
MDC.put("methodName", logEvent.methodName == null ? "" : logEvent.methodName);
MDC.put("restUrl", logEvent.restUrl == null ? "" : logEvent.restUrl);
MDC.put("step", "" + logEvent.step);
MDC.put("mesg", logEvent.message == null ? "" : logEvent.message.toString());


写日志方法:



Logevent.java为自定义对象:
public class LogEvent implements Serializable {

private static final long serialVersionUID = 1L;

public long time;

/**
* traceId,每个请求唯一
*/
public String traceId;

/**
* spanId
*/
public String spanId;

/**
* 产生日志的服务器IP
*/
public String logIp;

/**
* 用户请求ip
*/
public String clientIp;

......

}



Debug过encoder, charset为utf-8:



试过将自定义字段添加到ConsoleAppender的encoder的pattern里,控制台正常显示, 文件的中文内容显示:\u54C8\u54C8\u54C8

试过将文件改为utf-8编码, 不可行。求解。
...全文
2338 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 2 楼 sd4015700 的回复:
解决方案: 实现自己的JsonFactoryDecorator,在该类中禁用jackson对非ascii码进行escape编码的特性 实现步骤: 一. 实现自己的JsonFactoryDecorator
package com.pzy.component.logback_demo_01;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.MappingJsonFactory;

import net.logstash.logback.decorate.JsonFactoryDecorator;

public class MyJsonFactoryDecorator implements JsonFactoryDecorator {

	@Override
	public MappingJsonFactory decorate(MappingJsonFactory factory) {
		// 禁用对非ascii码进行escape编码的特性
		factory.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
		return factory;
	}

}
二. 修改logback.xml
<appender name="debugFile"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level></level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
		<file>/elk/debug.log</file> <!-- 当前的日志文件文件放在 elk文件下,该日志的内容会被filebeat传送到es -->
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  <!-- 历史日志会放到 bak 文件下,最多保存7天的历史,最多占用 1G的空间 -->
			<fileNamePattern>/bak/debug.%d{yyyy-MM-dd}.log</fileNamePattern>
			<maxHistory>7</maxHistory>
			<totalSizeCap>1GB</totalSizeCap>
		</rollingPolicy>
		<encoder
			class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
			<!-- 使用自定义的JsonFactory的装饰器,禁用jackson对非ascii码字符进行escape编码 -->
			<jsonFactoryDecorator class="com.pzy.component.logback_demo_01.MyJsonFactoryDecorator"/>
			<providers>
				<mdc/>
				<timestamp>
					<timeZone>UTC</timeZone>
				</timestamp>
				<pattern>
					<pattern>
						{
						"tags": ["errorlog"],
						"project": "myproject",
						"timestamp": "%date{\"yyyy-MM-dd'T'HH:mm:ss,SSSZ\"}",
						"log_level": "%level",
						"thread": "%thread",
						"class_name": "%class",
						"line_number": "%line",
						"message": "%message",
						"stack_trace": "%exception{5}",
						"req_id": "%X{reqId}",
						"elapsed_time": "#asLong{%X{elapsedTime}}"
						}
					</pattern>
				</pattern>
				<stackTrace>
			      <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
			        <maxDepthPerThrowable>2</maxDepthPerThrowable>
			        <maxLength>2048</maxLength>
			        <rootCauseFirst>true</rootCauseFirst>
			      </throwableConverter>
			    </stackTrace>
			</providers>
		</encoder>
	</appender>
虽然我是在你提出问题的几个月之后回答的,但我希望,如果其他人遇到了这个问题,如果找到了这里,很快的得到解决!
给个赞,亲测有效!!!
weixin_42567420 2018-07-04
  • 打赏
  • 举报
回复
引用 2 楼 sd4015700 的回复:
解决方案:
实现自己的JsonFactoryDecorator,在该类中禁用jackson对非ascii码进行escape编码的特性

实现步骤:
一. 实现自己的JsonFactoryDecorator
package com.pzy.component.logback_demo_01;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.MappingJsonFactory;

import net.logstash.logback.decorate.JsonFactoryDecorator;

public class MyJsonFactoryDecorator implements JsonFactoryDecorator {

@Override
public MappingJsonFactory decorate(MappingJsonFactory factory) {
// 禁用对非ascii码进行escape编码的特性
factory.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
return factory;
}

}


二. 修改logback.xml

<appender name="debugFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level></level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>/elk/debug.log</file> <!-- 当前的日志文件文件放在 elk文件下,该日志的内容会被filebeat传送到es -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 历史日志会放到 bak 文件下,最多保存7天的历史,最多占用 1G的空间 -->
<fileNamePattern>/bak/debug.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<!-- 使用自定义的JsonFactory的装饰器,禁用jackson对非ascii码字符进行escape编码 -->
<jsonFactoryDecorator class="com.pzy.component.logback_demo_01.MyJsonFactoryDecorator"/>
<providers>
<mdc/>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
<pattern>
<pattern>
{
"tags": ["errorlog"],
"project": "myproject",
"timestamp": "%date{\"yyyy-MM-dd'T'HH:mm:ss,SSSZ\"}",
"log_level": "%level",
"thread": "%thread",
"class_name": "%class",
"line_number": "%line",
"message": "%message",
"stack_trace": "%exception{5}",
"req_id": "%X{reqId}",
"elapsed_time": "#asLong{%X{elapsedTime}}"
}
</pattern>
</pattern>
<stackTrace>
<throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
<maxDepthPerThrowable>2</maxDepthPerThrowable>
<maxLength>2048</maxLength>
<rootCauseFirst>true</rootCauseFirst>
</throwableConverter>
</stackTrace>
</providers>
</encoder>
</appender>


虽然我是在你提出问题的几个月之后回答的,但我希望,如果其他人遇到了这个问题,如果找到了这里,很快的得到解决!

---------------- 亲测可行,这正确的答案没人响应,这论坛要没落了吗?
jacarri 2017-11-30
  • 打赏
  • 举报
回复
解决没啊? 我这样也出现了
「已注销」 2017-08-17
  • 打赏
  • 举报
回复
解决方案: 实现自己的JsonFactoryDecorator,在该类中禁用jackson对非ascii码进行escape编码的特性 实现步骤: 一. 实现自己的JsonFactoryDecorator
package com.pzy.component.logback_demo_01;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.MappingJsonFactory;

import net.logstash.logback.decorate.JsonFactoryDecorator;

public class MyJsonFactoryDecorator implements JsonFactoryDecorator {

	@Override
	public MappingJsonFactory decorate(MappingJsonFactory factory) {
		// 禁用对非ascii码进行escape编码的特性
		factory.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
		return factory;
	}

}
二. 修改logback.xml
<appender name="debugFile"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level></level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
		<file>/elk/debug.log</file> <!-- 当前的日志文件文件放在 elk文件下,该日志的内容会被filebeat传送到es -->
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  <!-- 历史日志会放到 bak 文件下,最多保存7天的历史,最多占用 1G的空间 -->
			<fileNamePattern>/bak/debug.%d{yyyy-MM-dd}.log</fileNamePattern>
			<maxHistory>7</maxHistory>
			<totalSizeCap>1GB</totalSizeCap>
		</rollingPolicy>
		<encoder
			class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
			<!-- 使用自定义的JsonFactory的装饰器,禁用jackson对非ascii码字符进行escape编码 -->
			<jsonFactoryDecorator class="com.pzy.component.logback_demo_01.MyJsonFactoryDecorator"/>
			<providers>
				<mdc/>
				<timestamp>
					<timeZone>UTC</timeZone>
				</timestamp>
				<pattern>
					<pattern>
						{
						"tags": ["errorlog"],
						"project": "myproject",
						"timestamp": "%date{\"yyyy-MM-dd'T'HH:mm:ss,SSSZ\"}",
						"log_level": "%level",
						"thread": "%thread",
						"class_name": "%class",
						"line_number": "%line",
						"message": "%message",
						"stack_trace": "%exception{5}",
						"req_id": "%X{reqId}",
						"elapsed_time": "#asLong{%X{elapsedTime}}"
						}
					</pattern>
				</pattern>
				<stackTrace>
			      <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
			        <maxDepthPerThrowable>2</maxDepthPerThrowable>
			        <maxLength>2048</maxLength>
			        <rootCauseFirst>true</rootCauseFirst>
			      </throwableConverter>
			    </stackTrace>
			</providers>
		</encoder>
	</appender>
虽然我是在你提出问题的几个月之后回答的,但我希望,如果其他人遇到了这个问题,如果找到了这里,很快的得到解决!
sw11112 2017-05-22
  • 打赏
  • 举报
回复
自己顶自己,222~

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧