Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java log4j2jsonlayout时间戳模式_Java_Logging_Log4j2 - Fatal编程技术网

Java log4j2jsonlayout时间戳模式

Java log4j2jsonlayout时间戳模式,java,logging,log4j2,Java,Logging,Log4j2,显然,在log4j2中没有时间戳模式支持。通常它只有JSON格式选项,但没有类似的pattern选项 { "configuration": { "name": "logggg", "packages" : "logger.savemyjob", "appenders": { "RollingFile": { "name": "rollingStone", "fileName": "async_rolled.log",

显然,在log4j2中没有时间戳模式支持。通常它只有JSON格式选项,但没有类似的
pattern
选项

{
  "configuration": {
    "name": "logggg",
    "packages" : "logger.savemyjob",
    "appenders": {
      "RollingFile": {
        "name": "rollingStone",
        "fileName": "async_rolled.log",
        "filePattern": "async_rolled-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz",
        "immediateFlush" : false,
         "JSONLayout": {
            "complete": true,
            "compact": false,
            "eventEol": true
         },
        "SizeBasedTriggeringPolicy": {
          "size": "10 MB"
        },
        "DefaultRolloverStrategy": {
          "max": "10"
        }
      }
    },
    "loggers": {
      "root": {
        "level": "debug",
        "appender-ref": {
          "ref": "rollingStone"
        }
      }
    }
  }
}
日志示例

{
  "timeMillis" : 1482231551081,
  "thread" : "main",
  "level" : "debug",
  "endOfBatch" : false,
  "threadId" : 1,
  "threadPriority" : 5, 
  "message" : "log4j might suck"
}
当我查看他们的API时,看起来太冗长了,并且没有看到添加时间戳字段的更简单的方法

JsonLayout
插件似乎是我需要覆盖的插件,因为它的
final
甚至不能扩展,否则我必须复制整个依赖类

@Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class JsonLayout extends AbstractJacksonLayout {

protected JsonLayout(final Configuration config, final boolean locationInfo, final boolean properties,
            final boolean encodeThreadContextAsList,
            final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern,
            final String footerPattern, final Charset charset) {
        super(config, new JacksonFactory.JSON(encodeThreadContextAsList).newWriter(locationInfo, properties, compact),
                charset, compact, complete, eventEol,
                PatternLayout.createSerializer(config, null, headerPattern, DEFAULT_HEADER, null, false, false),
                PatternLayout.createSerializer(config, null, footerPattern, DEFAULT_FOOTER, null, false, false));
    }

}
体系结构看起来比我预期的更复杂:(,我正在从
记录器
进行跟踪

我还考虑更改
LogEvent
本身

public interface LogEvent extends Serializable {

    @Deprecated
    Map<String, String> getContextMap();

    ReadOnlyStringMap getContextData();

    ThreadContext.ContextStack getContextStack();

    String getLoggerFqcn();

    Level getLevel();

    String getLoggerName();

    Marker getMarker();

    Message getMessage();

    long getTimeMillis();

    StackTraceElement getSource();

    String getThreadName();

    long getThreadId();

    int getThreadPriority();

    Throwable getThrown();

    ThrowableProxy getThrownProxy();

    boolean isEndOfBatch();

    boolean isIncludeLocation();

    void setEndOfBatch(boolean endOfBatch);

    void setIncludeLocation(boolean locationRequired);

    long getNanoTime();

    String getTimestamp();
}
我猜它可能会起作用,尽管它破坏了一些核心log4j核心测试。我基本上想知道在最小更改的情况下添加额外json字段的技巧

我很少看到像这样的impl,它似乎与log4jjsonapi完全不同,log4jjsonapi的性能非常好

这是我试图覆盖的失败尝试,
LogEvent


问题越来越长,我基本上想知道当我重写log4j2 api时不要错过的重要事情。

首先要做的是在上提出一个功能请求。这听起来像是可以让许多用户受益的事情,因此值得尝试在Log4j中修复它

同时,让我们来看一个自定义解决方案。我不会更改LogEvent,这将导致一个脆弱的解决方案(例如,可能无法与异步记录器和AsyncAppender一起工作)。此外,当您想要升级到更高版本的Log4j2时,您可能会遇到问题。
LogEvent
已经有了您需要的数据(
timeMillis
),它只需要格式化

官方的方法是创建一个自定义的Json布局插件。你可以重写,也可以从复制代码开始。(JIRA罚单中提出的另一个主题。)要更改的关键类可能是


Log4j2使用Jackson生成json字符串。您可能需要用提供格式化日期而不是原始毫秒的版本来替换LogEventJsonMixIn。Jackson可能已经有了一个反序列化程序,否则您需要自己编写。Log4j社区也可以提供更多想法。

因此,简而言之,我需要ite 7对象。流程如下所示

CustomLogEvent 
    -> LogEventToCustomLogEventConverter 
       -> CustomLogEventMixIn 
           -> CustomLog4jJsonModule 
                  -> CustomLog4jJsonObjectMapper 
                      -> CustomJacksonFactory 
                          -> CustomJSONLayout
CustomJSONLayout
是我将在我的
log4j2.json
中使用的插件,它支持参数作为配置

因此,我在
LogEvent
中同时使用了继承和组合

public class JsonLogEvent implements LogEvent{

    static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";
    static final DateFormat isoDateFormat = new SimpleDateFormat(TIMESTAMP_FORMAT);

    private LogEvent wrappedLogEvent;

    public JsonLogEvent(LogEvent wrappedLogEvent) {
        this.wrappedLogEvent = wrappedLogEvent;
    }

    public String getTimestamp() {
        return isoDateFormat.format(new Date(this.getTimeMillis()));
    }
}
CustomLogEventMixIn
,其键为
时间戳

@JsonSerialize(converter = JsonLogEvent.LogEventToCustomLogEventConverter.class)
@JsonRootName(XmlConstants.ELT_EVENT)
@JsonFilter("org.apache.logging.log4j.core.impl.Log4jLogEvent")
@JsonPropertyOrder({"timestamp", "threadName", "level", "loggerName", "marker", "message", "thrown",
        XmlConstants.ELT_CONTEXT_MAP, JsonConstants.ELT_CONTEXT_STACK, "loggerFQCN", "Source", "endOfBatch", "timeMillis" })
abstract class CustomLogEventMixIn extends LogEventMixIn {

    @JsonProperty("timestamp")
    public abstract String getTimestamp();

    private static final long serialVersionUID = 1L;

}

public static class LogEventToCustomLogEventConverter extends StdConverter<LogEvent, JsonLogEvent> {

    @Override
    public JsonLogEvent convert(LogEvent value) {
        return new JsonLogEvent(value);
    }
}

跟踪
JsonLayout
的使用方式非常有用。

如果这只是添加一个包含时间戳的新字段的问题,除了默认提供的timeMillis之外,为什么不尝试在新的自定义字段上使用查找

JsonLayout配置可能如下所示:

<JsonLayout>
    <KeyValuePair key="timestamp" value="$${date:yyyy-MM-dd'T'HH:mm:ss.SSSZ}" />
</JsonLayout>


$$是查找
date:
后面的字符是java SimpleDateFormat可以接受的格式。

谢谢Remko。我可能会创建一个JIRA问题。我最终像你说的那样,围绕
LogEvent
创建了包装器
JsonLogEvent
,返回格式化的时间。
 CustomLogEventMixIn扩展LogEventMixIn
,具有
时间戳
json密钥。可能对其他人也有用。如果留在StackOverflow上,每个人都需要将其作为自定义解决方案来实现。合并到Log4j中可能很好。谢谢你,Peter!这应该标记为已接受的解决方案,这是最简单、最优雅的解决方案。a小提示:我应用此设置来生成与DataDog兼容的日志。令我惊讶的是,它们不接受4位时区格式(如
+0100
),它必须在内部有
分隔符(如
+01:00
)。因此,将
Z
模式字母替换为
XXX
public class CustomLog4jJsonModule extends Log4jJsonModule {

    private static final long serialVersionUID = 1L;

    CustomLog4jJsonModule() {
        super();
    }

    @Override
    public void setupModule(final SetupContext context) {
        super.setupModule(context);

        context.setMixInAnnotations(LogEvent.class, CustomLogEventMixIn.class);
    }
}

public class CustomLog4jJsonObjectMapper extends ObjectMapper {

    public CustomLog4jJsonObjectMapper() {
        this.registerModule(new CustomLog4jJsonModule());
        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
    }

}
<JsonLayout>
    <KeyValuePair key="timestamp" value="$${date:yyyy-MM-dd'T'HH:mm:ss.SSSZ}" />
</JsonLayout>