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

org.apache.rocketmq.shaded.io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator Maven / Gradle / Ivy

There is a newer version: 5.0.7
Show newest version
/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package org.apache.rocketmq.shaded.io.opentelemetry.api.trace.propagation;

import static org.apache.rocketmq.shaded.io.opentelemetry.api.trace.propagation.internal.W3CTraceContextEncoding.decodeTraceState;
import static org.apache.rocketmq.shaded.io.opentelemetry.api.trace.propagation.internal.W3CTraceContextEncoding.encodeTraceState;

import org.apache.rocketmq.shaded.io.opentelemetry.api.internal.OtelEncodingUtils;
import org.apache.rocketmq.shaded.io.opentelemetry.api.internal.TemporaryBuffers;
import org.apache.rocketmq.shaded.io.opentelemetry.api.trace.Span;
import org.apache.rocketmq.shaded.io.opentelemetry.api.trace.SpanContext;
import org.apache.rocketmq.shaded.io.opentelemetry.api.trace.SpanId;
import org.apache.rocketmq.shaded.io.opentelemetry.api.trace.TraceFlags;
import org.apache.rocketmq.shaded.io.opentelemetry.api.trace.TraceId;
import org.apache.rocketmq.shaded.io.opentelemetry.api.trace.TraceState;
import org.apache.rocketmq.shaded.io.opentelemetry.context.Context;
import org.apache.rocketmq.shaded.io.opentelemetry.context.propagation.TextMapGetter;
import org.apache.rocketmq.shaded.io.opentelemetry.context.propagation.TextMapPropagator;
import org.apache.rocketmq.shaded.io.opentelemetry.context.propagation.TextMapSetter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

/**
 * Implementation of the W3C TraceContext propagation protocol. See W3C Trace Context.
 *
 * 

This is the default propagator for {@link SpanContext}s. The {@link SpanContext} type is * designed to support all the data propagated via W3C propagation natively. */ @Immutable public final class W3CTraceContextPropagator implements TextMapPropagator { private static final Logger logger = Logger.getLogger(W3CTraceContextPropagator.class.getName()); static final String TRACE_PARENT = "traceparent"; static final String TRACE_STATE = "tracestate"; private static final List FIELDS = Collections.unmodifiableList(Arrays.asList(TRACE_PARENT, TRACE_STATE)); private static final String VERSION = "00"; private static final int VERSION_SIZE = 2; private static final char TRACEPARENT_DELIMITER = '-'; private static final int TRACEPARENT_DELIMITER_SIZE = 1; private static final int TRACE_ID_HEX_SIZE = TraceId.getLength(); private static final int SPAN_ID_HEX_SIZE = SpanId.getLength(); private static final int TRACE_OPTION_HEX_SIZE = TraceFlags.getLength(); private static final int TRACE_ID_OFFSET = VERSION_SIZE + TRACEPARENT_DELIMITER_SIZE; private static final int SPAN_ID_OFFSET = TRACE_ID_OFFSET + TRACE_ID_HEX_SIZE + TRACEPARENT_DELIMITER_SIZE; private static final int TRACE_OPTION_OFFSET = SPAN_ID_OFFSET + SPAN_ID_HEX_SIZE + TRACEPARENT_DELIMITER_SIZE; private static final int TRACEPARENT_HEADER_SIZE = TRACE_OPTION_OFFSET + TRACE_OPTION_HEX_SIZE; private static final Set VALID_VERSIONS; private static final String VERSION_00 = "00"; private static final W3CTraceContextPropagator INSTANCE = new W3CTraceContextPropagator(); static { // A valid version is 1 byte representing an 8-bit unsigned integer, version ff is invalid. VALID_VERSIONS = new HashSet<>(); for (int i = 0; i < 255; i++) { String version = Long.toHexString(i); if (version.length() < 2) { version = '0' + version; } VALID_VERSIONS.add(version); } } private W3CTraceContextPropagator() { // singleton } /** * Returns a singleton instance of a {@link TextMapPropagator} implementing the W3C TraceContext * propagation. */ public static W3CTraceContextPropagator getInstance() { return INSTANCE; } @Override public Collection fields() { return FIELDS; } @Override public void inject(Context context, @Nullable C carrier, TextMapSetter setter) { if (context == null || setter == null) { return; } SpanContext spanContext = Span.fromContext(context).getSpanContext(); if (!spanContext.isValid()) { return; } char[] chars = TemporaryBuffers.chars(TRACEPARENT_HEADER_SIZE); chars[0] = VERSION.charAt(0); chars[1] = VERSION.charAt(1); chars[2] = TRACEPARENT_DELIMITER; String traceId = spanContext.getTraceId(); traceId.getChars(0, traceId.length(), chars, TRACE_ID_OFFSET); chars[SPAN_ID_OFFSET - 1] = TRACEPARENT_DELIMITER; String spanId = spanContext.getSpanId(); spanId.getChars(0, spanId.length(), chars, SPAN_ID_OFFSET); chars[TRACE_OPTION_OFFSET - 1] = TRACEPARENT_DELIMITER; String traceFlagsHex = spanContext.getTraceFlags().asHex(); chars[TRACE_OPTION_OFFSET] = traceFlagsHex.charAt(0); chars[TRACE_OPTION_OFFSET + 1] = traceFlagsHex.charAt(1); setter.set(carrier, TRACE_PARENT, new String(chars, 0, TRACEPARENT_HEADER_SIZE)); TraceState traceState = spanContext.getTraceState(); if (traceState.isEmpty()) { // No need to add an empty "tracestate" header. return; } setter.set(carrier, TRACE_STATE, encodeTraceState(traceState)); } @Override public Context extract(Context context, @Nullable C carrier, TextMapGetter getter) { if (context == null) { return Context.root(); } if (getter == null) { return context; } SpanContext spanContext = extractImpl(carrier, getter); if (!spanContext.isValid()) { return context; } return context.with(Span.wrap(spanContext)); } private static SpanContext extractImpl(@Nullable C carrier, TextMapGetter getter) { String traceParent = getter.get(carrier, TRACE_PARENT); if (traceParent == null) { return SpanContext.getInvalid(); } SpanContext contextFromParentHeader = extractContextFromTraceParent(traceParent); if (!contextFromParentHeader.isValid()) { return contextFromParentHeader; } String traceStateHeader = getter.get(carrier, TRACE_STATE); if (traceStateHeader == null || traceStateHeader.isEmpty()) { return contextFromParentHeader; } try { TraceState traceState = decodeTraceState(traceStateHeader); return SpanContext.createFromRemoteParent( contextFromParentHeader.getTraceId(), contextFromParentHeader.getSpanId(), contextFromParentHeader.getTraceFlags(), traceState); } catch (IllegalArgumentException e) { logger.fine("Unparseable tracestate header. Returning span context without state."); return contextFromParentHeader; } } private static SpanContext extractContextFromTraceParent(String traceparent) { // TODO(bdrutu): Do we need to verify that version is hex and that // for the version the length is the expected one? boolean isValid = (traceparent.length() == TRACEPARENT_HEADER_SIZE || (traceparent.length() > TRACEPARENT_HEADER_SIZE && traceparent.charAt(TRACEPARENT_HEADER_SIZE) == TRACEPARENT_DELIMITER)) && traceparent.charAt(TRACE_ID_OFFSET - 1) == TRACEPARENT_DELIMITER && traceparent.charAt(SPAN_ID_OFFSET - 1) == TRACEPARENT_DELIMITER && traceparent.charAt(TRACE_OPTION_OFFSET - 1) == TRACEPARENT_DELIMITER; if (!isValid) { logger.fine("Unparseable traceparent header. Returning INVALID span context."); return SpanContext.getInvalid(); } String version = traceparent.substring(0, 2); if (!VALID_VERSIONS.contains(version)) { return SpanContext.getInvalid(); } if (version.equals(VERSION_00) && traceparent.length() > TRACEPARENT_HEADER_SIZE) { return SpanContext.getInvalid(); } String traceId = traceparent.substring(TRACE_ID_OFFSET, TRACE_ID_OFFSET + TraceId.getLength()); String spanId = traceparent.substring(SPAN_ID_OFFSET, SPAN_ID_OFFSET + SpanId.getLength()); char firstTraceFlagsChar = traceparent.charAt(TRACE_OPTION_OFFSET); char secondTraceFlagsChar = traceparent.charAt(TRACE_OPTION_OFFSET + 1); if (!OtelEncodingUtils.isValidBase16Character(firstTraceFlagsChar) || !OtelEncodingUtils.isValidBase16Character(secondTraceFlagsChar)) { return SpanContext.getInvalid(); } TraceFlags traceFlags = TraceFlags.fromByte( OtelEncodingUtils.byteFromBase16(firstTraceFlagsChar, secondTraceFlagsChar)); return SpanContext.createFromRemoteParent(traceId, spanId, traceFlags, TraceState.getDefault()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy