2929import java .util .ArrayDeque ;
3030import java .util .Deque ;
3131import java .util .Optional ;
32- import javax .annotation .Nullable ;
3332
3433/**
3534 * Represents a trace as an ordered list of non-completed spans. Supports adding and removing of spans. This class is
4544public abstract class Trace {
4645
4746 private final String traceId ;
48- @ Nullable
49- private final String localTraceId ;
5047
51- private Trace (String traceId , @ Nullable String localTraceId ) {
48+ private Trace (String traceId ) {
5249 checkArgument (!Strings .isNullOrEmpty (traceId ), "traceId must be non-empty" );
5350 this .traceId = traceId ;
54- this .localTraceId = localTraceId ;
5551 }
5652
5753 /**
@@ -143,42 +139,33 @@ final String getTraceId() {
143139 /**
144140 * The globally unique non-empty identifier for this call trace within a service (or another locality context).
145141 *
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.
142+ * While {@link #getTraceId()} is expected to be propagated across RPC calls, the top span id distinguishes
143+ * between two concurrent RPC calls made to a service with the same traceid.
148144 */
149- final Optional <String > getLocalTraceId () {
150- // XXX: should this be equal to traceId if localTraceId is not set?
151- return Optional .ofNullable (localTraceId );
152- }
145+ abstract Optional <String > getTopSpanId ();
153146
154147 abstract Optional <String > getOriginatingSpanId ();
155148
156149 /** Returns a copy of this Trace which can be independently mutated. */
157150 abstract Trace deepCopy ();
158151
159152 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 );
153+ return isObservable ? new Sampled (traceId ) : new Unsampled (traceId );
166154 }
167155
168156 private static final class Sampled extends Trace {
169157
170158 private final Deque <OpenSpan > stack ;
171159
172- private Sampled (ArrayDeque <OpenSpan > stack , String traceId , @ Nullable String localTraceId ) {
173- super (traceId , localTraceId );
160+ private Sampled (ArrayDeque <OpenSpan > stack , String traceId ) {
161+ super (traceId );
174162 this .stack = stack ;
175163 }
176164
177- private Sampled (String traceId , @ Nullable String localTraceId ) {
178- this (new ArrayDeque <>(), traceId , localTraceId );
165+ private Sampled (String traceId ) {
166+ this (new ArrayDeque <>(), traceId );
179167 }
180168
181-
182169 @ Override
183170 @ SuppressWarnings ("ResultOfMethodCallIgnored" ) // Sampled traces cannot optimize this path
184171 void fastStartSpan (String operation , String parentSpanId , SpanType type ) {
@@ -216,6 +203,14 @@ boolean isObservable() {
216203 return true ;
217204 }
218205
206+ @ Override
207+ Optional <String > getTopSpanId () {
208+ if (stack .isEmpty ()) {
209+ return Optional .empty ();
210+ }
211+ return Optional .of (stack .peekLast ().getSpanId ());
212+ }
213+
219214 @ Override
220215 Optional <String > getOriginatingSpanId () {
221216 if (stack .isEmpty ()) {
@@ -226,7 +221,7 @@ Optional<String> getOriginatingSpanId() {
226221
227222 @ Override
228223 Trace deepCopy () {
229- return new Sampled (new ArrayDeque <>(stack ), getTraceId (), getLocalTraceId (). orElse ( null ) );
224+ return new Sampled (new ArrayDeque <>(stack ), getTraceId ());
230225 }
231226
232227 @ Override
@@ -242,35 +237,41 @@ private static final class Unsampled extends Trace {
242237 */
243238 private int numberOfSpans ;
244239 private Optional <String > originatingSpanId = Optional .empty ();
240+ private Optional <String > topSpanId = Optional .empty ();
245241
246- private Unsampled (int numberOfSpans , String traceId , @ Nullable String localTraceId ) {
247- super (traceId , localTraceId );
242+ private Unsampled (int numberOfSpans , String traceId ) {
243+ super (traceId );
248244 this .numberOfSpans = numberOfSpans ;
249245 validateNumberOfSpans ();
250246 }
251247
252- private Unsampled (String traceId , @ Nullable String localTraceId ) {
253- this (0 , traceId , localTraceId );
248+ private Unsampled (String traceId ) {
249+ this (0 , traceId );
254250 }
255251
256252 @ Override
257253 void fastStartSpan (String _operation , String parentSpanId , SpanType _type ) {
258- startSpan (Optional .of (parentSpanId ));
254+ if (numberOfSpans == 0 ) {
255+ originatingSpanId = Optional .of (parentSpanId );
256+ topSpanId = Optional .of (Tracers .randomId ());
257+ }
258+ numberOfSpans ++;
259259 }
260260
261261 @ Override
262262 void fastStartSpan (String _operation , SpanType _type ) {
263+ if (numberOfSpans == 0 ) {
264+ topSpanId = Optional .of (Tracers .randomId ());
265+ }
263266 numberOfSpans ++;
264267 }
265268
266269 @ Override
267270 protected void push (OpenSpan span ) {
268- startSpan (span .getParentSpanId ());
269- }
270-
271- private void startSpan (Optional <String > parentSpanId ) {
272271 if (numberOfSpans == 0 ) {
273- originatingSpanId = parentSpanId ;
272+ // TODO: shouldn't this be span.getOriginatingSpanId?
273+ originatingSpanId = span .getParentSpanId ();
274+ topSpanId = Optional .of (span .getSpanId ());
274275 }
275276 numberOfSpans ++;
276277 }
@@ -288,6 +289,7 @@ Optional<OpenSpan> pop() {
288289 }
289290 if (numberOfSpans == 0 ) {
290291 originatingSpanId = Optional .empty ();
292+ topSpanId = Optional .empty ();
291293 }
292294 return Optional .empty ();
293295 }
@@ -303,14 +305,20 @@ boolean isObservable() {
303305 return false ;
304306 }
305307
308+ @ Override
309+ Optional <String > getTopSpanId () {
310+ return topSpanId ;
311+ }
312+
306313 @ Override
307314 Optional <String > getOriginatingSpanId () {
308315 return originatingSpanId ;
309316 }
310317
311318 @ Override
312319 Trace deepCopy () {
313- return new Unsampled (numberOfSpans , getTraceId (), getLocalTraceId ().orElse (null ));
320+ // TODO: shouldn't this preserve originatingSpanId / topSpanId?
321+ return new Unsampled (numberOfSpans , getTraceId ());
314322 }
315323
316324 /** Internal validation, this should never fail because {@link #pop()} only decrements positive values. */
0 commit comments