Jaeger Trace MDC
1. ๆนๆกๆฆ่ฟฐโ
1.1 ่ๆฏไธ็ฎๆ โ
ๅจๅๅธๅผ็ณป็ปไธญ๏ผ่ทจๆๅก็่ฏทๆฑ้พ่ทฏ่ฟฝ่ธชๆฏๅฎไฝ้ฎ้ข็ๅ ณ้ฎๆๆฎตใๆฌๆนๆกๆจๅจๅฎ็ฐ Jaeger ๅๅธๅผ่ฟฝ่ธชไธ SLF4J MDC๏ผMapped Diagnostic Context๏ผ็ๆทฑๅบฆ้ๆ๏ผไฝฟๅพ๏ผ
- ๆฅๅฟ่ชๅจๆบๅธฆ traceId/spanId๏ผไพฟไบๆฅๅฟ่ๅๆฅ่ฏข
- ๆฏๆ่ทจๆๅก็ trace ไธไธๆไผ ้
- ๅจ็บฟ็จๆฑ ็ญๅผๆญฅๅบๆฏไธไฟๆ trace ไธไธๆ็ๅ็กฎๆง
1.2 ๆ ธๅฟไปทๅผโ
- ้ฎ้ขๅฎไฝๆ็ๆๅ๏ผ้่ฟ traceId ๅฟซ้ๅ ณ่ๅๅธๅผ็ณป็ปไธญ็ๆๆ็ธๅ ณๆฅๅฟ
- ้ถไพตๅ ฅๆง๏ผไธๅกไปฃ็ ๆ ้ๆๅจ็ฎก็ MDC๏ผ่ชๅจๆณจๅ ฅๅๆธ ็
- ็บฟ็จๅฎๅ จ๏ผๆฏๆๅตๅฅ Span ๅ็บฟ็จๆฑ ๅค็จๅบๆฏ
2. ๆถๆ่ฎพ่ฎกโ
2.1 ๆดไฝๆถๆๅพโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Application Layer โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Controller โโโโ>โ Service โโโโ>โ DAO โ โ
โ โ (HTTP Entry) โ โ (Business) โ โ (Database) โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Tracing Layer โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ CustomMDCScopeManager (ๆ ธๅฟ็ปไปถ) โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ ThreadLocal<CustomMDCScope> โ โ โ
โ โ โ - ็ฎก็ Scope ็ๅฝๅจๆ โ โ โ
โ โ โ - ็ปดๆค Span ๆ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ CustomMDCScope (Scope ๅฎ็ฐ) โ โ โ
โ โ โ - MDC ๅฟซ็
งไธๆขๅค โ โ โ
โ โ โ - ๆฏๆๅตๅฅ Span โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Logging Layer โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ SLF4J MDC โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ traceId: 04bf92f3577b34da... โ โ โ
โ โ โ spanId: 36bd32b7a5712a1a โ โ โ
โ โ โ parentId: 00f067aa0ba902b7 โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โผ
โโโโโโโโโโโโโโโโโโโโโโ
โ Jaeger Collector โ
โ (Trace Storage) โ
โโโโโโโโโโโโโโโโโโโโโโ
2.2 ๆ ธๅฟ็ปไปถ่ฏดๆโ
2.2.1 CustomMDCScopeManagerโ
่่ดฃ๏ผๅฎ็ฐ OpenTracing ็ ScopeManager ๆฅๅฃ๏ผ็ฎก็ Span ็ๆฟๆดปไธไผ ๆญ
ๅ ณ้ฎๅฎ็ฐ๏ผ
private final ThreadLocal<CustomMDCScope> tlsScope = new ThreadLocal<>();
@Override
public Scope activate(Span span) {
return new CustomMDCScope(span);
}
@Override
public Span activeSpan() {
CustomMDCScope scope = tlsScope.get();
return scope == null ? null : scope.wrapped;
}
่ฎพ่ฎก่ฆ็น๏ผ
- ไฝฟ็จ
ThreadLocalไฟ่ฏ็บฟ็จ้็ฆป - ๆฏๆ Scope ็ๅตๅฅ๏ผ้่ฟ้พ่กจ็ปๆ็ปดๆค previous๏ผ
- ๅฎ็ฐๆๆฟๆดป๏ผไป
ๅจ่ฐ็จ
activate()ๆถๆๆณจๅ ฅ MDC
2.2.2 CustomMDCScopeโ
่่ดฃ๏ผๅฎ็ฐ OpenTracing ็ Scope ๆฅๅฃ๏ผ็ฎก็ๅไธช Span ็็ๅฝๅจๆ
ๆ ธๅฟๆบๅถ๏ผๅฟซ็ ง-ๆณจๅ ฅ-ๆขๅค๏ผSnapshot-Inject-Restore๏ผ
CustomMDCScope(Span span) {
// 1. ไฟๅญๅฝๅ MDC ๅฟซ็
ง
this.previousTraceId = MDC.get("traceId");
this.previousSpanId = MDC.get("spanId");
// 2. ๅปบ็ซ้พ่กจๅ
ณ็ณป๏ผๆฏๆๅตๅฅ๏ผ
this.previous = CustomMDCScopeManager.this.tlsScope.get();
CustomMDCScopeManager.this.tlsScope.set(this);
// 3. ๆณจๅ
ฅๆฐ็ trace ไธไธๆ
MDC.put("traceId", span.context().toTraceId());
MDC.put("spanId", span.context().toSpanId());
}
@Override
public void close() {
// 4. ๆขๅคๅฐไธไธๅฑ Scope
CustomMDCScopeManager.this.tlsScope.set(previous);
// 5. ๆขๅค MDC ๅฐๅฟซ็
ง็ถๆ
restoreMDC("traceId", previousTraceId);
restoreMDC("spanId", previousSpanId);
}
3. ๅ ณ้ฎๆต็จ่ฎพ่ฎกโ
3.1 ๆฅๆถ่ฟ็จ Trace ไธไธๆ็ๆต็จโ
โโโโโโโโโโโโโโโ
โ HTTP Requestโ
โ Headers โ
โ uber-trace-id: 4bf92f3577b...โ
โโโโโโโโฌโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 1. ่งฃๆ HTTP Header โ
โ - ๆๅ traceId (128-bit) โ
โ - ๆๅ parentSpanId (64-bit) โ
โ - ๆๅ flags (้ๆ ทๆ ่ฎฐ) โ
โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 2. ๆ้ JaegerSpanContext โ
โ long[] parts = splitTraceId() โ
โ new JaegerSpanContext( โ
โ traceIdHigh, โ
โ traceIdLow, โ
โ parentSpanId, โ
โ parentOfParentId, โ
โ flags โ
โ ) โ
โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 3. ๅๅปบๅญ Span โ
โ tracer.buildSpan("child-span")โ
โ .asChildOf(parentContext)โ
โ .withTag(...) โ
โ .start() โ
โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 4. ๆฟๆดป Span ๅฐๅฝๅ็บฟ็จ โ
โ try (Scope scope = โ
โ tracer.scopeManager() โ
โ .activate(childSpan)) โ
โ { โ
โ // MDC ่ชๅจๆณจๅ
ฅ โ
โ // ไธๅก้ป่พๆง่ก โ
โ } // MDC ่ชๅจๆธ
็ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
3.2 ๅตๅฅ Span ็ MDC ็ฎก็ๆต็จโ
ๆถ้ด็บฟ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ>
ThreadLocal Stack:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ null โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
activate(spanA)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ScopeA: {traceId: xxx, spanId: A, previous: null}โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MDC: {traceId: xxx, spanId: A}
activate(spanB) // ๅตๅฅ่ฐ็จ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ScopeB: {traceId: xxx, spanId: B, previous: ScopeA}โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MDC: {traceId: xxx, spanId: B} // spanId ๆดๆฐ
// ไธๅกไปฃ็ ๆง่ก
log.info("Processing...") // ๆฅๅฟๆบๅธฆ spanId=B
close(ScopeB)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ScopeA: {traceId: xxx, spanId: A, previous: null}โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MDC: {traceId: xxx, spanId: A} // ๆขๅคๅฐ spanId=A
close(ScopeA)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ null โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MDC: {} // ๅฎๅ
จๆธ
็ฉบ
3.3 Trace ID ๅๅฒ็ฎๆณโ
Jaeger ๆฏๆ 128-bit ็ traceId๏ผไฝ Java long ไป
ไธบ 64-bit๏ผๅ ๆญค้่ฆๅๅฒ๏ผ
/**
* ๅฐๅๅ
ญ่ฟๅถ traceId ๅญ็ฌฆไธฒๅๅฒไธบ้ซ64ไฝๅไฝ64ไฝ
*
* ็คบไพ:
* ่พๅ
ฅ: "04bf92f3577b34da63ce929d0e0e4736" (32ไธชๅๅ
ญ่ฟๅถๅญ็ฌฆ = 128 bit)
* ่พๅบ: [0x04bf92f3577b34da, 0x63ce929d0e0e4736]
*/
public static long[] splitTraceId(String traceIdHex) {
if (traceIdHex.length() <= 16) {
// ไป
ๆไฝ64ไฝ๏ผ้ซไฝไธบ0
return new long[]{0L, parseLong(traceIdHex)};
} else {
// ๅๅฒไธบ้ซ64ไฝๅไฝ64ไฝ
String highHex = traceIdHex.substring(0, traceIdHex.length() - 16);
String lowHex = traceIdHex.substring(traceIdHex.length() - 16);
return new long[]{parseLong(highHex), parseLong(lowHex)};
}
}
4. ้ ็ฝฎไธ้ๆโ
4.1 Tracer ๅๅงๅ้ ็ฝฎโ
static Tracer tracer = new Configuration("order-service")
.withSampler(
new Configuration.SamplerConfiguration()
.withType("const")
.withParam(1) // ้ๆ ท็ 100%
)
.withReporter(
new Configuration.ReporterConfiguration()
.withLogSpans(true) // ๅผๅ็ฏๅขๅฏ็จๆฅๅฟ่พๅบ
.withSender(
new Configuration.SenderConfiguration()
.withAgentHost("localhost")
.withAgentPort(6831)
)
)
.getTracerBuilder()
.withScopeManager(new CustomMDCScopeManager()) // ๅ
ณ้ฎ๏ผๆณจๅ
ฅ่ชๅฎไน็ฎก็ๅจ
.build();
4.2 Logback ้ ็ฝฎโ
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [traceId=%X{traceId} spanId=%X{spanId}] - %msg%n</pattern>
</encoder>
</appender>
<appender name="JSON" class="ch.qos.logback.core.FileAppender">
<file>logs/app.json</file>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeMdcKeyName>traceId</includeMdcKeyName>
<includeMdcKeyName>spanId</includeMdcKeyName>
<includeMdcKeyName>parentId</includeMdcKeyName>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="JSON" />
</root>
</configuration>
4.3 Spring Boot ้ๆ๏ผๅฏ้๏ผโ
@Configuration
public class TracingConfig {
@Bean
public Tracer jaegerTracer() {
return new Configuration(
env.getProperty("spring.application.name", "unknown-service")
)
.withSampler(samplerConfig())
.withReporter(reporterConfig())
.getTracerBuilder()
.withScopeManager(new CustomMDCScopeManager())
.build();
}
@Bean
public TracingFilter tracingFilter(Tracer tracer) {
return new TracingFilter(tracer);
}
}
5. ไฝฟ็จๅบๆฏไธๆไฝณๅฎ่ทตโ
5.1 ๆฅๆถไธๆธธ Trace ไธไธๆโ
@RestController
public class OrderController {
@GetMapping("/order/{id}")
public Order getOrder(
@PathVariable String id,
@RequestHeader(value = "uber-trace-id", required = false) String uberTraceId
) {
JaegerSpanContext parentContext = parseUberTraceId(uberTraceId);
Span span = tracer.buildSpan("get-order")
.asChildOf(parentContext) // ๅ
ณ้ฎ๏ผ้พๆฅ่ฟ็จ็ถ Span
.withTag(Tags.SPAN_KIND, Tags.SPAN_KIND_SERVER)
.withTag("order.id", id)
.start();
try (Scope scope = tracer.scopeManager().activate(span)) {
log.info("Processing order request"); // ่ชๅจๆบๅธฆ traceId/spanId
return orderService.getById(id);
} finally {
span.finish();
}
}
}
5.2 ๅไธๆธธไผ ้ Trace ไธไธๆโ
public class PaymentClient {
public void processPayment(String orderId) {
Span span = tracer.buildSpan("call-payment-service")
.withTag(Tags.SPAN_KIND, Tags.SPAN_KIND_CLIENT)
.start();
try (Scope scope = tracer.scopeManager().activate(span)) {
HttpHeaders headers = new HttpHeaders();
// ๆณจๅ
ฅ trace ไธไธๆๅฐ HTTP Header
tracer.inject(
span.context(),
Format.Builtin.HTTP_HEADERS,
new HttpHeadersCarrier(headers)
);
restTemplate.exchange(
"http://payment-service/pay",
HttpMethod.POST,
new HttpEntity<>(paymentRequest, headers),
PaymentResponse.class
);
} finally {
span.finish();
}
}
}
5.3 ๅผๆญฅๅบๆฏๅค็โ
@Service
public class AsyncOrderService {
@Autowired
private Tracer tracer;
@Autowired
private ExecutorService executorService;
public void processOrderAsync(String orderId) {
Span parentSpan = tracer.activeSpan(); // ่ทๅๅฝๅ Span
executorService.submit(() -> {
// ๅจๆฐ็บฟ็จไธญ้ๆฐๆฟๆดป็ถ Span
Span asyncSpan = tracer.buildSpan("async-process")
.asChildOf(parentSpan)
.start();
try (Scope scope = tracer.scopeManager().activate(asyncSpan)) {
log.info("Async processing order"); // MDC ๆญฃ็กฎๆณจๅ
ฅ
// ไธๅก้ป่พ
} finally {
asyncSpan.finish();
}
});
}
}
6. ๅ ณ้ฎ่ฎพ่ฎกๅณ็ญโ
6.1 ไธบไปไนไธ็ดๆฅๅจไธๅกไปฃ็ ไธญๆไฝ MDC๏ผโ
้ฎ้ข๏ผๆๅจ็ฎก็ๅฎนๆ้ๆผๆธ ็๏ผๅฏผ่ด็บฟ็จๆฑ ๅค็จๆถ traceId ๆฑกๆ
่งฃๅณๆนๆก๏ผ้่ฟ ScopeManager ็็ๅฝๅจๆ็ฎก็๏ผๅจ activate() ๆถๆณจๅ
ฅ๏ผๅจ close() ๆถ่ชๅจๆธ
็
6.2 ไธบไปไน้่ฆไฟๅญ MDC ๅฟซ็ ง๏ผโ
ๅบๆฏ๏ผๅตๅฅ Span ่ฐ็จๆถ๏ผ้่ฆๅจๅญ Span ็ปๆๅๆขๅค็ถ Span ็ MDC
ๅฎ็ฐ๏ผ
// ่ฟๅ
ฅๅญ Span ๆถ
this.previousTraceId = MDC.get("traceId"); // ไฟๅญๅฟซ็
ง
MDC.put("traceId", childSpan.context().toTraceId()); // ่ฆ็
// ้ๅบๅญ Span ๆถ
restoreMDC("traceId", previousTraceId); // ๆขๅคๅฟซ็
ง
6.3 ไธบไปไนไฝฟ็จ ThreadLocal ่ไธๆฏ InheritableThreadLocal๏ผโ
่้๏ผ
ThreadLocal๏ผไธฅๆ ผ็บฟ็จ้็ฆป๏ผ้ๅๅๆญฅๅบๆฏInheritableThreadLocal๏ผๅญ็บฟ็จ็ปงๆฟ็ถ็บฟ็จๅผ๏ผไฝๅจ็บฟ็จๆฑ ๅค็จๆถๅฎนๆๅบ็ฐไธไธๆๆณๆผ
ๆจ่๏ผๅผๆญฅๅบๆฏๆพๅผไผ ้ Span๏ผ่้ไพ่ต่ชๅจ็ปงๆฟ
7. ็ๆงไธ่ฐ่ฏโ
7.1 ๆฅๅฟ่พๅบ็คบไพโ
21:45:32.123 [http-nio-8080-exec-1] INFO c.w.OrderService [traceId=04bf92f3577b34da63ce929d0e0e4736 spanId=36bd32b7a5712a1a] - Processing order ORD-001
21:45:32.234 [http-nio-8080-exec-1] INFO c.w.PaymentClient [traceId=04bf92f3577b34da63ce929d0e0e4736 spanId=7f3a28b9c4d5e6a1] - Calling payment service
21:45:32.456 [http-nio-8080-exec-1] INFO c.w.OrderService [traceId=04bf92f3577b34da63ce929d0e0e4736 spanId=36bd32b7a5712a1a] - Order processed successfully
7.2 Jaeger UI ๆฅ่ฏขโ
ๅจ Jaeger UI ไธญๅฏไปฅ๏ผ
- ้่ฟ traceId
04bf92f3577b34da63ce929d0e0e4736ๆฅ็ๅฎๆด่ฐ็จ้พ - ๆฅ็ๆฏไธช Span ็ Tags๏ผๅฆ
db.statement,http.status_code๏ผ - ๆฅ็ Span ไน้ด็็ถๅญๅ ณ็ณปๅ่ๆถๅๅธ
7.3 ๅธธ่ง้ฎ้ขๆๆฅโ
| ้ฎ้ข็ฐ่ฑก | ๅฏ่ฝๅๅ | ๆๆฅๆนๆณ |
|---|---|---|
| ๆฅๅฟไธญ traceId ไธบ็ฉบ | ๆชๆฟๆดป Span ๆ ScopeManager ๆชๆญฃ็กฎ้ ็ฝฎ | ๆฃๆฅ activate() ่ฐ็จๅ Tracer ๆๅปบ |
| traceId ๅจไธๅ่ฏทๆฑ้ดไธฒๅฐ | MDC ๆชๆญฃ็กฎๆธ ็๏ผ็บฟ็จๆฑ ๅค็จ๏ผ | ็กฎไฟ finally ๅไธญ่ฐ็จ MDC.remove() |
| ๅญ Span ๆช้พๆฅๅฐ็ถ Span | asChildOf() ๅๆฐ้่ฏฏ | ้ช่ฏ parentSpanId ๆฏๅฆๆญฃ็กฎ่งฃๆ |
| Jaeger ไธญ็ไธๅฐ Span | ้ๆ ท็่ฎพ็ฝฎไธบ0ๆ Reporter ้ ็ฝฎ้่ฏฏ | ๆฃๆฅ withParam(1) ๅ็ฝ็ป่ฟ้ๆง |
8. ๆง่ฝ่้โ
8.1 ๆง่ฝๅฝฑๅๅๆโ
| ๆไฝ | ่ๆถ | ๅฝฑๅ |
|---|---|---|
| MDC.put() | < 1ฮผs | ๅฏๅฟฝ็ฅ |
| ThreadLocal.get() | < 1ฮผs | ๅฏๅฟฝ็ฅ |
| Span.start() | ~10ฮผs | ไฝ |
| Span.finish() + ไธๆฅ | ~100ฮผs | ๅผๆญฅไธๆฅ๏ผๅฏนไธปๆต็จๅฝฑๅๅฐ |
8.2 ไผๅๅปบ่ฎฎโ
- ๅ็ๆงๅถ้ๆ ท็๏ผ็ไบง็ฏๅขๅฏ่ฎพ็ฝฎไธบ 0.1๏ผ10%๏ผไปฅ้ไฝๅญๅจๆๆฌ
- ๆน้ไธๆฅ๏ผReporter ้
็ฝฎ
withFlushInterval(1000)ๆน้ๅ้ Span - ้ฟๅ ่ฟๅบฆ Span๏ผไธ่ฆไธบๆฏไธชๆฐๆฎๅบๆฅ่ฏข้ฝๅๅปบ Span๏ผๆงๅถ็ฒๅบฆ
9. ๆฉๅฑๆนๅโ
9.1 ๆฏๆๅๅบๅผ็ผ็จ๏ผReactor/WebFlux๏ผโ
public class ReactorScopeManager implements ScopeManager {
@Override
public Scope activate(Span span) {
return new ReactorScope(span);
}
static class ReactorScope implements Scope {
ReactorScope(Span span) {
// ไฝฟ็จ Reactor Context ่้ ThreadLocal
Context.of("span", span);
}
}
}
9.2 ้ๆ Spring Cloud Sleuthโ
Spring Cloud Sleuth ๆไพไบๅผ็ฎฑๅณ็จ็ๅๅธๅผ่ฟฝ่ธช๏ผๅฏๆฟไปฃๆฌๆนๆก๏ผ
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
9.3 ๆฏๆ OpenTelemetryโ
OpenTelemetry ๆฏๆฐไธไปฃๅฏ่งๆตๆงๆ ๅ๏ผๅปบ่ฎฎๆชๆฅ่ฟ็งป๏ผ
OpenTelemetry openTelemetry = AutoConfiguredOpenTelemetrySdk
.initialize()
.getOpenTelemetrySdk();
10. ๆป็ปโ
ๆฌๆนๆก้่ฟ่ชๅฎไน ScopeManager ๅฎ็ฐไบ Jaeger Trace ไธ SLF4J MDC ็ๆ ็ผ้ๆ๏ผๅ
ทๅคไปฅไธ็น็น๏ผ
โ
่ชๅจๅ๏ผScope ็ๅฝๅจๆ็ฎก็๏ผๆ ้ๆๅจๆไฝ MDC
โ
็บฟ็จๅฎๅ
จ๏ผThreadLocal ้็ฆป + ๅฟซ็
งๆขๅคๆบๅถ
โ
ๅตๅฅๆฏๆ๏ผ้พ่กจ็ปๆ็ปดๆคๅคๅฑ Span ๅ
ณ็ณป
โ
็ไบงๅฏ็จ๏ผๅทฒ่่็บฟ็จๆฑ ๅค็จใๅผๆญฅๅบๆฏ็ญ่พน็ๆ
ๅต
่ฏฅๆนๆก้็จไบ้่ฆ็ฒพ็ปๆงๅถ trace ไธไธๆไผ ๆญ็ๅพฎๆๅกๆถๆ๏ผ็นๅซๆฏ้่ฆๆฅๆถไธๆธธ trace ไฟกๆฏ็ๆๅก็ฝๅ ณใBFF ๅฑ็ญๅบๆฏใ