/** * Creates a new {@code traceparent}-compliant {@link TraceContext} with a 64 bit {@link #id}. * <p> * Note: the {@link #traceId} will still be 128 bit * </p> * @param tracer */ public static TraceContext with64BitId(ElasticApmTracer tracer) { return new TraceContext(tracer, Id.new64BitId()); }
/** * Returns the last 8 bytes of this id as a {@code long}. * <p> * The least significant bits (the right part) of an id is preferred to be used for making random sampling decisions. * </p> * <p> * "There are systems that make random sampling decisions based on the value of trace-id. * So to increase interoperability it is recommended to keep the random part on the right side of trace-id value." * </p> * @see <a href="https://github.com/w3c/distributed-tracing/blob/master/trace_context/HTTP_HEADER_FORMAT.md#trace-id">W3C trace context spec</a> * @return the last 8 bytes of this id as a {@code long} */ public long getLeastSignificantBits() { return readLong(data.length - 8); }
public void asChildOf(TraceContext parent) { traceId.copyFrom(parent.traceId); parentId.copyFrom(parent.id); transactionId.copyFrom(parent.transactionId); flags = parent.flags; id.setToRandomValue(); clock.init(parent.clock); onMutation(); }
@Test void testReInit() { final Id id = Id.new64BitId(); id.fromHexString("0000000000000001", 0); assertThat(id.toString()).isEqualTo("0000000000000001"); assertThat(id.isEmpty()).isFalse(); id.fromHexString("0000000000000002", 0); assertThat(id.toString()).isEqualTo("0000000000000002"); assertThat(id.isEmpty()).isFalse(); }
@Test void testFromAndToLong() { final Id id = Id.new128BitId(); id.fromLongs(21, 42); assertThat(id.isEmpty()).isFalse(); assertThat(id.readLong(0)).isEqualTo(21); assertThat(id.readLong(8)).isEqualTo(42); } }
return false; traceId.fromHexString(traceParentHeader, TRACE_ID_OFFSET); if (traceId.isEmpty()) { return false; parentId.fromHexString(traceParentHeader, PARENT_ID_OFFSET); if (parentId.isEmpty()) { return false; id.setToRandomValue(); transactionId.copyFrom(id);
@Test void isSampledEmpiricalTest() { int sampledTransactions = 0; Id id = Id.new128BitId(); for (int i = 0; i < ITERATIONS; i++) { id.setToRandomValue(); if (sampler.isSampled(id)) { sampledTransactions++; } } assertThat(sampledTransactions).isBetween((int) (SAMPLING_RATE * ITERATIONS - DELTA), (int) (SAMPLING_RATE * ITERATIONS + DELTA)); }
@Test void testSamplingLowerBoundary() { long lowerBound = -Long.MAX_VALUE / 2; final Id transactionId = Id.new128BitId(); transactionId.fromLongs((long) 0, lowerBound + 1); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isTrue(); transactionId.fromLongs((long) 0, lowerBound); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isTrue(); transactionId.fromLongs((long) 0, lowerBound - 1); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isFalse(); }
public void setToRandomValue() { setToRandomValue(ThreadLocalRandom.current()); }
@Override public void resetState() { traceId.resetState(); id.resetState(); parentId.resetState(); outgoingHeader.setLength(0); flags = 0; clock.resetState(); }
/** * Creates a new {@link TraceContext} with a 128 bit {@link #id}, * suitable for errors, * as those might not have a trace reference and therefore require a larger id in order to be globally unique. * @param tracer */ public static TraceContext with128BitId(ElasticApmTracer tracer) { return new TraceContext(tracer, Id.new128BitId()); }
public static Id new128BitId() { return new Id(16); }
@Test void testInitEmpty() { final Id id = Id.new64BitId(); assertThat(id.toString()).isEqualTo("0000000000000000"); assertThat(id.isEmpty()).isTrue(); id.fromHexString("0000000000000000", 0); assertThat(id.toString()).isEqualTo("0000000000000000"); assertThat(id.isEmpty()).isTrue(); id.fromLongs(0); assertThat(id.toString()).isEqualTo("0000000000000000"); assertThat(id.isEmpty()).isTrue(); }
public void asRootSpan(Sampler sampler) { traceId.setToRandomValue(); id.setToRandomValue(); transactionId.copyFrom(id); if (sampler.isSampled(traceId)) { this.flags = FLAG_RECORDED; } clock.init(); onMutation(); }
@Test void testSamplingUpperBoundary() { long upperBound = Long.MAX_VALUE / 2; final Id transactionId = Id.new128BitId(); transactionId.fromLongs((long) 0, upperBound - 1); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isTrue(); transactionId.fromLongs((long) 0, upperBound); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isTrue(); transactionId.fromLongs((long) 0, upperBound + 1); assertThat(ProbabilitySampler.of(0.5).isSampled(transactionId)).isFalse(); }
public void captureException(long epochMicros, @Nullable Throwable e, @Nullable TraceContextHolder<?> active) { if (e != null) { ErrorCapture error = errorPool.createInstance(); error.withTimestamp(epochMicros); error.setException(e); Transaction currentTransaction = currentTransaction(); if (currentTransaction != null) { error.setTransactionType(currentTransaction.getType()); error.setTransactionSampled(currentTransaction.isSampled()); } if (active != null) { if (active instanceof Transaction) { Transaction transaction = (Transaction) active; // The error might have occurred in a different thread than the one the transaction was recorded // That's why we have to ensure the visibility of the transaction properties error.getContext().copyFrom(transaction.getContextEnsureVisibility()); } else if (active instanceof Span) { Span span = (Span) active; error.getContext().getTags().putAll(span.getContext().getTags()); } error.asChildOf(active.getTraceContext()); } else { error.getTraceContext().getId().setToRandomValue(); } reporter.report(error); } }
public static Id new64BitId() { return new Id(8); }