3030import io .opentracing .Span ;
3131import io .opentracing .propagation .Format ;
3232import io .opentracing .propagation .TextMap ;
33+ import io .opentracing .tag .Tags ;
3334import io .opentracing .util .ThreadLocalScopeManager ;
3435import org .apache .commons .lang3 .builder .ReflectionToStringBuilder ;
3536import org .apache .commons .lang3 .builder .ToStringStyle ;
@@ -43,6 +44,7 @@ public class Tracer implements io.opentracing.Tracer {
4344 protected final PropagationRegistry registry ;
4445 private final String serviceName ;
4546 private final ScopeManager scopeManager ;
47+ private final boolean dualSpanMode ;
4648
4749 private final Counter spansCreatedCounter ;
4850
@@ -60,12 +62,14 @@ public class Tracer implements io.opentracing.Tracer {
6062 private final Timer extractTimer ;
6163 private final Counter extractFailureCounter ;
6264
63- public Tracer (String serviceName , ScopeManager scopeManager , Clock clock , Dispatcher dispatcher , PropagationRegistry registry , Metrics metrics ) {
65+ public Tracer (String serviceName , ScopeManager scopeManager , Clock clock ,
66+ Dispatcher dispatcher , PropagationRegistry registry , Metrics metrics , boolean dualSpanMode ) {
6467 this .serviceName = serviceName ;
6568 this .scopeManager = scopeManager ;
6669 this .clock = clock ;
6770 this .dispatcher = dispatcher ;
6871 this .registry = registry ;
72+ this .dualSpanMode = dualSpanMode ;
6973
7074 this .dispatchTimer = Timer .builder ("dispatch" ).register (metrics );
7175 this .closeTimer = Timer .builder ("close" ).register (metrics );
@@ -250,21 +254,19 @@ public SpanBuilder withStartTimestamp(long microseconds) {
250254 return this ;
251255 }
252256
253- @ Override
254- public Scope startActive (boolean finishSpanOnClose ) {
255- return tracer .scopeManager ().activate (start (), finishSpanOnClose );
257+ boolean isServerSpan () {
258+ return Tags .SPAN_KIND_SERVER .equals (tags .get (Tags .SPAN_KIND .getKey ()));
256259 }
257260
258- protected SpanContext createNewContext () {
259- UUID randomId = UUID .randomUUID ();
260- return createContext (randomId , randomId , null , Collections .emptyMap ());
261+ SpanContext createNewContext () {
262+ return createContext (UUID .randomUUID (), UUID .randomUUID (), null , Collections .emptyMap ());
261263 }
262264
263- protected SpanContext createContext (UUID traceId , UUID spanId , UUID parentId , Map <String , String > baggage ) {
264- return new SpanContext (traceId , spanId , parentId , baggage );
265+ SpanContext createContext (UUID traceId , UUID spanId , UUID parentId , Map <String , String > baggage ) {
266+ return new SpanContext (traceId , spanId , parentId , baggage , false );
265267 }
266268
267- protected SpanContext createDependentContext () {
269+ SpanContext createDependentContext () {
268270 Reference parent = references .get (0 );
269271 for (Reference reference : references ) {
270272 if (References .CHILD_OF .equals (reference .getReferenceType ())) {
@@ -279,13 +281,25 @@ protected SpanContext createDependentContext() {
279281 baggage .putAll (reference .getContext ().getBaggage ());
280282 }
281283
284+ // This is a check to see if the tracer is configured to support single
285+ // single span type (Zipkin style shared span id) or
286+ // dual span type (client and server having their own span ids ).
287+ // a. If tracer is not of dualSpanType and if it is a server span then we
288+ // just return the parent context with the same shared span ids
289+ // b. If tracer is not of dualSpanType and if the parent context is an extracted one from the wire
290+ // then we assume this is the first span in the server and so just return the parent context
291+ // with the same shared span ids
292+ if (!tracer .dualSpanMode && (isServerSpan () || parent .getContext ().isExtractedContext ())) {
293+ return parent .getContext ();
294+ }
295+
282296 return createContext (parent .getContext ().getTraceId (),
283297 UUID .randomUUID (),
284298 parent .getContext ().getSpanId (),
285299 baggage );
286300 }
287301
288- protected SpanContext createContext () {
302+ SpanContext createContext () {
289303 // handle active spans if needed
290304 if (references .isEmpty () && !ignoreActive && tracer .activeSpan () != null ) {
291305 asChildOf (tracer .activeSpan ());
@@ -294,6 +308,7 @@ protected SpanContext createContext() {
294308 if (references .isEmpty ()) {
295309 return createNewContext ();
296310 }
311+
297312 return createDependentContext ();
298313 }
299314
@@ -304,6 +319,11 @@ private long calculateStartTime() {
304319 return startTime ;
305320 }
306321
322+ @ Override
323+ public Scope startActive (boolean finishSpanOnClose ) {
324+ return tracer .scopeManager ().activate (start (), finishSpanOnClose );
325+ }
326+
307327 @ Override
308328 @ Deprecated
309329 public com .expedia .www .haystack .client .Span startManual () {
@@ -324,6 +344,7 @@ public static class Builder {
324344 protected Dispatcher dispatcher ;
325345 protected PropagationRegistry registry = new PropagationRegistry ();
326346 protected Metrics metrics ;
347+ private boolean dualSpanMode ;
327348
328349 public Builder (MetricsRegistry registry , String serviceName , Dispatcher dispatcher ) {
329350 this (new Metrics (registry , Tracer .class .getName (), Collections .emptyList ()), serviceName , dispatcher );
@@ -341,7 +362,6 @@ public Builder(Metrics metrics, String serviceName, Dispatcher dispatcher) {
341362 TextMapPropagator httpPropagator = new TextMapPropagator .Builder ().withURLCodex ().build ();
342363 withFormat (Format .Builtin .HTTP_HEADERS , (Injector <TextMap >) httpPropagator );
343364 withFormat (Format .Builtin .HTTP_HEADERS , (Extractor <TextMap >) httpPropagator );
344-
345365 }
346366
347367 public Builder withScopeManager (ScopeManager scope ) {
@@ -375,8 +395,18 @@ public Builder clearAllFormats() {
375395 return this ;
376396 }
377397
398+ /**
399+ * Enables production of client and server spans with two different span-ids. If not enabled,
400+ * this will cause the Tracer to produce client and server spans with shared span-ids (Zipkin style)
401+ * @return this builder instance
402+ */
403+ public Builder withDualSpanMode () {
404+ dualSpanMode = true ;
405+ return this ;
406+ }
407+
378408 public Tracer build () {
379- return new Tracer (serviceName , scopeManager , clock , dispatcher , registry , metrics );
409+ return new Tracer (serviceName , scopeManager , clock , dispatcher , registry , metrics , dualSpanMode );
380410 }
381411
382412 }
0 commit comments