@@ -138,6 +138,7 @@ public class Span implements SpanContext {
138138 private final long begin ;
139139 private long end = 0 ;
140140 private final String name ;
141+ private final long traceIdHigh ;
141142 private final long traceId ;
142143 private List <Long > parents = new ArrayList <>();
143144 private final long spanId ;
@@ -169,6 +170,7 @@ public Span(Span current, Span savedSpan) {
169170 this .begin = current .getBegin ();
170171 this .end = current .getEnd ();
171172 this .name = current .getName ();
173+ this .traceIdHigh = current .getTraceIdHigh ();
172174 this .traceId = current .getTraceId ();
173175 this .parents = current .getParents ();
174176 this .spanId = current .getSpanId ();
@@ -183,37 +185,63 @@ public Span(Span current, Span savedSpan) {
183185 this .savedSpan = savedSpan ;
184186 }
185187
188+ /**
189+ * @deprecated please use {@link SpanBuilder}
190+ */
191+ @ Deprecated
186192 public Span (long begin , long end , String name , long traceId , List <Long > parents ,
187193 long spanId , boolean remote , boolean exportable , String processId ) {
188194 this (begin , end , name , traceId , parents , spanId , remote , exportable , processId ,
189195 null );
190196 }
191197
198+ /**
199+ * @deprecated please use {@link SpanBuilder}
200+ */
201+ @ Deprecated
192202 public Span (long begin , long end , String name , long traceId , List <Long > parents ,
193203 long spanId , boolean remote , boolean exportable , String processId ,
194204 Span savedSpan ) {
195- if (begin > 0 ) { // conventionally, 0 indicates unset
205+ this (new SpanBuilder ()
206+ .begin (begin )
207+ .end (end )
208+ .name (name )
209+ .traceId (traceId )
210+ .parents (parents )
211+ .spanId (spanId )
212+ .remote (remote )
213+ .exportable (exportable )
214+ .processId (processId )
215+ .savedSpan (savedSpan ));
216+ }
217+
218+ Span (SpanBuilder builder ) {
219+ if (builder .begin > 0 ) { // conventionally, 0 indicates unset
196220 this .startNanos = null ; // don't know the start tick
197- this .begin = begin ;
221+ this .begin = builder . begin ;
198222 } else {
199223 this .startNanos = nanoTime ();
200224 this .begin = System .currentTimeMillis ();
201225 }
202- if (end > 0 ) {
203- this .end = end ;
204- this .durationMicros = (end - begin ) * 1000 ;
226+ if (builder . end > 0 ) {
227+ this .end = builder . end ;
228+ this .durationMicros = (this . end - this . begin ) * 1000 ;
205229 }
206- this .name = name != null ? name : "" ;
207- this .traceId = traceId ;
208- this .parents = parents ;
209- this .spanId = spanId ;
210- this .remote = remote ;
211- this .exportable = exportable ;
212- this .processId = processId ;
213- this .savedSpan = savedSpan ;
230+ this .name = builder .name != null ? builder .name : "" ;
231+ this .traceIdHigh = builder .traceIdHigh ;
232+ this .traceId = builder .traceId ;
233+ this .parents .addAll (builder .parents );
234+ this .spanId = builder .spanId ;
235+ this .remote = builder .remote ;
236+ this .exportable = builder .exportable ;
237+ this .processId = builder .processId ;
238+ this .savedSpan = builder .savedSpan ;
214239 this .tags = new ConcurrentHashMap <>();
240+ this .tags .putAll (builder .tags );
215241 this .logs = new ConcurrentLinkedQueue <>();
242+ this .logs .addAll (builder .logs );
216243 this .baggage = new ConcurrentHashMap <>();
244+ this .baggage .putAll (builder .baggage );
217245 }
218246
219247 public static SpanBuilder builder () {
@@ -397,7 +425,30 @@ public long getSpanId() {
397425 }
398426
399427 /**
400- * A pseudo-unique (random) number assigned to the trace associated with this span
428+ * When non-zero, the trace containing this span uses 128-bit trace identifiers.
429+ *
430+ * <p>{@code traceIdHigh} corresponds to the high bits in big-endian format and
431+ * {@link #getTraceId()} corresponds to the low bits.
432+ *
433+ * <p>Ex. to convert the two fields to a 128bit opaque id array, you'd use code like below.
434+ * <pre>{@code
435+ * ByteBuffer traceId128 = ByteBuffer.allocate(16);
436+ * traceId128.putLong(span.getTraceIdHigh());
437+ * traceId128.putLong(span.getTraceId());
438+ * traceBytes = traceId128.array();
439+ * }</pre>
440+ *
441+ * @see #traceIdString()
442+ * @since 1.2.0
443+ */
444+ public long getTraceIdHigh () {
445+ return this .traceIdHigh ;
446+ }
447+
448+ /**
449+ * Unique 8-byte identifier for a trace, set on all spans within it.
450+ *
451+ * @see #getTraceIdHigh() for notes about 128-bit trace identifiers
401452 */
402453 public long getTraceId () {
403454 return this .traceId ;
@@ -452,8 +503,27 @@ public boolean isExportable() {
452503 return this .exportable ;
453504 }
454505
506+ /**
507+ * Returns the 16 or 32 character hex representation of the span's trace ID
508+ *
509+ * @since 1.2.0
510+ */
511+ public String traceIdString () {
512+ if (this .traceIdHigh != 0 ) {
513+ char [] result = new char [32 ];
514+ writeHexLong (result , 0 , this .traceIdHigh );
515+ writeHexLong (result , 16 , this .traceId );
516+ return new String (result );
517+ }
518+ char [] result = new char [16 ];
519+ writeHexLong (result , 0 , this .traceId );
520+ return new String (result );
521+ }
522+
455523 /**
456524 * Represents given long id as 16-character lower-hex string
525+ *
526+ * @see #traceIdString()
457527 */
458528 public static String idToHex (long id ) {
459529 char [] data = new char [16 ];
@@ -488,29 +558,40 @@ static void writeHexByte(char[] data, int pos, byte b) {
488558 public static long hexToId (String hexString ) {
489559 Assert .hasText (hexString , "Can't convert empty hex string to long" );
490560 int length = hexString .length ();
491- if (length < 1 || length > 32 ) throw new IllegalArgumentException ("Malformed id" );
561+ if (length < 1 || length > 32 ) throw new IllegalArgumentException ("Malformed id: " + hexString );
492562
493563 // trim off any high bits
494- int i = length > 16 ? length - 16 : 0 ;
564+ int beginIndex = length > 16 ? length - 16 : 0 ;
565+
566+ return hexToId (hexString , beginIndex );
567+ }
495568
569+ /**
570+ * Parses a 16 character lower-hex string with no prefix into an unsigned long, starting at the
571+ * specified index.
572+ *
573+ * @since 1.2.0
574+ */
575+ public static long hexToId (String lowerHex , int index ) {
576+ Assert .hasText (lowerHex , "Can't convert empty hex string to long" );
496577 long result = 0 ;
497- for (; i < length ; i ++) {
498- char c = hexString .charAt (i );
578+ for (int endIndex = Math . min ( index + 16 , lowerHex . length ()); index < endIndex ; index ++) {
579+ char c = lowerHex .charAt (index );
499580 result <<= 4 ;
500581 if (c >= '0' && c <= '9' ) {
501582 result |= c - '0' ;
502583 } else if (c >= 'a' && c <= 'f' ) {
503584 result |= c - 'a' + 10 ;
504585 } else {
505- throw new IllegalArgumentException ("Malformed id" );
586+ throw new IllegalArgumentException ("Malformed id: " + lowerHex );
506587 }
507588 }
508589 return result ;
509590 }
510591
511592 @ Override
512593 public String toString () {
513- return "[Trace: " + idToHex ( this . traceId ) + ", Span: " + idToHex (this .spanId )
594+ return "[Trace: " + traceIdString ( ) + ", Span: " + idToHex (this .spanId )
514595 + ", Parent: " + getParentIdIfPresent () + ", exportable:" + this .exportable + "]" ;
515596 }
516597
@@ -520,31 +601,36 @@ private String getParentIdIfPresent() {
520601
521602 @ Override
522603 public int hashCode () {
523- final int prime = 31 ;
524- int result = 1 ;
525- result = prime * result + (int ) (this .spanId ^ (this .spanId >>> 32 ));
526- result = prime * result + (int ) (this .traceId ^ (this .traceId >>> 32 ));
527- return result ;
604+ int h = 1 ;
605+ h *= 1000003 ;
606+ h ^= (this .traceIdHigh >>> 32 ) ^ this .traceIdHigh ;
607+ h *= 1000003 ;
608+ h ^= (this .traceId >>> 32 ) ^ this .traceId ;
609+ h *= 1000003 ;
610+ h ^= (this .spanId >>> 32 ) ^ this .spanId ;
611+ h *= 1000003 ;
612+ return h ;
528613 }
529614
530615 @ Override
531- public boolean equals (Object obj ) {
532- if (this == obj )
616+ public boolean equals (Object o ) {
617+ if (o == this ) {
533618 return true ;
534- if ( obj == null )
535- return false ;
536- if ( getClass () != obj . getClass ())
537- return false ;
538- Span other = ( Span ) obj ;
539- if (this .spanId != other .spanId )
540- return false ;
541- return this . traceId == other . traceId ;
619+ }
620+ if ( o instanceof Span ) {
621+ Span that = ( Span ) o ;
622+ return ( this . traceIdHigh == that . traceIdHigh )
623+ && ( this . traceId == that . traceId )
624+ && (this .spanId == that .spanId );
625+ }
626+ return false ;
542627 }
543628
544629 public static class SpanBuilder {
545630 private long begin ;
546631 private long end ;
547632 private String name ;
633+ private long traceIdHigh ;
548634 private long traceId ;
549635 private ArrayList <Long > parents = new ArrayList <>();
550636 private long spanId ;
@@ -581,6 +667,11 @@ public Span.SpanBuilder name(String name) {
581667 return this ;
582668 }
583669
670+ public Span .SpanBuilder traceIdHigh (long traceIdHigh ) {
671+ this .traceIdHigh = traceIdHigh ;
672+ return this ;
673+ }
674+
584675 public Span .SpanBuilder traceId (long traceId ) {
585676 this .traceId = traceId ;
586677 return this ;
@@ -652,23 +743,12 @@ public Span.SpanBuilder savedSpan(Span savedSpan) {
652743 }
653744
654745 public Span build () {
655- Span span = new Span (this .begin , this .end , this .name , this .traceId ,
656- this .parents , this .spanId , this .remote , this .exportable ,
657- this .processId , this .savedSpan );
658- span .logs .addAll (this .logs );
659- span .tags .putAll (this .tags );
660- span .baggage .putAll (this .baggage );
661- return span ;
746+ return new Span (this );
662747 }
663748
664749 @ Override
665750 public String toString () {
666- return "SpanBuilder{" + "begin=" + this .begin + ", end=" + this .end
667- + ", name=" + this .name + ", traceId=" + this .traceId + ", parents="
668- + this .parents + ", spanId=" + this .spanId + ", remote=" + this .remote
669- + ", exportable=" + this .exportable + ", processId='" + this .processId
670- + '\'' + ", savedSpan=" + this .savedSpan + ", logs=" + this .logs
671- + ", tags=" + this .tags + '}' ;
751+ return new Span (this ).toString ();
672752 }
673753 }
674754}
0 commit comments