我尝试使用logstash-logback-encoderspring boot 将日志发送到 ELK。但不幸的是我收到这个错误。
|-ERROR in net.logstash.logback.appender.LogstashTcpSocketAppender[LOGSTASH] - Unable to process event: 'java.time.Instant ch.qos.logback.classic.spi.ILoggingEvent.getInstant()' java.lang.NoSuchMethodError: 'java.time.Instant ch.qos.logback.classic.spi.ILoggingEvent.getInstant()'
at java.lang.NoSuchMethodError: 'java.time.Instant ch.qos.logback.classic.spi.ILoggingEvent.getInstant()'
at at net.logstash.logback.composite.loggingevent.LoggingEventFormattedTimestampJsonProvider.getTimestampAsInstant(LoggingEventFormattedTimestampJsonProvider.java:29)
at at net.logstash.logback.composite.loggingevent.LoggingEventFormattedTimestampJsonProvider.getTimestampAsInstant(LoggingEventFormattedTimestampJsonProvider.java:25)
at at net.logstash.logback.composite.AbstractFormattedTimestampJsonProvider.writeTo(AbstractFormattedTimestampJsonProvider.java:164)
at at net.logstash.logback.composite.JsonProviders.writeTo(JsonProviders.java:78)
at at net.logstash.logback.composite.AbstractCompositeJsonFormatter.writeEventToGenerator(AbstractCompositeJsonFormatter.java:290)
at at net.logstash.logback.composite.AbstractCompositeJsonFormatter$JsonFormatter.writeEvent(AbstractCompositeJsonFormatter.java:190)
at at net.logstash.logback.composite.AbstractCompositeJsonFormatter.writeEvent(AbstractCompositeJsonFormatter.java:156)
at at net.logstash.logback.encoder.CompositeJsonEncoder.encode(CompositeJsonEncoder.java:106)
at at net.logstash.logback.encoder.CompositeJsonEncoder.encode(CompositeJsonEncoder.java:80)
at at net.logstash.logback.encoder.CompositeJsonEncoder.encode(CompositeJsonEncoder.java:36)
at at net.logstash.logback.appender.AbstractLogstashTcpSocketAppender$TcpSendingEventHandler.encode(AbstractLogstashTcpSocketAppender.java:654)
at at net.logstash.logback.appender.AbstractLogstashTcpSocketAppender$TcpSendingEventHandler.writeEvent(AbstractLogstashTcpSocketAppender.java:616)
at at net.logstash.logback.appender.AbstractLogstashTcpSocketAppender$TcpSendingEventHandler.onEvent(AbstractLogstashTcpSocketAppender.java:580)
at at net.logstash.logback.appender.AbstractLogstashTcpSocketAppender$TcpSendingEventHandler.onEvent(AbstractLogstashTcpSocketAppender.java:291)
at at net.logstash.logback.appender.AsyncDisruptorAppender$EventClearingEventHandler.onEvent(AsyncDisruptorAppender.java:363)
at at net.logstash.logback.appender.AsyncDisruptorAppender$EventClearingEventHandler.onEvent(AsyncDisruptorAppender.java:350)
at at net.logstash.logback.encoder.com.lmax.disruptor.BatchEventProcessor.processEvents(BatchEventProcessor.java:168)
Run Code Online (Sandbox Code Playgroud)
的版本logstash-logback-encoder是7.4.
|-ERROR …Run Code Online (Sandbox Code Playgroud) spring-boot logstash-logback-encoder elastic-stack spring-logback
我有一个logback.groovy,它使用一些自定义字段将数据发送到网络上的logstash:
appender("LOGSTASH", LogstashTcpSocketAppender) {
encoder(LogstashEncoder) {
customFields = """{ "token": "xxxxx", "environment":"dev", "some_property":"foobar" }"""
}
remoteHost = "logstashlistener.host.name"
port = 5000
}
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.但是,我需要清理一些对弹性搜索下游无效的字段名称.基于LogstashEncoder文档,这可以像这样实现:
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<fieldNames>
<timestamp>time</timestamp>
<message>msg</message>
...
</fieldNames>
</encoder>
Run Code Online (Sandbox Code Playgroud)
这看起来很棒,但我必须将其纳入logback.groovy表示法.我尝试了一个hashmap,字符串和更多,但总是最终Cannot cast object 'xxxx' with class 'xxxx' to class 'net.logstash.logback.fieldnames.LogstashFieldNames'
我想知道当使用logstash-logback-encoder 以 JSON 格式登录时,在日志记录调用中使用 StructuredArguments 的最佳实践是什么。
我想在单独的字段中记录一些结构化参数,但我不想将这些参数格式化为文字字符串消息。
如果我像这样编写日志行,一切都会按照我想要的方式正常工作,但是我的 IntelliJ IDEA 和 Sonarqube 静态代码分析都考虑了这个有问题的问题:
log.info("Query executed successfully!", StructuredArguments.value("hits", result.getHits()));
(or more concise)
log.info("Query executed successfully!", v("hits", result.getHits()));
Run Code Online (Sandbox Code Playgroud)
IntelliJ 在这一行发出警告:
提供的参数 (1) 多于指定的占位符 (0)
我怎样才能避免这种情况?当然,我可以消除警告并为其添加例外,但我想知道这是否是最佳实践。
对于日志记录,我们使用 Logback。目前我们正在使用 Splunk 来查看 Spring Boot 日志。根据项目要求,我们需要转向 Kibana。首先,我们应该以 JSON 格式登录,以便 Kibana 可以轻松处理它。目前我们还没有用 Kibana 取代 Splunk,但当与 Kibana 集成成功后,我们可以逐渐在所有项目中取代 Splunk。
因此,根据要求,我们需要现有日志,即文本日志,但出于研发目的,我们还需要 JSON 日志。
logstash-logback-encoder在一个字符串中显示stacktrace的输出,例如
"stack_trace": "java.lang.RuntimeException: null\n\tat com.ideasforsharing.demo.controllers.SleuthController.helloSleuth(SleuthController.java:24)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n"
Run Code Online (Sandbox Code Playgroud)
这很难读。我如何格式化stacktrace的显示以多行显示,也许使用json数组?
"stack_trace" : [
"java.lang.RuntimeException: null",
"com.ideasforsharing.demo.controllers.SleuthController.helloSleuth(SleuthController.java:24)",
"at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
"at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)"
]
Run Code Online (Sandbox Code Playgroud) 在 JVM 项目中,我们使用 Logstash 在生产服务器上记录带有附加 JSON 数据的消息。
问题是 JSON 很难在控制台中读取。因此,我尝试更改为本地(开发)配置以使用 PatternLayoutEncoder 并在本地拥有漂亮、干净的日志。
我发现这个问题: https ://github.com/logstash/logstash-logback-encoder/issues/136
结论是,使用 Logstash logback 编码器 5.0,我们现在可以将键/值对与结构化参数统一起来。
我这样做了,效果很好,但我遇到的问题是,现在在 Logstash 上,这些对在消息和 JSON 中都会重复。
ch.qos.logback.classic.encoder.PatternLayoutEncodernet.logstash.logback.encoder.LogstashEncoder要么我这样做:
LOGGER.info("Some message", kv("user_id", 1));
Run Code Online (Sandbox Code Playgroud)
Logstash json 是这样的:
{ message: "Some message", user_id: 1 }
Run Code Online (Sandbox Code Playgroud)
但控制台日志没有参数:
2018-04-10 08:38:38,042 INFO - Some message
Run Code Online (Sandbox Code Playgroud)
或者我这样做:
LOGGER.info("Some message {}", kv("user_id", 1));
Run Code Online (Sandbox Code Playgroud)
Logstash json 有重复的信息(不好):
{ message: "Some message user_id=1", user_id: 1 }
Run Code Online (Sandbox Code Playgroud)
控制台日志就是我想要的:
2018-04-10 08:38:38,042 INFO - Some message user_id=1
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:
如何配置日志,以便以干净的方式在控制台中获取附加信息,但不会在 …
我的Spring Boot日志当前如下所示。
{"@timestamp":"2018-08-07T14:49:21.244+01:00","@version":"1","message":"Starting Application on ipkiss bla bla)","logger_name":"logger name....","thread_name":"main","level":"INFO","level_value":20000}
Run Code Online (Sandbox Code Playgroud)
使用如下的logback-spring.xml设置
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="com.ipkiss.correlate.logback.CorrelationPatternLayoutEncoder">
<pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} id = %id %m%n%wEx</pattern>
</encoder>
</appender>
Run Code Online (Sandbox Code Playgroud)
和我的LayoutEncoder类看起来像这样
public class CorrelationPatternLayoutEncoder extends PatternLayoutEncoder {
public CorrelationPatternLayoutEncoder() {
}
@Override
public void start() {
PatternLayout patternLayout = new PatternLayout();
patternLayout.getDefaultConverterMap().put("id", CorrelationConverter.class.getName());
patternLayout.setContext(context);
patternLayout.setPattern(getPattern());
patternLayout.setOutputPatternAsHeader(outputPatternAsHeader);
patternLayout.start();
this.layout = patternLayout;
this.started = true;
}
Run Code Online (Sandbox Code Playgroud)
}
我想要达到的目的是将id添加到日志中,我无法使logstach附加我的id,我根据文档尝试了Custom(自定义)字段,但我无法使其正常工作,我有什么想法可以实现?
这就是我要结束的
{"id":"3a7ccd34-d66a-4fcc-a12e-763a395a496c","@timestamp":"2018-08-07T14:49:21.244+01:00","@version":"1","message":"Starting Application on ipkiss bla bla)","logger_name":"logger name....","thread_name":"main","level":"INFO","level_value":20000}
Run Code Online (Sandbox Code Playgroud)
或ID附加在日志末尾。
有谁知道记录异常和结构化参数的最佳实践是什么?查看https://github.com/logstash/logstash-logback-encoder#customizing-stack-traces,建议不要使用它们,但没有提供替代方案。
我希望能够将一些由 logstash logback 编码器生成的字段包装在另一个字段中。这可以通过 logback-spring.xml 中的 XML 配置来完成,还是我必须实现一些类然后在配置中引用它?
我尝试阅读有关实现 Factory 和 Decorator 方法的文章,但它似乎并没有让我获得任何帮助。
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/Users/name/dev/test.log
</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>/Users/name/dev/log/test.%d{yyyy-MM-dd}.log
</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"component":"webserver","datacenter":"ord"}
</customFields>
</encoder>
</appender>
Run Code Online (Sandbox Code Playgroud)
某些日志时我得到的当前 JSON 是:
{
"@timestamp": "2019-07-18T18:12:49.431-07:00",
"@version": "1",
"message": "Application shutdown requested.",
"logger_name": "org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar$SpringApplicationAdmin",
"thread_name": "RMI TCP Connection(2)-127.0.0.1",
"level": "INFO",
"level_value": 20000,
"component": "webserver",
"datacenter": "ord"
}
Run Code Online (Sandbox Code Playgroud)
我想要的是:
{
"@timestamp": "2019-07-18T18:12:49.431-07:00",
"@version": "1",
"component": "webserver",
"datacenter": "ord",
"data": {
"message": "Application shutdown requested.",
"logger_name": "org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar$SpringApplicationAdmin",
"thread_name": …Run Code Online (Sandbox Code Playgroud) json logback logstash logstash-logback-encoder spring-logback
我正在尝试在 POC 应用程序中使用可配置的 JSON 日志logback-logstash编码器在 POC 应用程序中配置可配置的 JSON 日志。尽管我已经定义了所有建议的依赖项,并将日志记录配置减少为只有一个记录器和附加程序(以尝试隔离问题),但我仍然收到“无法找到附加程序 x。您是在上面还是下面定义的......”
我尝试逐步删除所有其他记录器/附加器,直到只剩下“找不到”的记录器/附加器。我多次检查了附加程序在记录器定义中引用之前是否已定义。我目前正在运行测试,因此我创建了一个显式的 logback-tests.xml,其配置与 logback.xml 相同。我最初已经在内部设置了所有依赖项,但按照 logback-logstash 编码器文档中的说明,我最好让它们由 dependencyManagement 管理
依赖项:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
</properties>
...
<logback.jackson.json>0.1.5</logback.jackson.json>
<logstash-logback-encoder.version>5.2</logstash-logback-encoder.version>
<ch.qos.logback.version>1.2.3</ch.qos.logback.version>
</properties>
<dependencyManagement>
...
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${ch.qos.logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${ch.qos.logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>${ch.qos.logback.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
<!-- ======= -->
<!-- Logging -->
<!-- ======= -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-jackson</artifactId>
<version>${logback.jackson.json}</version>
</dependency>
<dependency> …Run Code Online (Sandbox Code Playgroud)