Log4J - JsonLayout和RollingFileAppender生成无效的JSON

时间:2016-07-28 12:34:15

标签: java json logging log4j2 rollingfileappender

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

这是我设置布局和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
  }
]

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

[
{
  "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

你是否知道如何解决这个问题而不做一个糟糕的黑客删除额外的]并用逗号替换它?

谢谢!

2 个答案:

答案 0 :(得分:1)

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

您有两种选择:

  1. 对于JSONLayout,设置complete = false(在样本中将其设置为true),这将打印出来,而不是'['和']'。然后,您可以在调用GSON之前自己添加这些字符(因为该文件实际上没有数组)。
  2. 使用像org.json这样简单的东西创建你自己的JSONLayout(你需要扩展AbstractStringLayout):json或GSON来获取文件的字符串。

答案 1 :(得分:0)

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

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

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