web-dev-qa-db-fra.com

Comment enrichir les données d'ouverture Jaeger avec les journaux d'application (produits par slf4j) pour Spring Boot?

Il existe une application Spring Boot existante qui utilise l'enregistreur SLF4J. J'ai décidé d'ajouter le support du traçage distribué via l'API standard opentracing avec Jaeger comme traceur. Il est vraiment étonnant de voir à quel point la configuration initiale est facile - tout ce qui est nécessaire est simplement d'ajouter deux dépendances au 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>

et fournir au bean Tracer la configuration:

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

Tout fonctionne comme un charme - les demandes d'application sont traitées par Jaeger et les portées sont créées:

enter image description here

Cependant, dans l'intervalle Logs, il n'y a que preHandle & afterCompletion événements avec des informations sur la classe/méthode qui ont été appelées lors de l'exécution de la demande (aucun journal produit par slf4j l'enregistreur est collecté):

enter image description here

La question est de savoir s'il est possible de configurer le Tracer pour récupérer les journaux produits par l'enregistreur d'application (slf4j dans mon cas) pour que tous les journaux d'application se fassent via: LOG.info/LOG.warn/LOG.error etc. serait également reflété dans Jaeger

[~ # ~] note [~ # ~] : J'ai compris comment se connecter pour s'étendre manuellement via opentracing API par exemple:

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

Et faites quelques manipulations manuelles avec la balise ERROR pour le traitement des exceptions dans les filtres, par exemple.

} 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
}

Mais, je me demande toujours s'il est possible de configurer le traceur pour récupérer les journaux d'application automatically:

  • LOG.info -> tracer ajoute un nouveau journal à la plage active
  • LOG.error -> tracer ajoute un nouveau journal à la plage active et ajoute la balise ERROR

[~ # ~] mise à jour [~ # ~] : j'ai pu ajouter les journaux d'application au traceur en ajoutant un wrapper pour l'enregistreur, par ex.

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);
}

Cependant, jusqu'à présent, je n'ai pas pu trouver d'options de configuration d'opentracing qui permettraient d'ajouter automatiquement les journaux d'application au traceur par défaut. Fondamentalement, il semble que le développeur devrait ajouter des journaux supplémentaires au traceur par programme si nécessaire. De plus, après avoir étudié davantage le traçage, il semble que normalement logging et tracing sont traités séparément et l'ajout de tous les journaux d'application au traceur n'est pas une bonne idée (le traceur devrait principalement inclure des exemples de données et étiquettes d'identification de la demande)

7
Ilya Buziuk

https://github.com/opentracing-contrib/Java-spring-cloud le projet envoie automatiquement la journalisation standard à la plage active. Ajoutez simplement la dépendance suivante à votre pom.xml

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

Ou utilisez ceci https://github.com/opentracing-contrib/Java-spring-cloud/tree/master/instrument-starters/opentracing-spring-cloud-core starter si vous souhaitez uniquement l'intégration de la journalisation .

5
Pavol Loffay

Voici ce que j'ai fait pour que les journaux liés à jdbc de Logback (Slf4j) soient écrits dans le serveur Jaeger:

En commençant par la configuration de 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>

Voici mon appender:

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();
  }
}
0
sharden

Ensuite, j'utilise opentracing-spring-jaeger-cloud-starter

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

J'ai une seule ligne dans la console avec la trace et l'étendue actuelles i.j.internal.reporters.LoggingReporter: Span a signalé: 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

Ensuite, j'utilise Spring-cloud-starter-sleuth

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

J'ai la trace et les étendues comme [my-service, 90e1114e35c897d6,90e1114e35c897d6, false] dans chaque ligne et c'est utile pour le battement de fichiers dans ELK

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

Comment puis-je obtenir la même console de connexion en utilisant opentracing-spring-jaeger-cloud-starter?

ma config opentracing

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

0
Petr Sheshenya