All Downloads are FREE. Search and download functionalities are using the official Maven repository.

zipkin2.reporter.brave.ConvertingSpanReporter Maven / Gradle / Ivy

There is a newer version: 3.4.2
Show newest version
/*
 * Copyright The OpenZipkin Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package zipkin2.reporter.brave;

import brave.Span.Kind;
import brave.Tag;
import brave.handler.MutableSpan;
import brave.handler.MutableSpan.AnnotationConsumer;
import brave.handler.MutableSpan.TagConsumer;
import brave.handler.SpanHandler;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Logger;
import zipkin2.Endpoint;
import zipkin2.Span;
import zipkin2.reporter.Reporter;

final class ConvertingSpanReporter implements Reporter {
  static final Logger logger = Logger.getLogger(ConvertingSpanReporter.class.getName());
  static final Map BRAVE_TO_ZIPKIN_KIND = generateKindMap();

  final Reporter delegate;
  final Tag errorTag;

  ConvertingSpanReporter(Reporter delegate, Tag errorTag) {
    this.delegate = delegate;
    this.errorTag = errorTag;
  }

  @Override public void report(MutableSpan span) {
    maybeAddErrorTag(span);
    Span converted = convert(span);
    delegate.report(converted);
  }

  static Span convert(MutableSpan span) {
    Span.Builder result = Span.newBuilder()
        .traceId(span.traceId())
        .parentId(span.parentId())
        .id(span.id())
        .name(span.name());

    long start = span.startTimestamp(), finish = span.finishTimestamp();
    result.timestamp(start);
    if (start != 0 && finish != 0L) result.duration(Math.max(finish - start, 1));

    // use ordinal comparison to defend against version skew
    Kind kind = span.kind();
    if (kind != null) {
      result.kind(BRAVE_TO_ZIPKIN_KIND.get(kind));
    }

    String localServiceName = span.localServiceName(), localIp = span.localIp();
    if (localServiceName != null || localIp != null) {
      result.localEndpoint(Endpoint.newBuilder()
          .serviceName(localServiceName)
          .ip(localIp)
          .port(span.localPort())
          .build());
    }

    String remoteServiceName = span.remoteServiceName(), remoteIp = span.remoteIp();
    if (remoteServiceName != null || remoteIp != null) {
      result.remoteEndpoint(Endpoint.newBuilder()
          .serviceName(remoteServiceName)
          .ip(remoteIp)
          .port(span.remotePort())
          .build());
    }

    span.forEachTag(Consumer.INSTANCE, result);
    span.forEachAnnotation(Consumer.INSTANCE, result);
    if (span.shared()) result.shared(true);
    if (span.debug()) result.debug(true);
    return result.build();
  }

  void maybeAddErrorTag(MutableSpan span) {
    // span.tag(key) iterates: check if we need to first!
    if (span.error() == null) return;
    if (span.tag("error") == null) errorTag.tag(span.error(), null, span);
  }

  @Override public String toString() {
    return delegate.toString();
  }

  /**
   * Overridden to avoid duplicates when added via {@link brave.Tracing.Builder#addSpanHandler(SpanHandler)}
   */
  @Override public final boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof ConvertingSpanReporter)) return false;
    return delegate.equals(((ConvertingSpanReporter) o).delegate);
  }

  /**
   * Overridden to avoid duplicates when added via {@link brave.Tracing.Builder#addSpanHandler(SpanHandler)}
   */
  @Override public final int hashCode() {
    return delegate.hashCode();
  }

  enum Consumer implements TagConsumer, AnnotationConsumer {
    INSTANCE;

    @Override public void accept(Span.Builder target, String key, String value) {
      target.putTag(key, value);
    }

    @Override public void accept(Span.Builder target, long timestamp, String value) {
      target.addAnnotation(timestamp, value);
    }
  }

  /**
   * This keeps the code maintenance free in the rare case there is disparity between Brave and
   * Zipkin kind values.
   */
  static Map generateKindMap() {
    Map result = new LinkedHashMap();
    // Note: Both Brave and Zipkin treat null kind as a local/in-process span
    for (Kind kind : Kind.values()) {
      try {
        result.put(kind, Span.Kind.valueOf(kind.name()));
      } catch (RuntimeException e) {
        logger.warning("Could not map Brave kind " + kind + " to Zipkin");
      }
    }
    return result;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy