Skip to content

Latest commit

 

History

History
204 lines (151 loc) · 6.3 KB

README.md

File metadata and controls

204 lines (151 loc) · 6.3 KB

API Incubator

Experimental APIs, including Event API, extended Log Bridge APIs, extended Metrics APIs, extended ContextPropagator APIs, and extended Trace APIs.

Event API

Features:

See EventApiUsageTest.

Extended Log Bridge API

Features:

  • Set AnyValue log record body with arbitrarily complex data

See ExtendedLogsBridgeApiUsageTest.

Extended Metrics APIs

Features:

  • Synchronous gauge instrument
  • Attributes advice

See ExtendedMetricsApiUsageTest.

Extended ContextPropagator APIs

Features:

  • Simplified injection / extraction of context

See ExtendedContextPropagatorsUsageTest.

ExtendedTracer

Utility methods to make it easier to use the OpenTelemetry tracer.

Here are some examples how the utility methods can help reduce boilerplate code.

TODO: translate examples to test to ensure no java compilation issues.

Tracing a function

Before:

Span span = tracer.spanBuilder("reset_checkout").startSpan();
String transactionId;
try (Scope scope = span.makeCurrent()) {
  transactionId = resetCheckout(cartId);
} catch (Throwable e) {
  span.setStatus(StatusCode.ERROR);
  span.recordException(e);
  throw e; // or throw new RuntimeException(e) - depending on your error handling strategy
} finally {
  span.end();
}

After:

import io.opentelemetry.extension.incubator.trace.ExtendedTracer;

ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
String transactionId = extendedTracer.spanBuilder("reset_checkout").startAndCall(() -> resetCheckout(cartId));

If you want to set attributes on the span, you can use the startAndCall method on the span builder:

import io.opentelemetry.extension.incubator.trace.ExtendedTracer;

ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
String transactionId = extendedTracer.spanBuilder("reset_checkout")
    .setAttribute("foo", "bar")
    .startAndCall(() -> resetCheckout(cartId));

Note:

  • Use startAndRun instead of startAndCall if the function returns void (both on the tracer and span builder).
  • Exceptions are re-thrown without modification - see Exception handling for more details.

Trace context propagation

Before:

Map<String, String> propagationHeaders = new HashMap<>();
openTelemetry
    .getPropagators()
    .getTextMapPropagator()
    .inject(
        Context.current(),
        propagationHeaders,
        (map, key, value) -> {
          if (map != null) {
            map.put(key, value);
          }
        });

// add propagationHeaders to request headers and call checkout service
// in checkout service: get request headers into a Map<String, String> requestHeaders
Map<String, String> requestHeaders = new HashMap<>();
String cartId = "cartId";

SpanBuilder spanBuilder = tracer.spanBuilder("checkout_cart");

TextMapGetter<Map<String, String>> TEXT_MAP_GETTER =
    new TextMapGetter<Map<String, String>>() {
      @Override
      public Set<String> keys(Map<String, String> carrier) {
        return carrier.keySet();
      }

      @Override
      @Nullable
      public String get(@Nullable Map<String, String> carrier, String key) {
        return carrier == null ? null : carrier.get(key);
      }
    };

Map<String, String> normalizedTransport =
    requestHeaders.entrySet().stream()
        .collect(
            Collectors.toMap(
                entry -> entry.getKey().toLowerCase(Locale.ROOT), Map.Entry::getValue));
Context newContext = openTelemetry
    .getPropagators()
    .getTextMapPropagator()
    .extract(Context.current(), normalizedTransport, TEXT_MAP_GETTER);
String transactionId;
try (Scope ignore = newContext.makeCurrent()) {
  Span span = spanBuilder.setSpanKind(SERVER).startSpan();
  try (Scope scope = span.makeCurrent()) {
    transactionId = processCheckout(cartId);
  } catch (Throwable e) {
    span.setStatus(StatusCode.ERROR);
    span.recordException(e);
    throw e; // or throw new RuntimeException(e) - depending on your error handling strategy
  } finally {
    span.end();
  }
}

After:

import io.opentelemetry.extension.incubator.propagation.ExtendedContextPropagators;

Map<String, String> propagationHeaders =
    ExtendedContextPropagators.getTextMapPropagationContext(openTelemetry.getPropagators());
// add propagationHeaders to request headers and call checkout service
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.extension.incubator.trace.ExtendedTracer;

// in checkout service: get request headers into a Map<String, String> requestHeaders
Map<String, String> requestHeaders = new HashMap<>();
String cartId = "cartId";

ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
String transactionId = extendedTracer.spanBuilder("checkout_cart")
    .setSpanKind(SpanKind.SERVER)
    .setParentFrom(openTelemetry.getPropagators(), requestHeaders)
    .startAndCall(() -> processCheckout(cartId));

Exception handling

ExtendedTracer re-throws exceptions without modification. This means you can catch exceptions around ExtendedTracer calls and handle them as you would without ExtendedTracer.

When an exception is encountered during an ExtendedTracer call, the span is marked as error and the exception is recorded.

If you want to customize this behaviour, e.g. to only record the exception, because you are able to recover from the error, you can call the overloaded method of startAndCall or startAndRun that takes an exception handler:

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.extension.incubator.trace.ExtendedTracer;

ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
String transactionId = extendedTracer.spanBuilder("checkout_cart")
    .startAndCall(() -> processCheckout(cartId), Span::recordException);