OpenTracing实现思路(附OpenTracing-Jaeger-Java实例)

OpenTracing实现思路(附OpenTracing-Jaeger-Java实例)_第1张图片
对于SpringCloud,开源社区已经实现了OpenTracing/OpenTelemetry, 但是对于Dubbo 或者 公司内部的RPC框架,却还没有Jaeger的实现,如果要使用,需要我们自己实现。

今天我们就以Jaeger 为例, 来聊下如何实现OpenTracing/OpenTelemetry。

转载请注明出处(手动微笑)

OpenTracing-Java

  • 一、OpenTracing/OpenTelemetry 实现思路
  • 二、OpenTracing/OpenTelemetry Java实现实例
    • 2.1 客户端标准实现
    • 2.2 服务端实现
  • 三、参考文档

一、OpenTracing/OpenTelemetry 实现思路

OpenTracing实现思路(附OpenTracing-Jaeger-Java实例)_第2张图片

二、OpenTracing/OpenTelemetry Java实现实例

以下为OpenTracing的标准实现思路,以Http请求为例;

2.1 客户端标准实现

Span span = tracer.buildSpan("...").start();
try (Scope scope = tracer.scopeManager().activate(span)) {
   span.setTag("...", "...");
	//... 业务调用逻辑
} catch (Exception e) {
   span.log(...);
} finally {
    // Optionally finish the Span if the operation it represents
    //is logically completed at this point.
    span.finish();
}

2.2 服务端实现

/**
* If request is traced then do not start new span.
*/
if (servletRequest.getAttribute(SERVER_SPAN_CONTEXT) != null) {
    chain.doFilter(servletRequest, servletResponse);
} else {
    SpanContext extractedContext = tracer.extract(Format.Builtin.HTTP_HEADERS,
            new HttpServletRequestExtractAdapter(httpRequest));

    final Span span = tracer.buildSpan(httpRequest.getMethod())
            .asChildOf(extractedContext)
            .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
            .start();

    httpRequest.setAttribute(SERVER_SPAN_CONTEXT, span.context());

    for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {
        spanDecorator.onRequest(httpRequest, span);
    }

    try (Scope scope = tracer.activateSpan(span)) {
        chain.doFilter(servletRequest, servletResponse);
        if (!httpRequest.isAsyncStarted()) {
            for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {
                spanDecorator.onResponse(httpRequest, httpResponse, span);
            }
        }
    // catch all exceptions (e.g. RuntimeException, ServletException...)
    } catch (Throwable ex) {
        for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {
            spanDecorator.onError(httpRequest, httpResponse, ex, span);
        }
        throw ex;
    } finally {
        if (httpRequest.isAsyncStarted()) {
            // what if async is already finished? This would not be called
            httpRequest.getAsyncContext()
                    .addListener(new AsyncListener() {
                @Override
                public void onComplete(AsyncEvent event) throws IOException {
                    HttpServletRequest httpRequest = (HttpServletRequest) event.getSuppliedRequest();
                    HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse();
                    for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {
                            spanDecorator.onResponse(httpRequest,
                            httpResponse,
                            span);
                    }
                    span.finish();
                }

                @Override
                public void onTimeout(AsyncEvent event) throws IOException {
                    HttpServletRequest httpRequest = (HttpServletRequest) event.getSuppliedRequest();
                    HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse();
                    for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {
                            spanDecorator.onTimeout(httpRequest,
                                httpResponse,
                                event.getAsyncContext().getTimeout(),
                                span);
                        }
                }

                @Override
                public void onError(AsyncEvent event) throws IOException {
                    HttpServletRequest httpRequest = (HttpServletRequest) event.getSuppliedRequest();
                    HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse();
                    for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {
                        spanDecorator.onError(httpRequest,
                            httpResponse,
                            event.getThrowable(),
                            span);
                    }
                }

                @Override
                public void onStartAsync(AsyncEvent event) throws IOException {
                }
            });
        } else {
            // If not async, then need to explicitly finish the span associated with the scope.
            // This is necessary, as we don't know whether this request is being handled
            // asynchronously until after the scope has already been started.
            span.finish();
        }
    }
}

三、参考文档

  • Opentracing Official
  • Opentelemetry-java
  • Common Case
  • OpenTracing语义标准规范及实现

你可能感兴趣的:(微服务)