简体   繁体   English

Log4J-JsonLayout和RollingFileAppender生成无效的JSON

[英]Log4J - JsonLayout and RollingFileAppender generating invalid JSON

I'm trying to store my logs in JSON files using Log4J (2.6.2). 我正在尝试使用Log4J(2.6.2)将日志存储在JSON文件中。 I'm using a JsonLayout in a RollingFileAppender , and it's working properly as long as I'm not trying to append to a file that has already been written previously. 我在RollingFileAppender使用JsonLayout ,并且只要我不尝试附加到先前已编写的文件中,它就可以正常工作。

Here's my code for setting up the Layout and the Appender: 这是我用于设置版式和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);

As I said, it's working fine the first time I'm writing in my log file: 正如我所说的,这是我第一次在日志文件中编写代码时工作正常:

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

I then close my appender, etc... and relaunch my application, and when I'm writing new logs to this existing file, here's what I'm getting: 然后关闭我的附加程序,等等...并重新启动我的应用程序,当我将新日志写入此现有文件时,这就是我得到的:

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

]

This issue makes it impossible to parse the logs as Gson will fail to create a List from this file. 由于Gson无法从该文件创建List ,因此此问题使无法解析日志。

Do you have any idea on how to fix this issue without doing a crappy hack removing the extra ] and replacing it with a comma? 您对如何解决此问题有任何想法,而不必进行doing脚的修改,删除多余的]并用逗号替换吗?

Thanks! 谢谢!

The reason why the JSONLayout does this is to create a "well-formed" JSON document. JSONLayout执行此操作的原因是创建“格式正确的” JSON文档。 You need to put each document in its own file (with start and end brackets) for this to be true, which isn't the case here. 您需要将每个文档放在其自己的文件中(带有开始和结尾方括号),这是正确的,这里不是这种情况。

You have two options: 您有两种选择:

  1. For JSONLayout, set complete=false (you have it as true in your sample) which will print it out without the '[' and ']'. 对于JSONLayout,将complete = false设置为示例(在示例中为true),这将在不使用'['和']'的情况下将其打印出来。 You can then add these chars yourself before calling GSON (as the file will not really have an array). 然后,您可以在调用GSON之前自己添加这些字符(因为该文件实际上不会具有数组)。
  2. Create your own JSONLayout (you need to extend AbstractStringLayout) using something simple like org.json:json or GSON to get you the string for the file. 使用诸如org.json:json或GSON之类的简单内容创建自己的JSONLayout(您需要扩展AbstractStringLayout)以获取文件的字符串。

Since no other solution was satisfying, I ended up using a regex to replace the invalid characters... 由于没有其他解决方案令人满意,因此我最终使用了正则表达式来替换无效字符...

It's pretty safe since it checks if it's not in between two double-quotes, but it's not the ideal solution obviously: 这很安全,因为它会检查它是否不在两个双引号之间,但这显然不是理想的解决方案:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM