【问题标题】:Log4J - JsonLayout and RollingFileAppender generating invalid JSONLog4J - JsonLayout 和 RollingFileAppender 生成无效的 JSON
【发布时间】:2016-12-02 20:31:05
【问题描述】:

我正在尝试使用 Log4J (2.6.2) 将我的日志存储在 JSON 文件中。我在RollingFileAppender 中使用JsonLayout,只要我不尝试附加到之前已经写入的文件,它就可以正常工作。

这是我设置 Layout 和 Appender 的代码:

Layout<?> layout = JsonLayout.createLayout(config, false, false, false, true, false, true, "[", "]", Charset.defaultCharset());

String appenderFileName = "mylogfile-latest.log.json";
String appenderFilePattern = "mylogfile-%i.log.json";
String appenderName = "MyAppender";
Appender appender = RollingFileAppender.createAppender(appenderFileName, appenderFilePattern, "true", appenderName, "true", "256", "true",
        SizeBasedTriggeringPolicy.createPolicy(this.configuration.getLogMaxSize().toString()),
        null, layout, null, "false", "false", null, config);

正如我所说,我第一次在日志文件中写入时运行良好:

[
  {
    "timeMillis" : 1469620840442,
    "thread" : "SimpleAsyncTaskExecutor-43",
    "level" : "ERROR",
    "loggerName" : "MyLogger",
    "message" : "my log message",
    "endOfBatch" : false,
    "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
    "threadId" : 243,
    "threadPriority" : 5
  }
  , {
    "timeMillis" : 1469620840442,
    "thread" : "SimpleAsyncTaskExecutor-43",
    "level" : "DEBUG",
    "loggerName" : "MyLogger",
    "message" : "my log message",
    "endOfBatch" : false,
    "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
    "threadId" : 243,
    "threadPriority" : 5
  }
]

然后我关闭我的附加程序等...并重新启动我的应用程序,当我将新日志写入这个现有文件时,这就是我得到的:

[
{
  "timeMillis" : 1469620840442,
  "thread" : "SimpleAsyncTaskExecutor-43",
  "level" : "ERROR",
  "loggerName" : "MyLogger",
  "message" : "my log message",
  "endOfBatch" : false,
  "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  "threadId" : 243,
  "threadPriority" : 5
}
, {
  "timeMillis" : 1469620840442,
  "thread" : "SimpleAsyncTaskExecutor-43",
  "level" : "DEBUG",
  "loggerName" : "MyLogger",
  "message" : "my log message",
  "endOfBatch" : false,
  "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
  "threadId" : 243,
  "threadPriority" : 5
}

]
{
    "timeMillis" : 1469620840490,
    "thread" : "SimpleAsyncTaskExecutor-43",
    "level" : "ERROR",
    "loggerName" : "MyLogger",
    "message" : "my log message",
    "endOfBatch" : false,
    "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
    "threadId" : 245,
    "threadPriority" : 5
  }
  , {
    "timeMillis" : 1469620840492,
    "thread" : "SimpleAsyncTaskExecutor-43",
    "level" : "DEBUG",
    "loggerName" : "MyLogger",
    "message" : "my log message",
    "endOfBatch" : false,
    "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
    "threadId" : 245,
    "threadPriority" : 5
  }

]

此问题导致无法解析日志,因为 Gson 将无法从该文件创建 List

您是否知道如何解决此问题,而无需进行糟糕的破解删除多余的] 并用逗号替换它?

谢谢!

【问题讨论】:

    标签: java json logging log4j2 rollingfileappender


    【解决方案1】:

    JSONLayout 这样做的原因是为了创建一个“格式良好”的 JSON 文档。您需要将每个文档放在自己的文件中(带有开始和结束括号)才能做到这一点,但这里不是这种情况。

    你有两个选择:

    1. 对于 JSONLayout,设置 complete=false(您在示例中将其设置为 true),这将在没有“[”和“]”的情况下将其打印出来。然后,您可以在调用 GSON 之前自己添加这些字符(因为文件实际上没有数组)。
    2. 使用 org.json:json 或 GS​​ON 之类的简单方法创建您自己的 JSONLayout(您需要扩展 AbstractStringLayout),以获取文件的字符串。

    【讨论】:

      【解决方案2】:

      由于没有其他解决方案令人满意,我最终使用正则表达式替换无效字符...

      它非常安全,因为它会检查它是否不在两个双引号之间,但显然它不是理想的解决方案:

      String content = new String(Files.readAllBytes(Paths.get(pathToLogFile)));
      content = content.replaceAll("(\\}\\R{2}\\]\\R\\{)(?=(?:(?:\\.|[^\"\\\\])*\"(?:\\.|[^\"\\\\])*\")*(?:\\.|[^\"\\\\])*)", "}\n, {");
      Files.write(Paths.get(pathToLogFile), content.getBytes());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-16
        • 1970-01-01
        • 2016-12-02
        • 1970-01-01
        • 2011-07-04
        • 2023-03-26
        相关资源
        最近更新 更多