Separating the B3 logic for Single and Multiple headers (#1235)
* Separating the B3 logic for Single and Multiple headers * Refactored to static variables for Single/Multi Headers * Fixes review comments - javadoc and ctor changes * exposing B3Propagator via static getters * Dummy commit to test the build * Converted the abstract class into interface for injector/extractor
This commit is contained in:
parent
833c30af98
commit
2577fc71a0
|
|
@ -197,7 +197,7 @@ public class PropagatorContextExtractBenchmark {
|
|||
}
|
||||
};
|
||||
|
||||
private final B3Propagator b3Propagator = new B3Propagator(true);
|
||||
private final B3Propagator b3Propagator = B3Propagator.getSingleHeaderPropagator();
|
||||
|
||||
@Override
|
||||
protected Context doExtract() {
|
||||
|
|
@ -243,7 +243,7 @@ public class PropagatorContextExtractBenchmark {
|
|||
}
|
||||
};
|
||||
|
||||
private final B3Propagator b3Propagator = new B3Propagator();
|
||||
private final B3Propagator b3Propagator = B3Propagator.getMultipleHeaderPropagator();
|
||||
|
||||
@Override
|
||||
protected Context doExtract() {
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ public class PropagatorContextInjectBenchmark {
|
|||
/** Benchmark for injecting trace context into a single B3 header. */
|
||||
public static class B3SingleHeaderContextInjectBenchmark extends AbstractContextInjectBenchmark {
|
||||
|
||||
private final B3Propagator b3Propagator = new B3Propagator(true);
|
||||
private final B3Propagator b3Propagator = B3Propagator.getSingleHeaderPropagator();
|
||||
private final B3Propagator.Setter<Map<String, String>> setter =
|
||||
new B3Propagator.Setter<Map<String, String>>() {
|
||||
@Override
|
||||
|
|
@ -139,7 +139,7 @@ public class PropagatorContextInjectBenchmark {
|
|||
public static class B3MultipleHeaderContextInjectBenchmark
|
||||
extends AbstractContextInjectBenchmark {
|
||||
|
||||
private final B3Propagator b3Propagator = new B3Propagator();
|
||||
private final B3Propagator b3Propagator = B3Propagator.getMultipleHeaderPropagator();
|
||||
private final B3Propagator.Setter<Map<String, String>> setter =
|
||||
new B3Propagator.Setter<Map<String, String>>() {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -51,19 +51,41 @@ public class B3Propagator implements HttpTextFormat {
|
|||
private final B3PropagatorInjector b3PropagatorInjector;
|
||||
private final B3PropagatorExtractor b3PropagatorExtractor;
|
||||
|
||||
/** Creates a new instance of {@link B3Propagator}. Defaults to use multiple headers. */
|
||||
public B3Propagator() {
|
||||
this(false);
|
||||
private static final B3Propagator SINGLE_HEADER =
|
||||
new B3Propagator(
|
||||
new B3PropagatorInjectorSingleHeader(), new B3PropagatorExtractorSingleHeader());
|
||||
private static final B3Propagator MULTI_HEADER =
|
||||
new B3Propagator(
|
||||
new B3PropagatorInjectorMultipleHeaders(), new B3PropagatorExtractorMultipleHeaders());
|
||||
|
||||
/**
|
||||
* Returns an instance of {@link B3Propagator} with Single Header Implementation of B3 propagation
|
||||
* protocol. See <a
|
||||
* href=https://github.com/openzipkin/b3-propagation#single-header>openzipkin/b3-propagation#single-header</a>.
|
||||
*
|
||||
* @return Returns an instance of {@link B3Propagator} with Single Header implementation of B3
|
||||
* propagation protocol.
|
||||
*/
|
||||
public static B3Propagator getSingleHeaderPropagator() {
|
||||
return SINGLE_HEADER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link B3Propagator}.
|
||||
* Returns an instance of {@link B3Propagator} with Multiple Header Implementation of B3
|
||||
* propagation protocol. See <a
|
||||
* href=https://github.com/openzipkin/b3-propagation#multiple-headers>openzipkin/b3-propagation#multiple-headers</a>.
|
||||
*
|
||||
* @param singleHeader whether to use single or multiple headers.
|
||||
* @return Returns an instance of {@link B3Propagator} with Multiple Header implementation of B3
|
||||
* propagation protocol.
|
||||
*/
|
||||
public B3Propagator(boolean singleHeader) {
|
||||
b3PropagatorInjector = new B3PropagatorInjector(singleHeader);
|
||||
b3PropagatorExtractor = new B3PropagatorExtractor(singleHeader);
|
||||
public static B3Propagator getMultipleHeaderPropagator() {
|
||||
return MULTI_HEADER;
|
||||
}
|
||||
|
||||
private B3Propagator(
|
||||
B3PropagatorInjector b3PropagatorInjector, B3PropagatorExtractor b3PropagatorExtractor) {
|
||||
this.b3PropagatorInjector = b3PropagatorInjector;
|
||||
this.b3PropagatorExtractor = b3PropagatorExtractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -16,140 +16,60 @@
|
|||
|
||||
package io.opentelemetry.contrib.trace.propagation;
|
||||
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.COMBINED_HEADER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.COMBINED_HEADER_DELIMITER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.MAX_SPAN_ID_LENGTH;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.MAX_TRACE_ID_LENGTH;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.SAMPLED_HEADER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.SPAN_ID_HEADER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.TRACE_ID_HEADER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.TRUE_INT;
|
||||
|
||||
import io.grpc.Context;
|
||||
import io.opentelemetry.context.propagation.HttpTextFormat;
|
||||
import io.opentelemetry.internal.StringUtils;
|
||||
import io.opentelemetry.trace.DefaultSpan;
|
||||
import io.opentelemetry.trace.SpanContext;
|
||||
import io.opentelemetry.trace.SpanId;
|
||||
import io.opentelemetry.trace.TraceFlags;
|
||||
import io.opentelemetry.trace.TraceId;
|
||||
import io.opentelemetry.trace.TraceState;
|
||||
import io.opentelemetry.trace.TracingContextUtils;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
final class B3PropagatorExtractor {
|
||||
private static final TraceFlags SAMPLED_FLAGS = TraceFlags.builder().setIsSampled(true).build();
|
||||
private static final TraceFlags NOT_SAMPLED_FLAGS =
|
||||
TraceFlags.builder().setIsSampled(false).build();
|
||||
private static final Logger logger = Logger.getLogger(B3PropagatorExtractor.class.getName());
|
||||
interface B3PropagatorExtractor {
|
||||
|
||||
private final boolean isSingleHeader;
|
||||
<C> Context extract(Context context, C carrier, HttpTextFormat.Getter<C> getter);
|
||||
|
||||
B3PropagatorExtractor(boolean isSingleHeader) {
|
||||
this.isSingleHeader = isSingleHeader;
|
||||
}
|
||||
@Immutable
|
||||
class Util {
|
||||
private static final Logger logger = Logger.getLogger(Util.class.getName());
|
||||
private static final TraceFlags SAMPLED_FLAGS = TraceFlags.builder().setIsSampled(true).build();
|
||||
private static final TraceFlags NOT_SAMPLED_FLAGS =
|
||||
TraceFlags.builder().setIsSampled(false).build();
|
||||
|
||||
<C> Context extract(Context context, C carrier, HttpTextFormat.Getter<C> getter) {
|
||||
Objects.requireNonNull(carrier, "carrier");
|
||||
Objects.requireNonNull(getter, "getter");
|
||||
private Util() {}
|
||||
|
||||
SpanContext spanContext;
|
||||
static SpanContext buildSpanContext(String traceId, String spanId, String sampled) {
|
||||
try {
|
||||
TraceFlags traceFlags =
|
||||
TRUE_INT.equals(sampled) || Boolean.parseBoolean(sampled) // accept either "1" or "true"
|
||||
? SAMPLED_FLAGS
|
||||
: NOT_SAMPLED_FLAGS;
|
||||
|
||||
if (isSingleHeader) {
|
||||
spanContext = getSpanContextFromSingleHeader(carrier, getter);
|
||||
} else {
|
||||
spanContext = getSpanContextFromMultipleHeaders(carrier, getter);
|
||||
return SpanContext.createFromRemoteParent(
|
||||
TraceId.fromLowerBase16(StringUtils.padLeft(traceId, MAX_TRACE_ID_LENGTH), 0),
|
||||
SpanId.fromLowerBase16(spanId, 0),
|
||||
traceFlags,
|
||||
TraceState.getDefault());
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.INFO, "Error parsing B3 header. Returning INVALID span context.", e);
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
}
|
||||
|
||||
return TracingContextUtils.withSpan(DefaultSpan.create(spanContext), context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringSplitter")
|
||||
private static <C> SpanContext getSpanContextFromSingleHeader(
|
||||
C carrier, HttpTextFormat.Getter<C> getter) {
|
||||
String value = getter.get(carrier, COMBINED_HEADER);
|
||||
if (StringUtils.isNullOrEmpty(value)) {
|
||||
return SpanContext.getInvalid();
|
||||
static boolean isTraceIdValid(String value) {
|
||||
return !(StringUtils.isNullOrEmpty(value) || value.length() > MAX_TRACE_ID_LENGTH);
|
||||
}
|
||||
|
||||
// must have between 2 and 4 hyphen delimieted parts:
|
||||
// traceId-spanId-sampled-parentSpanId (last two are optional)
|
||||
// NOTE: we do not use parentSpanId
|
||||
String[] parts = value.split(COMBINED_HEADER_DELIMITER);
|
||||
if (parts.length < 2 || parts.length > 4) {
|
||||
logger.info(
|
||||
"Invalid combined header '" + COMBINED_HEADER + ". Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
static boolean isSpanIdValid(String value) {
|
||||
return !(StringUtils.isNullOrEmpty(value) || value.length() > MAX_SPAN_ID_LENGTH);
|
||||
}
|
||||
|
||||
String traceId = parts[0];
|
||||
if (!isTraceIdValid(traceId)) {
|
||||
logger.info(
|
||||
"Invalid TraceId in B3 header: " + COMBINED_HEADER + ". Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String spanId = parts[1];
|
||||
if (!isSpanIdValid(spanId)) {
|
||||
logger.info(
|
||||
"Invalid SpanId in B3 header: " + COMBINED_HEADER + ". Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String sampled = parts.length >= 3 ? parts[2] : null;
|
||||
|
||||
return buildSpanContext(traceId, spanId, sampled);
|
||||
}
|
||||
|
||||
private static <C> SpanContext getSpanContextFromMultipleHeaders(
|
||||
C carrier, HttpTextFormat.Getter<C> getter) {
|
||||
String traceId = getter.get(carrier, TRACE_ID_HEADER);
|
||||
if (!isTraceIdValid(traceId)) {
|
||||
logger.info(
|
||||
"Invalid TraceId in B3 header: "
|
||||
+ TRACE_ID_HEADER
|
||||
+ "'. Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String spanId = getter.get(carrier, SPAN_ID_HEADER);
|
||||
if (!isSpanIdValid(spanId)) {
|
||||
logger.info(
|
||||
"Invalid SpanId in B3 header: " + SPAN_ID_HEADER + "'. Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String sampled = getter.get(carrier, SAMPLED_HEADER);
|
||||
return buildSpanContext(traceId, spanId, sampled);
|
||||
}
|
||||
|
||||
private static SpanContext buildSpanContext(String traceId, String spanId, String sampled) {
|
||||
try {
|
||||
TraceFlags traceFlags =
|
||||
TRUE_INT.equals(sampled) || Boolean.parseBoolean(sampled) // accept either "1" or "true"
|
||||
? SAMPLED_FLAGS
|
||||
: NOT_SAMPLED_FLAGS;
|
||||
|
||||
return SpanContext.createFromRemoteParent(
|
||||
TraceId.fromLowerBase16(StringUtils.padLeft(traceId, MAX_TRACE_ID_LENGTH), 0),
|
||||
SpanId.fromLowerBase16(spanId, 0),
|
||||
traceFlags,
|
||||
TraceState.getDefault());
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.INFO, "Error parsing B3 header. Returning INVALID span context.", e);
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isTraceIdValid(String value) {
|
||||
return !(StringUtils.isNullOrEmpty(value) || value.length() > MAX_TRACE_ID_LENGTH);
|
||||
}
|
||||
|
||||
private static boolean isSpanIdValid(String value) {
|
||||
return !(StringUtils.isNullOrEmpty(value) || value.length() > MAX_SPAN_ID_LENGTH);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2020, OpenTelemetry Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.trace.propagation;
|
||||
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.SAMPLED_HEADER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.SPAN_ID_HEADER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.TRACE_ID_HEADER;
|
||||
|
||||
import io.grpc.Context;
|
||||
import io.opentelemetry.context.propagation.HttpTextFormat;
|
||||
import io.opentelemetry.trace.DefaultSpan;
|
||||
import io.opentelemetry.trace.SpanContext;
|
||||
import io.opentelemetry.trace.TracingContextUtils;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
final class B3PropagatorExtractorMultipleHeaders implements B3PropagatorExtractor {
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(B3PropagatorExtractorMultipleHeaders.class.getName());
|
||||
|
||||
@Override
|
||||
public <C> Context extract(Context context, C carrier, HttpTextFormat.Getter<C> getter) {
|
||||
Objects.requireNonNull(carrier, "carrier");
|
||||
Objects.requireNonNull(getter, "getter");
|
||||
SpanContext spanContext = getSpanContextFromMultipleHeaders(carrier, getter);
|
||||
return TracingContextUtils.withSpan(DefaultSpan.create(spanContext), context);
|
||||
}
|
||||
|
||||
private static <C> SpanContext getSpanContextFromMultipleHeaders(
|
||||
C carrier, HttpTextFormat.Getter<C> getter) {
|
||||
String traceId = getter.get(carrier, TRACE_ID_HEADER);
|
||||
if (!Util.isTraceIdValid(traceId)) {
|
||||
logger.info(
|
||||
"Invalid TraceId in B3 header: "
|
||||
+ TRACE_ID_HEADER
|
||||
+ "'. Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String spanId = getter.get(carrier, SPAN_ID_HEADER);
|
||||
if (!Util.isSpanIdValid(spanId)) {
|
||||
logger.info(
|
||||
"Invalid SpanId in B3 header: " + SPAN_ID_HEADER + "'. Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String sampled = getter.get(carrier, SAMPLED_HEADER);
|
||||
return Util.buildSpanContext(traceId, spanId, sampled);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2020, OpenTelemetry Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.trace.propagation;
|
||||
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.COMBINED_HEADER;
|
||||
import static io.opentelemetry.contrib.trace.propagation.B3Propagator.COMBINED_HEADER_DELIMITER;
|
||||
|
||||
import io.grpc.Context;
|
||||
import io.opentelemetry.context.propagation.HttpTextFormat;
|
||||
import io.opentelemetry.internal.StringUtils;
|
||||
import io.opentelemetry.trace.DefaultSpan;
|
||||
import io.opentelemetry.trace.SpanContext;
|
||||
import io.opentelemetry.trace.TracingContextUtils;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
final class B3PropagatorExtractorSingleHeader implements B3PropagatorExtractor {
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(B3PropagatorExtractorSingleHeader.class.getName());
|
||||
|
||||
@Override
|
||||
public <C> Context extract(Context context, C carrier, HttpTextFormat.Getter<C> getter) {
|
||||
Objects.requireNonNull(carrier, "carrier");
|
||||
Objects.requireNonNull(getter, "getter");
|
||||
SpanContext spanContext = getSpanContextFromSingleHeader(carrier, getter);
|
||||
return TracingContextUtils.withSpan(DefaultSpan.create(spanContext), context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringSplitter")
|
||||
private static <C> SpanContext getSpanContextFromSingleHeader(
|
||||
C carrier, HttpTextFormat.Getter<C> getter) {
|
||||
String value = getter.get(carrier, COMBINED_HEADER);
|
||||
if (StringUtils.isNullOrEmpty(value)) {
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
// must have between 2 and 4 hyphen delimieted parts:
|
||||
// traceId-spanId-sampled-parentSpanId (last two are optional)
|
||||
// NOTE: we do not use parentSpanId
|
||||
String[] parts = value.split(COMBINED_HEADER_DELIMITER);
|
||||
if (parts.length < 2 || parts.length > 4) {
|
||||
logger.info(
|
||||
"Invalid combined header '" + COMBINED_HEADER + ". Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String traceId = parts[0];
|
||||
if (!Util.isTraceIdValid(traceId)) {
|
||||
logger.info(
|
||||
"Invalid TraceId in B3 header: " + COMBINED_HEADER + ". Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String spanId = parts[1];
|
||||
if (!Util.isSpanIdValid(spanId)) {
|
||||
logger.info(
|
||||
"Invalid SpanId in B3 header: " + COMBINED_HEADER + ". Returning INVALID span context.");
|
||||
return SpanContext.getInvalid();
|
||||
}
|
||||
|
||||
String sampled = parts.length >= 3 ? parts[2] : null;
|
||||
|
||||
return Util.buildSpanContext(traceId, spanId, sampled);
|
||||
}
|
||||
}
|
||||
|
|
@ -18,59 +18,9 @@ package io.opentelemetry.contrib.trace.propagation;
|
|||
|
||||
import io.grpc.Context;
|
||||
import io.opentelemetry.context.propagation.HttpTextFormat;
|
||||
import io.opentelemetry.trace.Span;
|
||||
import io.opentelemetry.trace.SpanContext;
|
||||
import io.opentelemetry.trace.SpanId;
|
||||
import io.opentelemetry.trace.TraceId;
|
||||
import io.opentelemetry.trace.TracingContextUtils;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
final class B3PropagatorInjector {
|
||||
private static final int SAMPLED_FLAG_SIZE = 1;
|
||||
private static final int TRACE_ID_HEX_SIZE = 2 * TraceId.getSize();
|
||||
private static final int SPAN_ID_HEX_SIZE = 2 * SpanId.getSize();
|
||||
private static final int COMBINED_HEADER_DELIMITER_SIZE = 1;
|
||||
private static final int SPAN_ID_OFFSET = TRACE_ID_HEX_SIZE + COMBINED_HEADER_DELIMITER_SIZE;
|
||||
private static final int SAMPLED_FLAG_OFFSET =
|
||||
SPAN_ID_OFFSET + SPAN_ID_HEX_SIZE + COMBINED_HEADER_DELIMITER_SIZE;
|
||||
private static final int COMBINED_HEADER_SIZE = SAMPLED_FLAG_OFFSET + SAMPLED_FLAG_SIZE;
|
||||
|
||||
private final boolean singleHeader;
|
||||
|
||||
B3PropagatorInjector(boolean singleHeader) {
|
||||
this.singleHeader = singleHeader;
|
||||
}
|
||||
|
||||
<C> void inject(Context context, C carrier, HttpTextFormat.Setter<C> setter) {
|
||||
Objects.requireNonNull(context, "context");
|
||||
Objects.requireNonNull(setter, "setter");
|
||||
|
||||
Span span = TracingContextUtils.getSpanWithoutDefault(context);
|
||||
if (span == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SpanContext spanContext = span.getContext();
|
||||
String sampled =
|
||||
spanContext.getTraceFlags().isSampled() ? B3Propagator.TRUE_INT : B3Propagator.FALSE_INT;
|
||||
|
||||
if (singleHeader) {
|
||||
char[] chars = new char[COMBINED_HEADER_SIZE];
|
||||
spanContext.getTraceId().copyLowerBase16To(chars, 0);
|
||||
chars[SPAN_ID_OFFSET - 1] = B3Propagator.COMBINED_HEADER_DELIMITER_CHAR;
|
||||
spanContext.getSpanId().copyLowerBase16To(chars, SPAN_ID_OFFSET);
|
||||
chars[SAMPLED_FLAG_OFFSET - 1] = B3Propagator.COMBINED_HEADER_DELIMITER_CHAR;
|
||||
chars[SAMPLED_FLAG_OFFSET] =
|
||||
spanContext.getTraceFlags().isSampled()
|
||||
? B3Propagator.IS_SAMPLED
|
||||
: B3Propagator.NOT_SAMPLED;
|
||||
setter.set(carrier, B3Propagator.COMBINED_HEADER, new String(chars));
|
||||
} else {
|
||||
setter.set(carrier, B3Propagator.TRACE_ID_HEADER, spanContext.getTraceId().toLowerBase16());
|
||||
setter.set(carrier, B3Propagator.SPAN_ID_HEADER, spanContext.getSpanId().toLowerBase16());
|
||||
setter.set(carrier, B3Propagator.SAMPLED_HEADER, sampled);
|
||||
}
|
||||
}
|
||||
interface B3PropagatorInjector {
|
||||
<C> void inject(Context context, C carrier, HttpTextFormat.Setter<C> setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2020, OpenTelemetry Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.trace.propagation;
|
||||
|
||||
import io.grpc.Context;
|
||||
import io.opentelemetry.context.propagation.HttpTextFormat;
|
||||
import io.opentelemetry.trace.Span;
|
||||
import io.opentelemetry.trace.SpanContext;
|
||||
import io.opentelemetry.trace.TracingContextUtils;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
final class B3PropagatorInjectorMultipleHeaders implements B3PropagatorInjector {
|
||||
@Override
|
||||
public <C> void inject(Context context, C carrier, HttpTextFormat.Setter<C> setter) {
|
||||
Objects.requireNonNull(context, "context");
|
||||
Objects.requireNonNull(setter, "setter");
|
||||
|
||||
Span span = TracingContextUtils.getSpanWithoutDefault(context);
|
||||
if (span == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SpanContext spanContext = span.getContext();
|
||||
String sampled =
|
||||
spanContext.getTraceFlags().isSampled() ? B3Propagator.TRUE_INT : B3Propagator.FALSE_INT;
|
||||
|
||||
setter.set(carrier, B3Propagator.TRACE_ID_HEADER, spanContext.getTraceId().toLowerBase16());
|
||||
setter.set(carrier, B3Propagator.SPAN_ID_HEADER, spanContext.getSpanId().toLowerBase16());
|
||||
setter.set(carrier, B3Propagator.SAMPLED_HEADER, sampled);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2020, OpenTelemetry Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.opentelemetry.contrib.trace.propagation;
|
||||
|
||||
import io.grpc.Context;
|
||||
import io.opentelemetry.context.propagation.HttpTextFormat;
|
||||
import io.opentelemetry.trace.Span;
|
||||
import io.opentelemetry.trace.SpanContext;
|
||||
import io.opentelemetry.trace.SpanId;
|
||||
import io.opentelemetry.trace.TraceId;
|
||||
import io.opentelemetry.trace.TracingContextUtils;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
final class B3PropagatorInjectorSingleHeader implements B3PropagatorInjector {
|
||||
private static final int SAMPLED_FLAG_SIZE = 1;
|
||||
private static final int TRACE_ID_HEX_SIZE = 2 * TraceId.getSize();
|
||||
private static final int SPAN_ID_HEX_SIZE = 2 * SpanId.getSize();
|
||||
private static final int COMBINED_HEADER_DELIMITER_SIZE = 1;
|
||||
private static final int SPAN_ID_OFFSET = TRACE_ID_HEX_SIZE + COMBINED_HEADER_DELIMITER_SIZE;
|
||||
private static final int SAMPLED_FLAG_OFFSET =
|
||||
SPAN_ID_OFFSET + SPAN_ID_HEX_SIZE + COMBINED_HEADER_DELIMITER_SIZE;
|
||||
private static final int COMBINED_HEADER_SIZE = SAMPLED_FLAG_OFFSET + SAMPLED_FLAG_SIZE;
|
||||
|
||||
@Override
|
||||
public <C> void inject(Context context, C carrier, HttpTextFormat.Setter<C> setter) {
|
||||
Objects.requireNonNull(context, "context");
|
||||
Objects.requireNonNull(setter, "setter");
|
||||
|
||||
Span span = TracingContextUtils.getSpanWithoutDefault(context);
|
||||
if (span == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SpanContext spanContext = span.getContext();
|
||||
|
||||
char[] chars = new char[COMBINED_HEADER_SIZE];
|
||||
spanContext.getTraceId().copyLowerBase16To(chars, 0);
|
||||
chars[SPAN_ID_OFFSET - 1] = B3Propagator.COMBINED_HEADER_DELIMITER_CHAR;
|
||||
spanContext.getSpanId().copyLowerBase16To(chars, SPAN_ID_OFFSET);
|
||||
chars[SAMPLED_FLAG_OFFSET - 1] = B3Propagator.COMBINED_HEADER_DELIMITER_CHAR;
|
||||
chars[SAMPLED_FLAG_OFFSET] =
|
||||
spanContext.getTraceFlags().isSampled()
|
||||
? B3Propagator.IS_SAMPLED
|
||||
: B3Propagator.NOT_SAMPLED;
|
||||
setter.set(carrier, B3Propagator.COMBINED_HEADER, new String(chars));
|
||||
}
|
||||
}
|
||||
|
|
@ -69,8 +69,8 @@ public class B3PropagatorTest {
|
|||
return carrier.get(key);
|
||||
}
|
||||
};
|
||||
private final B3Propagator b3Propagator = new B3Propagator();
|
||||
private final B3Propagator b3PropagatorSingleHeader = new B3Propagator(true);
|
||||
private final B3Propagator b3Propagator = B3Propagator.getMultipleHeaderPropagator();
|
||||
private final B3Propagator b3PropagatorSingleHeader = B3Propagator.getSingleHeaderPropagator();
|
||||
@Rule public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private static SpanContext getSpanContext(Context context) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue