4545public 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. */
0 commit comments