Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.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 是否有一个Logback布局来创建以消息参数作为属性的JSON对象?_Java_Json_Slf4j_Logback_Loggly - Fatal编程技术网

Java 是否有一个Logback布局来创建以消息参数作为属性的JSON对象?

Java 是否有一个Logback布局来创建以消息参数作为属性的JSON对象?,java,json,slf4j,logback,loggly,Java,Json,Slf4j,Logback,Loggly,我想将日志事件作为带有参数化字符串消息的JSON对象发送给Loggly。我们的项目目前有很多代码如下所示: String someParameter = "1234"; logger.log("This is a log message with a parameter {}", someParameter); { "message": "This is a log message with a parameter 1234", "level": INFO, ....

我想将日志事件作为带有参数化字符串消息的JSON对象发送给Loggly。我们的项目目前有很多代码如下所示:

String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
    "message": "This is a log message with a parameter 1234",
    "level": INFO,
    ....
}
{
    "message": "This is a log message with a parameter {}",
    "level": INFO,
    "parameters": [
        "1234"
    ]
}
{  
   "ts":"2017-02-16T07:41:36.680-08:00",
   "msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
   "logger":"com.xxx.services.metrics.ExecutionTimeLogger",
   "level":"INFO",
   "metric":{  
      "name":"Controller Hit",
      "method":"setupSession",
      "className":"class com.xxx.services.controllers.SessionController",
      "duration":3225
   }
}
我们目前使用Logback作为SLF4J后端,Logback将ILogEvent对象序列化为JSON。因此,当我们的日志事件发送到Loggly时,它们看起来是这样的:

String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
    "message": "This is a log message with a parameter 1234",
    "level": INFO,
    ....
}
{
    "message": "This is a log message with a parameter {}",
    "level": INFO,
    "parameters": [
        "1234"
    ]
}
{  
   "ts":"2017-02-16T07:41:36.680-08:00",
   "msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
   "logger":"com.xxx.services.metrics.ExecutionTimeLogger",
   "level":"INFO",
   "metric":{  
      "name":"Controller Hit",
      "method":"setupSession",
      "className":"class com.xxx.services.controllers.SessionController",
      "duration":3225
   }
}
虽然这确实有效,但它为
someParameter
的每个值发送不同的
消息
字符串,这使得Loggly的自动过滤器几乎无用

相反,我希望有一个创建JSON的布局,如下所示:

String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
    "message": "This is a log message with a parameter 1234",
    "level": INFO,
    ....
}
{
    "message": "This is a log message with a parameter {}",
    "level": INFO,
    "parameters": [
        "1234"
    ]
}
{  
   "ts":"2017-02-16T07:41:36.680-08:00",
   "msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
   "logger":"com.xxx.services.metrics.ExecutionTimeLogger",
   "level":"INFO",
   "metric":{  
      "name":"Controller Hit",
      "method":"setupSession",
      "className":"class com.xxx.services.controllers.SessionController",
      "duration":3225
   }
}
此格式允许Loggly将所有日志事件与消息
一起分组这是一条带有参数的日志消息
,而不管
someParameter
的值是多少


它看起来是这样做的-除了编写自己的布局来执行ILogEvent对象的自定义序列化之外,是否有任何方法可以使用Logback完成此任务?

有一个用于Logback的JSON logstash编码器,

您可以使用为每种类型的日志消息设置一个戳,然后在日志中过滤一次


根据源代码,戳记作为单独的值存储在JSON中

这里有一个最近创建的项目,它提供了一个特定于JSON的日志API,并与SLF4J配合使用:


因此,我试图记录执行时间,我创建了一个名为ExecutionTime的pojo,其中包含名称、方法、类和持续时间

然后我就可以创建它了:

ExecutionTime time = new ExecutionTime("Controller Hit", methodName, className, sw.getTotalTimeMillis());
对于日志记录,我使用了:

private final Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info(append("metric", time), time.toString());
确保您有:

import static net.logstash.logback.marker.Markers.append;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
这将记录如下内容:

String someParameter = "1234";
logger.log("This is a log message with a parameter {}", someParameter);
{
    "message": "This is a log message with a parameter 1234",
    "level": INFO,
    ....
}
{
    "message": "This is a log message with a parameter {}",
    "level": INFO,
    "parameters": [
        "1234"
    ]
}
{  
   "ts":"2017-02-16T07:41:36.680-08:00",
   "msg":"ExecutionTime [name=Controller Hit, method=setupSession, className=class com.xxx.services.controllers.SessionController, duration=3225]",
   "logger":"com.xxx.services.metrics.ExecutionTimeLogger",
   "level":"INFO",
   "metric":{  
      "name":"Controller Hit",
      "method":"setupSession",
      "className":"class com.xxx.services.controllers.SessionController",
      "duration":3225
   }
}
可能是另一种设置,因为我使用logback-spring.xml将日志输出到json:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <property name="PROJECT_ID" value="my_service"/>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>app/logs/${PROJECT_ID}.json.log</File>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <fieldNames>
                <timestamp>ts</timestamp>
                <message>msg</message>
                <thread>[ignore]</thread>
                <levelValue>[ignore]</levelValue>
                <logger>logger</logger>
                <version>[ignore]</version>
            </fieldNames>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <maxIndex>10</maxIndex>
            <FileNamePattern>app/logs/${PROJECT_ID}.json.log.%i</FileNamePattern>
        </rollingPolicy>
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>20MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <logger name="com.xxx" additivity="false" level="DEBUG">
        <appender-ref ref="FILE"/>
        <appender-ref ref="CONSOLE"/>
    </logger>
    <root level="WARN">
        <appender-ref ref="FILE"/>
    </root>
</configuration>

app/logs/${PROJECT_ID}.json.log
ts
味精
[忽略]
[忽略]
记录器
[忽略]
10
app/logs/${PROJECT_ID}.json.log。%i
20MB

就像前面回答的那样,您将得到一个带有MDC的一维JSON树和/或使用带有logstash logback编码器的标记

如果您还需要以下信息:

  • 用于定义记录的数据类型键和类型的代码簿
  • 日志聚合工具的配置(如elasticsearch)
  • 生成的Java帮助程序代码用于高效和正确的日志记录
然后尝试我创建的项目:。它定义了一个简单的YAML格式定义,从中可以生成上述内容

助手代码语句示例如下

logger.info(host("localhost").port(8080), "Hello world");

生成标记时,会出现如下情况。

我在您的示例中看到的问题是,您不知道参数将插入消息中的何处。@LeonardBrünings这不重要,因为参数被传递到
log.log(消息,param1,param2)函数。只要在插入JSON对象的数组中保持顺序,一切都很好。但是JSON中的消息没有任何占位符。如果这是故意的且不是错误,您将不知道如何呈现正确的消息。@LeonardBrünings将占位符添加到示例输出JSONYup中,这就是我们最后用来向日志消息添加任意对象的内容。您能提供示例吗?开发人员必须从MDC中添加和删除值,这并不意味着它很优雅,这是一个很好的小图书馆。我怀疑我是否会将现有项目转换为it,因为这需要相当多的工作,但我肯定会在未来的项目中牢记这一点。谢谢@MusikPolicy-我们感谢您的反馈。我现在开始一个新项目,并将尝试此功能。但是,我不确定是否可以将默认字段配置为包含在日志中(我通过Logback实现了这一点,但我不喜欢依赖MDC来输出任何字段,所以我更喜欢带有API的slf4j json logger)。其想法是在配置文件中配置一个field+值,该值将自动添加到所有生成的JSON日志行/对象中。这在slf4j json logger中可能吗?现在没有这方面的功能。应该相对容易完成。请将此作为一个问题发布到github(此处),或提交一份PR!这种方法很好,我们也尝试过,但由于库的日志消息没有格式化为JSON,因此对我们没有任何用处。它作为消息的一部分出现,作为“度量”单独的节点-打印相同的信息?有什么建议吗?我可以解决重复的问题如下。logger.info(“TROS进程更新”,追加(“trosdata”,cleanerLogData),cleanerLogData);现在消息获得值“TROS Proces Update”