SLF4Jロガーを使用している既存のSpring Bootアプリがあります。 Jaegerをトレーサーとして使用して、標準のopentracing
APIによる分散トレースのサポートを追加することにしました。初期設定がいかに簡単かは驚くべきことです。必要なのは、2つの依存関係を_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>
_
Tracer
Beanに構成を提供します。
_@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
_ロガーによって生成されたログは収集されません)。
問題は、すべてのアプリケーションログが_slf4j
_/_LOG.info
_を介して実行されるように、アプリロガーによって生成されたログ(私の場合は_LOG.warn
_)をピックアップするようにトレーサーを構成できるかどうかです。/_LOG.error
_などもJaegerに反映されます
[〜#〜]ノート[〜#〜]:スパンにログを記録する方法を理解しました手動でopentracing
APIを使用して、例:
_Scope scope = tracer.scopeManager().active();
if (scope != null) {
scope.span().log("...");
}
_
そして、フィルタでの例外処理のために、ERROR
タグでmanual操作を実行します。
_} 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
タグを追加します[〜#〜] update [〜#〜]:ロガーのラッパーを追加することで、アプリケーションログをトレーサーに追加できました。
_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);
}
_
ただし、これまでのところ、デフォルトでアプリケーションログを自動的にトレーサーに追加できるオープントレーシング構成オプションを見つけることができませんでした。基本的に、必要に応じてdevがプログラムによってトレーサに追加のログを追加することが予想されるようです。また、トレースをさらに調査した後、通常logging
とtracing
は別々に処理され、すべてのアプリケーションログをトレーサーに追加することはお勧めできません(トレーサーは主にリクエストの識別のためにサンプルデータとタグを含める必要があります)
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 。
以下は、Logback(Slf4j)からjdbc関連のログをJaegerサーバーに書き込むために行ったものです。
Logback config(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();
}
}
それからopentracing-spring-jaeger-cloud-starterを使用します
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-spring-jaeger-cloud-starter</artifactId>
<version>2.0.0</version>
</dependency>
現在のトレースとスパンでコンソールに1行だけが表示されました。
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]のようなトレースとスパンがあり、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
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