Skip to content

Commit e57846e

Browse files
committed
Use top span id as the local id
1 parent 20aae2c commit e57846e

6 files changed

Lines changed: 49 additions & 67 deletions

File tree

tracing-jersey/src/main/java/com/palantir/tracing/jersey/TraceEnrichingFilter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
7373
Tracer.fastStartSpan(operation, SpanType.SERVER_INCOMING);
7474
} else {
7575
// propagate the traceid from request headers, but create a new local trace id to disambiguate
76-
Tracer.initTrace(getObservabilityFromHeader(requestContext), traceId, Tracers.randomId());
76+
Tracer.initTrace(getObservabilityFromHeader(requestContext), traceId);
7777
if (spanId == null) {
7878
Tracer.fastStartSpan(operation, SpanType.SERVER_INCOMING);
7979
} else {
@@ -84,7 +84,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
8484

8585
// Give asynchronous downstream handlers access to the trace id
8686
requestContext.setProperty(TRACE_ID_PROPERTY_NAME, Tracer.getTraceId());
87-
Tracer.getLocalTraceId().ifPresent(localId ->
87+
Tracer.getTopSpanId().ifPresent(localId ->
8888
requestContext.setProperty(LOCAL_TRACE_ID_PROPERTY_NAME, localId));
8989
requestContext.setProperty(SAMPLED_PROPERTY_NAME, Tracer.isTraceObservable());
9090
}

tracing-jersey/src/test/java/com/palantir/tracing/jersey/TraceEnrichingFilterTest.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,17 +185,6 @@ public void testTraceState_withoutRequestHeadersGeneratesValidTraceResponseHeade
185185
assertThat(spanCaptor.getValue().getOperation()).isEqualTo("Jersey: GET /trace");
186186
}
187187

188-
@Test
189-
public void testTraceState_withoutRequestHeadersDoesNotGenerateLocalTrace() {
190-
Response response = target.path("/local-trace").request().get();
191-
assertThat(response.getHeaderString(TraceHttpHeaders.TRACE_ID)).isNotNull();
192-
assertThat(response.getHeaderString(TraceHttpHeaders.PARENT_SPAN_ID)).isNull();
193-
assertThat(response.getHeaderString(TraceHttpHeaders.SPAN_ID)).isNull();
194-
verify(observer).consume(spanCaptor.capture());
195-
assertThat(spanCaptor.getValue().getOperation()).isEqualTo("Jersey: GET /local-trace");
196-
assertThat(response.readEntity(String.class)).isNullOrEmpty();
197-
}
198-
199188
@Test
200189
public void testTraceState_withoutRequestHeadersGeneratesValidTraceResponseHeadersWhenFailing() {
201190
Response response = target.path("/failing-trace").request().get();
@@ -305,7 +294,7 @@ public void getFailingTraceOperation() {
305294

306295
@Override
307296
public String getLocalTraceId() {
308-
return Tracer.getLocalTraceId().orElse(null);
297+
return Tracer.getTopSpanId().orElse(null);
309298
}
310299

311300
@Override

tracing-undertow/src/main/java/com/palantir/tracing/undertow/TracedOperationHandler.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ private String initializeTrace(HttpServerExchange exchange) {
100100

101101
/** Initializes trace state given a trace-id header from the client. */
102102
private void initializeTraceFromExisting(HeaderMap headers, String traceId) {
103-
// propagate the traceid from request headers, but create a new local trace id to disambiguate
104-
Tracer.initTrace(getObservabilityFromHeader(headers), traceId, Tracers.randomId());
103+
Tracer.initTrace(getObservabilityFromHeader(headers), traceId);
105104
String spanId = headers.getFirst(SPAN_ID); // nullable
106105
if (spanId == null) {
107106
Tracer.fastStartSpan(operation, SpanType.SERVER_INCOMING);

tracing-undertow/src/test/java/com/palantir/tracing/undertow/TracedOperationHandlerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public void whenTraceIsInHeader_usesGivenTraceIdwithDifferentLocalIds() throws E
110110
TracedOperationHandler traceSettingHandler =
111111
new TracedOperationHandler(exc -> {
112112
traceIdValue.set(Tracer.getTraceId());
113-
localTraceIdValue.set(Tracer.getLocalTraceId().orElse(null));
113+
localTraceIdValue.set(Tracer.getTopSpanId().orElse(null));
114114

115115
}, "GET /traced");
116116
traceSettingHandler.handleRequest(exchange);

tracing/src/main/java/com/palantir/tracing/Trace.java

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,10 @@
4545
public abstract class Trace {
4646

4747
private final String traceId;
48-
@Nullable
49-
private final String localTraceId;
5048

51-
private Trace(String traceId, @Nullable String localTraceId) {
49+
private Trace(String traceId) {
5250
checkArgument(!Strings.isNullOrEmpty(traceId), "traceId must be non-empty");
5351
this.traceId = traceId;
54-
this.localTraceId = localTraceId;
5552
}
5653

5754
/**
@@ -143,39 +140,31 @@ final String getTraceId() {
143140
/**
144141
* The globally unique non-empty identifier for this call trace within a service (or another locality context).
145142
*
146-
* While {@link #getTraceId()} is expected to be propagated across RPC calls, localTraceId distinguishes between
147-
* two concurrent RPC calls made to a service with the same traceid.
143+
* While {@link #getTraceId()} is expected to be propagated across RPC calls, the top span id distinguishes
144+
* between two concurrent RPC calls made to a service with the same traceid.
148145
*/
149-
final Optional<String> getLocalTraceId() {
150-
// XXX: should this be equal to traceId if localTraceId is not set?
151-
return Optional.ofNullable(localTraceId);
152-
}
146+
abstract Optional<String> getTopSpanId();
153147

154148
abstract Optional<String> getOriginatingSpanId();
155149

156150
/** Returns a copy of this Trace which can be independently mutated. */
157151
abstract Trace deepCopy();
158152

159153
static Trace of(boolean isObservable, String traceId) {
160-
return isObservable ? new Sampled(traceId, null) : new Unsampled(traceId, null);
161-
}
162-
163-
static Trace of(boolean isObservable, String traceId, String localTraceId) {
164-
checkArgument(!Strings.isNullOrEmpty(localTraceId), "localTraceId must be non-empty");
165-
return isObservable ? new Sampled(traceId, localTraceId) : new Unsampled(traceId, localTraceId);
154+
return isObservable ? new Sampled(traceId) : new Unsampled(traceId);
166155
}
167156

168157
private static final class Sampled extends Trace {
169158

170159
private final Deque<OpenSpan> stack;
171160

172-
private Sampled(ArrayDeque<OpenSpan> stack, String traceId, @Nullable String localTraceId) {
173-
super(traceId, localTraceId);
161+
private Sampled(ArrayDeque<OpenSpan> stack, String traceId) {
162+
super(traceId);
174163
this.stack = stack;
175164
}
176165

177-
private Sampled(String traceId, @Nullable String localTraceId) {
178-
this(new ArrayDeque<>(), traceId, localTraceId);
166+
private Sampled(String traceId) {
167+
this(new ArrayDeque<>(), traceId);
179168
}
180169

181170

@@ -216,6 +205,14 @@ boolean isObservable() {
216205
return true;
217206
}
218207

208+
@Override
209+
Optional<String> getTopSpanId() {
210+
if (stack.isEmpty()) {
211+
return Optional.empty();
212+
}
213+
return Optional.of(stack.peekLast().getSpanId());
214+
}
215+
219216
@Override
220217
Optional<String> getOriginatingSpanId() {
221218
if (stack.isEmpty()) {
@@ -226,7 +223,7 @@ Optional<String> getOriginatingSpanId() {
226223

227224
@Override
228225
Trace deepCopy() {
229-
return new Sampled(new ArrayDeque<>(stack), getTraceId(), getLocalTraceId().orElse(null));
226+
return new Sampled(new ArrayDeque<>(stack), getTraceId());
230227
}
231228

232229
@Override
@@ -242,35 +239,41 @@ private static final class Unsampled extends Trace {
242239
*/
243240
private int numberOfSpans;
244241
private Optional<String> originatingSpanId = Optional.empty();
242+
private Optional<String> topSpanId = Optional.empty();
245243

246-
private Unsampled(int numberOfSpans, String traceId, @Nullable String localTraceId) {
247-
super(traceId, localTraceId);
244+
private Unsampled(int numberOfSpans, String traceId) {
245+
super(traceId);
248246
this.numberOfSpans = numberOfSpans;
249247
validateNumberOfSpans();
250248
}
251249

252-
private Unsampled(String traceId, @Nullable String localTraceId) {
253-
this(0, traceId, localTraceId);
250+
private Unsampled(String traceId) {
251+
this(0, traceId);
254252
}
255253

256254
@Override
257255
void fastStartSpan(String _operation, String parentSpanId, SpanType _type) {
258-
startSpan(Optional.of(parentSpanId));
256+
if (numberOfSpans == 0) {
257+
originatingSpanId = Optional.of(parentSpanId);
258+
topSpanId = Optional.of(Tracers.randomId());
259+
}
260+
numberOfSpans++;
259261
}
260262

261263
@Override
262264
void fastStartSpan(String _operation, SpanType _type) {
265+
if (numberOfSpans == 0) {
266+
topSpanId = Optional.of(Tracers.randomId());
267+
}
263268
numberOfSpans++;
264269
}
265270

266271
@Override
267272
protected void push(OpenSpan span) {
268-
startSpan(span.getParentSpanId());
269-
}
270-
271-
private void startSpan(Optional<String> parentSpanId) {
272273
if (numberOfSpans == 0) {
273-
originatingSpanId = parentSpanId;
274+
// TODO: shouldn't this be span.getOriginatingSpanId?
275+
originatingSpanId = span.getParentSpanId();
276+
topSpanId = Optional.of(span.getSpanId());
274277
}
275278
numberOfSpans++;
276279
}
@@ -288,6 +291,7 @@ Optional<OpenSpan> pop() {
288291
}
289292
if (numberOfSpans == 0) {
290293
originatingSpanId = Optional.empty();
294+
topSpanId = Optional.empty();
291295
}
292296
return Optional.empty();
293297
}
@@ -303,14 +307,20 @@ boolean isObservable() {
303307
return false;
304308
}
305309

310+
@Override
311+
Optional<String> getTopSpanId() {
312+
return topSpanId;
313+
}
314+
306315
@Override
307316
Optional<String> getOriginatingSpanId() {
308317
return originatingSpanId;
309318
}
310319

311320
@Override
312321
Trace deepCopy() {
313-
return new Unsampled(numberOfSpans, getTraceId(), getLocalTraceId().orElse(null));
322+
// TODO: shouldn't this preserve originatingSpanId / topSpanId?
323+
return new Unsampled(numberOfSpans, getTraceId());
314324
}
315325

316326
/** Internal validation, this should never fail because {@link #pop()} only decrements positive values. */

tracing/src/main/java/com/palantir/tracing/Tracer.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,6 @@ private static Trace createTrace(Observability observability, String traceId) {
7878
return Trace.of(observable, traceId);
7979
}
8080

81-
/**
82-
* Creates a new localized trace, but does not set it as the current trace.
83-
*/
84-
private static Trace createTrace(Observability observability, String traceId, String localTraceId) {
85-
checkArgument(!Strings.isNullOrEmpty(traceId), "traceId must be non-empty");
86-
boolean observable = shouldObserve(observability);
87-
return Trace.of(observable, traceId, localTraceId);
88-
}
89-
9081
private static boolean shouldObserve(Observability observability) {
9182
switch (observability) {
9283
case SAMPLE:
@@ -148,13 +139,6 @@ public static void initTrace(Observability observability, String traceId) {
148139
setTrace(createTrace(observability, traceId));
149140
}
150141

151-
/**
152-
* Initializes the current thread's trace, erasing any previously accrued open spans.
153-
*/
154-
public static void initTrace(Observability observability, String traceId, String localTraceId) {
155-
setTrace(createTrace(observability, traceId, localTraceId));
156-
}
157-
158142
/**
159143
* Opens a new span for this thread's call trace, labeled with the provided operation and parent span. Only allowed
160144
* when the current trace is empty.
@@ -500,8 +484,8 @@ public static String getTraceId() {
500484
}
501485

502486
/** Returns the globally unique identifier for this thread's trace specific to this call. */
503-
public static Optional<String> getLocalTraceId() {
504-
return checkNotNull(currentTrace.get(), "There is no trace").getLocalTraceId();
487+
public static Optional<String> getTopSpanId() {
488+
return checkNotNull(currentTrace.get(), "There is no trace").getTopSpanId();
505489
}
506490

507491
/** Clears the current trace id and returns it if present. */

0 commit comments

Comments
 (0)