11

有一个使用 SLF4J 记录器的现有 Spring Boot 应用程序。我决定opentracing使用 Jaeger 作为跟踪器,通过标准 API 添加对分布式跟踪的支持。初始设置如此简单真是令人惊讶 - 所需要的只是将两个依赖项添加到pom.xml

    <dependency>
        <groupId>io.opentracing.contrib</groupId>
        <artifactId>opentracing-spring-web-autoconfigure</artifactId>
        <version>${io.opentracing.version}</version>
    </dependency>

    <dependency>
        <groupId>io.jaegertracing</groupId>
        <artifactId>jaeger-core</artifactId>
        <version>${jaegerVersion}</version>
    </dependency>

并为Tracerbean 提供配置:

@Bean
public io.opentracing.Tracer getTracer() throws ConfigurationException {
    return new new io.jaegertracing.Tracer.Builder("my-spring-boot-app").build();
}

所有的工作都像一个魅力 - 应用程序请求由 Jaeger 处理并创建跨度:

在此处输入图像描述

但是,在跨度Logs中,只有preHandle&afterCompletion事件包含有关在请求执行期间调用的类/方法的信息(不slf4j收集记录器生成的日志):

在此处输入图像描述

问题是是否可以将 Tracer 配置为拾取应用程序记录器(slf4j在我的情况下)生成的日志,以便通过://etc. 完成的所有应用程序日志LOG.infoLOG.warnLOG.error反映在 Jaeger 中

注意:我已经想出了如何通过API手动记录跨度,例如:opentracing

Scope scope = tracer.scopeManager().active();
if (scope != null) {
    scope.span().log("...");
}

并使用标签对过滤器中的异常处理进行一些手动操作,例如ERROR

} catch(Exception ex) {
    Tags.ERROR.set(span, true);
    span.log(Map.of(Fields.EVENT, "error", Fields.ERROR_OBJECT, ex, Fields.MESSAGE, ex.getMessage()));
    throw ex
}

但是,我仍然想知道是否可以配置跟踪器来获取应用程序日志automatically

  • LOG.info-> 跟踪器将新日志添加到活动跨度
  • LOG.error-> 跟踪器将新日志添加到活动跨度并添加ERROR标签

更新:我能够通过为记录器添加包装器来将应用程序日志添加到跟踪器,例如

public void error(String message, Exception e) {
    Scope scope = tracer.scopeManager().active();
    if (scope != null) {
        Span span = scope.span();
        Tags.ERROR.set(span, true);
        span.log(Map.of(Fields.EVENT, "error", Fields.ERROR_OBJECT, e, Fields.MESSAGE, e.getMessage()));

    }
    LOG.error(message, e);
}

但是,到目前为止,我还没有找到默认情况下允许将应用程序日志自动添加到跟踪器的 opentracing 配置选项。基本上,如果需要,似乎预计开发人员会以编程方式将额外的日志添加到跟踪器。另外,在调查了更多跟踪之后,它似乎是正常的logging并且tracing是单独处理的,并且将所有应用程序日志添加到跟踪器不是一个好主意(跟踪器应该主要包括示例数据和用于请求识别的标签)

4

4 回答 4

7

https://github.com/opentracing-contrib/java-spring-cloud项目自动将标准日志发送到活动跨度。只需将以下依赖项添加到您的 pom.xml

<dependency>
   <groupId>io.opentracing.contrib</groupId>
   <artifactId>opentracing-spring-cloud-starter</artifactId>
</dependency>

如果您只想集成日志记录,或者使用此https://github.com/opentracing-contrib/java-spring-cloud/tree/master/instrument-starters/opentracing-spring-cloud-core starter。

于 2018-06-22T09:38:46.143 回答
2

这是我为使来自 Logback (Slf4j) 的 jdbc 相关日志写入 Jaeger 服务器所做的操作:

从 Logback 配置(logback-spring.xml)开始:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="consoleAppender" source="logging.console.enabled" defaultValue="false"/>
<property name="ENV" value="${SPRING_PROFILES_ACTIVE:-dev}"/>

<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

<jmxConfigurator/>

<appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
        <includeMdc>true</includeMdc>
        <customFields>{"log_type":"application","appname":"products-rs-load", "environment": "${ENV}"}
        </customFields>
    </encoder>
</appender>
<appender name="myAppender" class="com.test.MyAppender">
</appender>
<root level="DEBUG">
    <appender-ref ref="myAppender"/>
</root>
<logger name="org.springframework.boot" level="INFO"/>
<logger name="p6spy" additivity="false" level="ALL">
    <appender-ref ref="myAppender" />
</logger>
</configuration>

这是我的附加程序:

import ch.qos.logback.core.AppenderBase;
public class MyAppender extends AppenderBase {

@Override
protected void append(Object eventObject) {
    LoggingEvent event = (LoggingEvent) eventObject;

    final String loggerName = event.getLoggerName();

    // only DB related operations have to be traced:
    if (!("p6spy".equals(loggerName))) {
        return;
    }
    /// Tracer config is straight forward
    Span sp = TracingUtils.buildActiveChildSpan(loggerName, null);

    if (Level.ERROR.equals(event.getLevel())) {
        TracingUtils.setErrorTag(sp);
    }
    Map<String, String> fields = new HashMap<String, String>();
    fields.put("level", event.getLevel().toString());
    fields.put("logger", loggerName);
    fields.put("content", event.getFormattedMessage());
    sp.log(fields);

    sp.finish();
  }
}
于 2019-11-11T08:48:18.417 回答
0

然后我使用opentracing-spring-jaeger-cloud-starter

<dependency>
    <groupId>io.opentracing.contrib</groupId>
    <artifactId>opentracing-spring-jaeger-cloud-starter</artifactId>
    <version>2.0.0</version>
</dependency>

我在控制台中只有一行当前跟踪和跨度 ijinternal.reporters.LoggingReporter :跨度报告:f1a264bbe2c7eae9:f1a264bbe2c7eae9:0:1 - my_method

2019-05-20 16:07:59.549 DEBUG 24428 --- [ctor-http-nio-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [632103eb] HTTP POST "/api"
2019-05-20 16:07:59.552 DEBUG 24428 --- [ctor-http-nio-2] s.w.r.r.m.a.RequestMappingHandlerMapping : [632103eb] Mapped to public reactor.core.publisher.Mono<org.springframework.http.ResponseEntity<model.Response>> service.controller.method(model.Request)
2019-05-20 16:07:59.559 DEBUG 24428 --- [ctor-http-nio-2] .s.w.r.r.m.a.RequestBodyArgumentResolver : [632103eb] Content-Type:application/json
2019-05-20 16:08:01.450  INFO 24428 --- [ctor-http-nio-2] i.j.internal.reporters.LoggingReporter   : Span reported: f1a264bbe2c7eae9:f1a264bbe2c7eae9:0:1 - method
2019-05-20 16:08:01.450 DEBUG 24428 --- [ctor-http-nio-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [632103eb] Completed 200 OK

然后我使用spring-cloud-starter-sleuth

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

我在每一行都得到了像 [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 这样的 Trace 和 Spans,这对 ELK 中的 filebeat 很有帮助

2019-05-20 16:15:38.646 DEBUG [my-service,,,] 12548 --- [ctor-http-nio-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [3e578505] HTTP POST "/api"
2019-05-20 16:15:38.662 DEBUG [my-service,,,] 12548 --- [ctor-http-nio-2] o.s.c.s.instrument.web.TraceWebFilter    : Received a request to uri [/api]
2019-05-20 16:15:38.667 DEBUG [my-service,,,] 12548 --- [ctor-http-nio-2] o.s.c.s.instrument.web.TraceWebFilter    : Handled receive of span NoopSpan(90e1114e35c897d6/90e1114e35c897d6)
2019-05-20 16:15:38.713 DEBUG [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 12548 --- [ctor-http-nio-2] s.w.r.r.m.a.RequestMappingHandlerMapping : [3e578505] Mapped to public reactor.core.publisher.Mono<org.springframework.http.ResponseEntity<model.Response>> service.controller.method(model.Request)
2019-05-20 16:15:38.727 DEBUG [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 12548 --- [ctor-http-nio-2] .s.w.r.r.m.a.RequestBodyArgumentResolver : [3e578505] Content-Type:application/json
2019-05-20 16:15:39.956 DEBUG [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 12548 --- [gine-1-thread-1] .s.w.r.r.m.a.ResponseEntityResultHandler : Using 'application/json;charset=UTF-8' given [*/*] and supported [application/json;charset=UTF-8, application/*+json;charset=UTF-8, text/event-stream]
2019-05-20 16:15:40.009 DEBUG [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 12548 --- [ctor-http-nio-2] o.s.c.s.instrument.web.TraceWebFilter    : Adding a method tag with value [method] to a span NoopSpan(90e1114e35c897d6/90e1114e35c897d6)
2019-05-20 16:15:40.009 DEBUG [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 12548 --- [ctor-http-nio-2] o.s.c.s.instrument.web.TraceWebFilter    : Adding a class tag with value [Controller] to a span NoopSpan(90e1114e35c897d6/90e1114e35c897d6)
2019-05-20 16:15:40.010 DEBUG [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 12548 --- [ctor-http-nio-2] o.s.c.s.instrument.web.TraceWebFilter    : Handled send of NoopSpan(90e1114e35c897d6/90e1114e35c897d6)
2019-05-20 16:15:40.021 DEBUG [my-service,90e1114e35c897d6,90e1114e35c897d6,false] 12548 --- [ctor-http-nio-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [3e578505] Completed 200 OK

如何使用 opentracing-spring-jaeger-cloud-starter 在控制台中获得相同的日志?

我的开放跟踪配置

opentracing:
  jaeger:
    enabled: true
    enable-b3-propagation: true
    log-spans: true
    const-sampler:
      decision: true
    http-sender:
      url: http://jaeger-collector:14268/api/traces

于 2019-05-20T13:39:29.403 回答
0

正如已经指出的那样,一般来说,将所有日志放在除开发环境之外的任何其他环境中的 Jaeger 跟踪中都是个坏主意——它可能会淹没 Jaeger。也正如在最相关的答案中回答的那样,opentracing-spring-cloud-core图书馆提供了这种能力。它由参数控制 opentracing.spring.cloud.log.enabled

查看io/opentracing/contrib/spring/cloud/log/LoggingAutoConfiguration.java

此 bean 添加SpanLogsAppender到根记录器,这会将日志添加到活动跨度。默认情况下,这将传播到所有其他记录器,除非某些记录器的additivity属性设置为false.

在我的应用程序中,com.mycompany.myapp 中的所有记录器都为additivityfalse,因此我必须为此创建解决方法。

我的解决方法是运行类似的逻辑,为我的应用程序的记录器“com.mycompany.myapp”添加 SpanLogsAppender,它将成为该包中所有类的父级:

package com.mycompany.myapp.config;

import ch.qos.logback.classic.Logger;
import io.opentracing.Tracer;
import io.opentracing.contrib.spring.cloud.log.SpanLogsAppender;
import io.opentracing.contrib.spring.tracer.configuration.TracerAutoConfiguration;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;


@Configuration
@AutoConfigureAfter(TracerAutoConfiguration.class)
@ConditionalOnClass(ch.qos.logback.classic.Logger.class)
@ConditionalOnProperty(name = "opentracing.spring.cloud.log.enabled", havingValue = "true", matchIfMissing = true)
public class MyAppLoggingAutoConfiguration {

    public MyAppLoggingAutoConfiguration(final Tracer tracer) {
        SpanLogsAppender spanLogsAppender = new SpanLogsAppender(tracer);
        spanLogsAppender.start();
        Logger rootLogger = (Logger)LoggerFactory.getLogger("com.mycompany.myapp");
        rootLogger.addAppender(spanLogsAppender);
    }
}

这样,为位于包中任何深度的类创建的所有记录器都com.mycompany.myapp将获得额外的 SpanLogsAppender,它将日志放入当前范围。

于 2021-07-22T01:49:07.543 回答