result = TraceContextOrSamplingFlags.create( TraceContext.newBuilder() .traceIdHigh(traceId[0]) .traceId(traceId[1]) .spanId(spanId) .sampled(traceTrue) .build());
@Override public TraceContextOrSamplingFlags extract(C carrier) { if (carrier == null) throw new NullPointerException("carrier == null"); // try to extract single-header format TraceContextOrSamplingFlags extracted = singleExtractor.extract(carrier); if (!extracted.equals(TraceContextOrSamplingFlags.EMPTY)) return extracted; // Start by looking at the sampled state as this is used regardless // Official sampled value is 1, though some old instrumentation send true String sampled = getter.get(carrier, propagation.sampledKey); Boolean sampledV = sampled != null ? sampled.equals("1") || sampled.equalsIgnoreCase("true") : null; boolean debug = "1".equals(getter.get(carrier, propagation.debugKey)); String traceIdString = getter.get(carrier, propagation.traceIdKey); // It is ok to go without a trace ID, if sampling or debug is set if (traceIdString == null) return TraceContextOrSamplingFlags.create(sampledV, debug); // Try to parse the trace IDs into the context TraceContext.Builder result = TraceContext.newBuilder(); if (result.parseTraceId(traceIdString, propagation.traceIdKey) && result.parseSpanId(getter, carrier, propagation.spanIdKey) && result.parseParentId(getter, carrier, propagation.parentSpanIdKey)) { if (sampledV != null) result.sampled(sampledV.booleanValue()); if (debug) result.debug(true); return TraceContextOrSamplingFlags.create(result.build()); } return TraceContextOrSamplingFlags.EMPTY; // trace context is malformed so return empty } }
/** * <em>Note:</em>If the key is {@linkplain Tags#SAMPLING_PRIORITY} and the value is zero, the * current span will be abandoned and future references to the {@link #context()} will be * unsampled. This does not affect the active span, nor does it affect any equivalent instances of * this object. This is a best efforts means to handle late sampling decisions. */ @Override public BraveSpan setTag(String key, Number value) { if (finishCalled) return this; if (trySetPeer(key, value)) return this; // handle late sampling decision if (Tags.SAMPLING_PRIORITY.getKey().equals(key) && value.intValue() == 0) { delegate.abandon(); // convert the span to no-op delegate = tracer.toSpan(delegate.context().toBuilder().sampled(false).build()); } return setTag(key, value.toString()); }
/** @see TraceContext#sampled() */ public Builder sampled(@Nullable Boolean sampled) { if (sampled == null) { flags &= ~(FLAG_SAMPLED_SET | FLAG_SAMPLED); return this; } return sampled(sampled.booleanValue()); }
/** * When the caller propagates IDs, but not a sampling decision, the current process should * decide. */ @Test public void verifyRoundTrip_externallyProvidedIds() { inject(map, "0000000000000001", null, "0000000000000001", null, null); verifyRoundTrip(TraceContextOrSamplingFlags.create(rootSpan.toBuilder().sampled(null).build())); }
@Test public void restoresSpanAfterRunnable() throws Exception { TraceContext context0 = TraceContext.newBuilder().traceId(3L).spanId(3L).build(); try (Scope scope0 = currentTraceContext.newScope(context0)) { attachesSpanInRunnable(); assertThat(currentTraceContext.get()) .isEqualTo(context0); verifyImplicitContext(context0); } }
@Test public void verifyRoundTrip_128BitTrace() throws Exception { String high64Bits = "463ac35c9f6413ad"; String low64Bits = "48485a3953bb6124"; inject(map, high64Bits + low64Bits, null, low64Bits, true, null); verifyRoundTrip(TraceContextOrSamplingFlags.create(rootSpan.toBuilder() .traceIdHigh(HexCodec.lowerHexToUnsignedLong(high64Bits)) .traceId(HexCodec.lowerHexToUnsignedLong(low64Bits)) .spanId(HexCodec.lowerHexToUnsignedLong(low64Bits)).build())); }
void noticesDifferentSpanId(Scope scope) { TraceContext differentSpanId = context.toBuilder().spanId(context.spanId() + 1L).build(); try (Scope scope2 = currentTraceContext.maybeScope(differentSpanId)) { assertThat(scope2).isNotEqualTo(Scope.NOOP); assertThat(currentTraceContext.get()) .isEqualTo(differentSpanId); verifyImplicitContext(differentSpanId); } finally { scope.close(); } }
public static TraceContext toTraceContext(SpanId spanId) { // visible for testing if (spanId == null) throw new NullPointerException("spanId == null"); return TraceContext.newBuilder() .traceIdHigh(spanId.traceIdHigh) .traceId(spanId.traceId) .parentId(spanId.nullableParentId()) .spanId(spanId.spanId) .debug(spanId.debug()) .sampled(spanId.sampled()).build(); }
@Override public void accept(Propagation<?> propagation) { TraceContext.Injector<Map<Object, String>> injector = propagation.injector(Map::put); TraceContext.Extractor<Map<Object, String>> extractor = propagation.extractor(Map::get); TraceContext ctx = TraceContext.newBuilder().traceId(1L).spanId(2L).sampled(false).build(); Map<Object, String> map = new LinkedHashMap<>(); injector.inject(ctx, map); assertThat(extractor.extract(map).context()) .isEqualToIgnoringGivenFields(ctx, "traceIdString", "spanIdString"); } }
@Override public TraceContextOrSamplingFlags extract(C carrier) { if (carrier == null) throw new NullPointerException("carrier == null"); // try to extract single-header format TraceContextOrSamplingFlags extracted = singleExtractor.extract(carrier); if (!extracted.equals(TraceContextOrSamplingFlags.EMPTY)) return extracted; // Start by looking at the sampled state as this is used regardless // Official sampled value is 1, though some old instrumentation send true String sampled = getter.get(carrier, propagation.sampledKey); Boolean sampledV = sampled != null ? sampled.equals("1") || sampled.equalsIgnoreCase("true") : null; boolean debug = "1".equals(getter.get(carrier, propagation.debugKey)); String traceIdString = getter.get(carrier, propagation.traceIdKey); // It is ok to go without a trace ID, if sampling or debug is set if (traceIdString == null) return TraceContextOrSamplingFlags.create(sampledV, debug); // Try to parse the trace IDs into the context TraceContext.Builder result = TraceContext.newBuilder(); if (result.parseTraceId(traceIdString, propagation.traceIdKey) && result.parseSpanId(getter, carrier, propagation.spanIdKey) && result.parseParentId(getter, carrier, propagation.parentSpanIdKey)) { if (sampledV != null) result.sampled(sampledV.booleanValue()); if (debug) result.debug(true); return TraceContextOrSamplingFlags.create(result.build()); } return TraceContextOrSamplingFlags.EMPTY; // trace context is malformed so return empty } }
/** * Ensures the specified {@link Tracing} uses a {@link RequestContextCurrentTraceContext}. * * @throws IllegalStateException if {@code tracing} does not use {@link RequestContextCurrentTraceContext} */ public static void ensureScopeUsesRequestContext(Tracing tracing) { final PingPongExtra extra = new PingPongExtra(); // trace contexts are not recorded until Tracer.toSpan, so this won't end up as junk data final TraceContext dummyContext = TraceContext.newBuilder().traceId(1).spanId(1) .extra(Collections.singletonList(extra)).build(); final boolean scopeUsesRequestContext; try (Scope scope = tracing.currentTraceContext().newScope(dummyContext)) { scopeUsesRequestContext = extra.isPong(); } if (!scopeUsesRequestContext) { throw new IllegalStateException( "Tracing.currentTraceContext is not a " + RequestContextCurrentTraceContext.class .getSimpleName() + " scope. " + "Please call Tracing.Builder.currentTraceContext(" + RequestContextCurrentTraceContext.class .getSimpleName() + ".INSTANCE)."); } }