mt_*_*mt_ 14 java logging json logback slf4j
我在JAX-RS应用程序中使用带有Logback的SLF4J ...我想以这样的方式登录到JSON,即我的消息不再被编码,而是原始打印到日志文件中:
目前它看起来像这样:
{"@timestamp":1363834123012,"@message":"{\"text\":\"From MLK to Barack
Ob...\n\"}"
Run Code Online (Sandbox Code Playgroud)
但我希望有这个:
{"@timestamp":1363834123012,"@message": { "text ": "From MLK to Barack
Ob...\n\}
Run Code Online (Sandbox Code Playgroud)
原因是我想再次解析JSON并希望避免数据的转义.
我写了一个自定义的logback编码器,但我发现无法避免转义.我可以传递一个对象进行回溯并根据对象的类型更改设置吗?
编辑:我找到了一种方式 - 不完全优雅 - 按照SSCE的要求:
在我的申请中
// SLF4J Logger
private static Logger logger = LoggerFactory.getLogger(MyClass.class);
// A logback? Marker
private Marker foo = MarkerFactory.getMarker("foo");
// Jackson ObjectMapper()
ObjectMapper mapper = new ObjectMapper();
// Log something...
logger.info(foo, mapper.writeValueAsString(json));
Run Code Online (Sandbox Code Playgroud)
我在这里使用了Logstash-Encoder的变体:https://github.com/logstash/logstash-logback-encoder
package my.package;
import static org.apache.commons.io.IOUtils.*;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import org.codehaus.jackson.JsonGenerator.Feature;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.slf4j.Marker;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.ThrowableProxyUtil;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.encoder.EncoderBase;
public class JsonEncoder extends EncoderBase<ILoggingEvent> {
private static final ObjectMapper MAPPER = new ObjectMapper().configure(
Feature.ESCAPE_NON_ASCII, true);
private static Marker M;
private boolean immediateFlush = true;
@Override
public void doEncode(ILoggingEvent event) throws IOException {
M = event.getMarker();
ObjectNode eventNode = MAPPER.createObjectNode();
eventNode.put("@timestamp", event.getTimeStamp());
//
if (M != null) {
if (M.getName().equals("foo")) {
JsonNode j = MAPPER.readTree(event.getFormattedMessage());
eventNode.put("@foo", j);
}
} else {
eventNode.put("@message", event.getFormattedMessage());
}
eventNode.put("@fields", createFields(event));
write(MAPPER.writeValueAsBytes(eventNode), outputStream);
write(CoreConstants.LINE_SEPARATOR, outputStream);
if (immediateFlush) {
outputStream.flush();
}
}
private ObjectNode createFields(ILoggingEvent event) {
// not important here
return fieldsNode;
}
@Override
public void close() throws IOException {
write(LINE_SEPARATOR, outputStream);
}
public boolean isImmediateFlush() {
return immediateFlush;
}
public void setImmediateFlush(boolean immediateFlush) {
this.immediateFlush = immediateFlush;
}
}
Run Code Online (Sandbox Code Playgroud)
它现在有效!是啊!但我想这不是最好的方法(序列化,反序列化JSON ......)
如果你有一个 Json 格式的消息,上面的解决方案可以工作,但不是那么好,因为你不想每次在代码中使用你的记录器时都调用一个特定于 logstash 的代码。
只需添加一个
net.logstash.logback.encoder.LogstashEncoder
Run Code Online (Sandbox Code Playgroud)
是不够的,因为消息本身保持转义。要解决此问题,请在 logback.xml 中尝试以下操作:
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp/>
<version/>
<loggerName/>
<pattern>
<pattern>
{
"jsonMessage": "#asJson{%message}"
}
</pattern>
</pattern>
</providers>
</encoder>
Run Code Online (Sandbox Code Playgroud)
#asJson 模式将转义您的消息。
| 归档时间: |
|
| 查看次数: |
10867 次 |
| 最近记录: |