diff --git a/dd-trace-api/src/main/java/datadog/trace/api/DD128bTraceId.java b/dd-trace-api/src/main/java/datadog/trace/api/DD128bTraceId.java
index a3046e98e9d..63852429871 100644
--- a/dd-trace-api/src/main/java/datadog/trace/api/DD128bTraceId.java
+++ b/dd-trace-api/src/main/java/datadog/trace/api/DD128bTraceId.java
@@ -14,7 +14,7 @@
* #highOrderBits} is set to 0 and {@link #lowOrderBits} contains a unique and random
* 63-bit id.
*/
-public class DD128bTraceId implements DDTraceId {
+public class DD128bTraceId extends DDTraceId {
public static final DD128bTraceId ZERO =
new DD128bTraceId(0, 0, "00000000000000000000000000000000");
/** Represents the high-order 64 bits of the 128-bit trace id. */
diff --git a/dd-trace-api/src/main/java/datadog/trace/api/DD64bTraceId.java b/dd-trace-api/src/main/java/datadog/trace/api/DD64bTraceId.java
index e3a4e7cf258..f40b47a89d4 100644
--- a/dd-trace-api/src/main/java/datadog/trace/api/DD64bTraceId.java
+++ b/dd-trace-api/src/main/java/datadog/trace/api/DD64bTraceId.java
@@ -9,9 +9,7 @@
* representations. The decimal string representation is either kept from parsing, or generated on
* demand and cached.
*/
-public class DD64bTraceId implements DDTraceId {
-
- public static final DD64bTraceId ZERO = new DD64bTraceId(0, "0");
+public class DD64bTraceId extends DDTraceId {
public static final DD64bTraceId MAX =
new DD64bTraceId(-1, "18446744073709551615"); // All bits set
@@ -61,9 +59,15 @@ public static DD64bTraceId fromHex(String s) throws NumberFormatException {
}
static DD64bTraceId create(long id, String str) {
- if (id == 0) return ZERO;
- if (id == -1) return MAX;
- return new DD64bTraceId(id, str);
+ // ZERO constant is created and stored by the parent class as part of its API contract
+ // But initialized by this 64-bit child class. Ensures uniqueness of ZERO once created.
+ if (id == 0 && ZERO != null) {
+ return (DD64bTraceId) ZERO;
+ } else if (id == -1) {
+ return MAX;
+ } else {
+ return new DD64bTraceId(id, str);
+ }
}
@Override
diff --git a/dd-trace-api/src/main/java/datadog/trace/api/DDTraceId.java b/dd-trace-api/src/main/java/datadog/trace/api/DDTraceId.java
index 5eee55a98ec..cc10e7493ee 100644
--- a/dd-trace-api/src/main/java/datadog/trace/api/DDTraceId.java
+++ b/dd-trace-api/src/main/java/datadog/trace/api/DDTraceId.java
@@ -8,11 +8,11 @@
*
It contains parsing and formatting to string for both decimal and hexadecimal representations.
* The string representations are either kept from parsing, or generated on demand and cached.
*/
-public interface DDTraceId {
+public abstract class DDTraceId {
/** Invalid TraceId value used to denote no TraceId. */
- DDTraceId ZERO = from(0);
+ public static final DDTraceId ZERO = from(0);
/** Convenience constant used from tests */
- DDTraceId ONE = from(1);
+ public static final DDTraceId ONE = from(1);
/**
* Creates a new {@link DD64bTraceId 64-bit TraceId} from the given {@code long} interpreted as
@@ -22,7 +22,7 @@ public interface DDTraceId {
* @param id The {@code long} representing the bits of the unsigned 64-bit id.
* @return A new {@link DDTraceId} instance.
*/
- static DDTraceId from(long id) {
+ public static DDTraceId from(long id) {
return DD64bTraceId.from(id);
}
@@ -34,7 +34,7 @@ static DDTraceId from(long id) {
* @return A new {@link DDTraceId} instance.
* @throws NumberFormatException If the given {@link String} does not represent a valid number.
*/
- static DDTraceId from(String s) throws NumberFormatException {
+ public static DDTraceId from(String s) throws NumberFormatException {
return DD64bTraceId.create(LongStringUtils.parseUnsignedLong(s), s);
}
@@ -47,7 +47,7 @@ static DDTraceId from(String s) throws NumberFormatException {
* @throws NumberFormatException If the given {@link #toHexString() hexadecimal String} does not
* represent a valid number.
*/
- static DDTraceId fromHex(String s) throws NumberFormatException {
+ public static DDTraceId fromHex(String s) throws NumberFormatException {
if (s == null) {
throw new NumberFormatException("s cannot be null");
}
@@ -62,7 +62,7 @@ static DDTraceId fromHex(String s) throws NumberFormatException {
* instance.
*/
@Override
- String toString();
+ public abstract String toString();
/**
* Returns the lower-case zero-padded 32 hexadecimal characters {@link String} representation of
@@ -71,7 +71,7 @@ static DDTraceId fromHex(String s) throws NumberFormatException {
* @return A cached lower-case zero-padded 32 hexadecimal characters {@link String} representation
* of the {@link DDTraceId} instance.
*/
- String toHexString();
+ public abstract String toHexString();
/**
* Returns the lower-case zero-padded {@link #toHexString() hexadecimal String} representation of
@@ -83,7 +83,7 @@ static DDTraceId fromHex(String s) throws NumberFormatException {
* @return A lower-case zero-padded {@link #toHexString() String representation} representation of
* the {@link DDTraceId} instance.
*/
- String toHexStringPadded(int size);
+ public abstract String toHexStringPadded(int size);
/**
* Returns the low-order 64 bits of the {@link DDTraceId} as an unsigned {@code long}. This means
@@ -91,7 +91,7 @@ static DDTraceId fromHex(String s) throws NumberFormatException {
*
* @return The low-order 64 bits of the {@link DDTraceId} as an unsigned {@code long}.
*/
- long toLong();
+ public abstract long toLong();
/**
* Returns the high-order 64 bits of 128-bit {@link DDTraceId} as un unsigned {@code long}. This
@@ -100,5 +100,5 @@ static DDTraceId fromHex(String s) throws NumberFormatException {
* @return The high-order 64 bits of the 128-bit {@link DDTraceId} as an unsigned {@code long},
* 0 for 64-bit {@link DDTraceId} only.
*/
- long toHighOrderLong();
+ public abstract long toHighOrderLong();
}
diff --git a/dd-trace-api/src/test/groovy/datadog/trace/api/DDTraceIdTest.groovy b/dd-trace-api/src/test/groovy/datadog/trace/api/DDTraceIdTest.groovy
index b236ce84bab..f8d1d70ae17 100644
--- a/dd-trace-api/src/test/groovy/datadog/trace/api/DDTraceIdTest.groovy
+++ b/dd-trace-api/src/test/groovy/datadog/trace/api/DDTraceIdTest.groovy
@@ -189,4 +189,14 @@ class DDTraceIdTest extends DDSpecification {
// Too long id
"1" * 33 | 0 | 33 | true
}
+
+ def "check ZERO constant initialization"() {
+ when:
+ def zero = DDTraceId.ZERO
+ def fromZero = DDTraceId.from(0)
+
+ then:
+ zero != null
+ zero.is(fromZero)
+ }
}
diff --git a/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java b/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java
index 875e6220605..a9376cd6597 100644
--- a/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java
+++ b/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3TraceId.java
@@ -4,7 +4,7 @@
import datadog.trace.api.DDTraceId;
/** A B3 {@link DDTraceId} along with its original {@link String} representation. */
-public class B3TraceId implements DDTraceId {
+public class B3TraceId extends DDTraceId {
/** The original {@link String} representation. */
protected final String original;