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:
Sameer Kulkarni 2020-05-26 22:56:05 +05:30 committed by GitHub
parent 833c30af98
commit 2577fc71a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 323 additions and 174 deletions

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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) {