Skip to content

Commit

Permalink
Merge pull request #13 from appoptics/NH-2314-w3c-trace-context
Browse files Browse the repository at this point in the history
NH-2314: W3C trace context propagation
  • Loading branch information
jiwen624 authored Nov 3, 2021
2 parents a0bc909 + 1c51546 commit 2e44b5b
Show file tree
Hide file tree
Showing 25 changed files with 370 additions and 317 deletions.
4 changes: 2 additions & 2 deletions agent/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ dependencies {
customShadow project(path: ":instrumentation", configuration: "shadow")
implementation project(path: ":core-bootstrap")
implementation "io.opentelemetry.javaagent:opentelemetry-javaagent:${versions.opentelemetryJavaagent}:all"
implementation "com.appoptics.agent.java:core:${versions.appoptics}"
implementation "com.appoptics.agent.java:metrics:${versions.appoptics}"
implementation "com.appoptics.agent.java:core:${versions.appopticsCore}"
implementation "com.appoptics.agent.java:metrics:${versions.appopticsMetrics}"
}

CopySpec isolateSpec() {
Expand Down
18 changes: 4 additions & 14 deletions appoptics-opentelemetry-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,13 @@ group = "com.appoptics.agent.java"
dependencies {
compileOnly("io.opentelemetry:opentelemetry-sdk:${versions.opentelemetry}")
compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-bootstrap:${versions.opentelemetryJavaagentAlpha}")
compileOnly "com.appoptics.agent.java:core:${versions.appoptics}"
compileOnly "com.appoptics.agent.java:metrics:${versions.appoptics}"
compileOnly "com.appoptics.agent.java:core:${versions.appopticsCore}"
compileOnly "com.appoptics.agent.java:metrics:${versions.appopticsMetrics}"
compileOnly project(":custom")
compileOnly project(":core-bootstrap")
testImplementation "junit:junit:4.10"
testImplementation "com.appoptics.agent.java:core:${versions.appoptics}"
testImplementation "com.appoptics.agent.java:metrics:${versions.appoptics}"



// implementation "io.opentelemetry.javaagent:opentelemetry-javaagent-api:1.1.0-alpha"
// implementation "io.opentelemetry.javaagent:opentelemetry-javaagent-tooling:1.1.0-alpha"
// implementation "io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:1.1.0-alpha"
// implementation "com.google.guava:guava:30.1-jre" //why

// compileOnly "com.appoptics.agent.java:appoptics-opentelemetry-sdk:6.23.0"
// implementation "com.appoptics.agent.java:appoptics-opentelemetry-java-extensions:6.23.0"
testImplementation "com.appoptics.agent.java:core:${versions.appopticsCore}"
testImplementation "com.appoptics.agent.java:metrics:${versions.appopticsMetrics}"
}


Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public void logException(Throwable error) {
* {@inheritDoc}
*/
public String getCurrentXTraceID() {
return Util.buildXTraceId(Span.current().getSpanContext());
return Util.W3CContextToHexString(Span.current().getSpanContext());
}

@Override
Expand Down
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ subprojects {
// opentelemetryJavaagent: "1.1.0",
bytebuddy : "1.10.18",
guava : "30.1-jre",
appoptics : "6.24.1"
appopticsCore : "7.0.0",
appopticsMetrics : "7.0.0"
]
versions.opentelemetryAlpha = "${versions.opentelemetry}-alpha"
versions.opentelemetryJavaagentAlpha = "${versions.opentelemetryJavaagent}-alpha"
Expand Down
4 changes: 2 additions & 2 deletions core-bootstrap/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies {
compileOnly("org.checkerframework:checker-qual:3.13.0")
compileOnly "org.slf4j:slf4j-api:1.6.2"

compileOnly "com.appoptics.agent.java:core:${versions.appoptics}"
compileOnly "com.appoptics.agent.java:metrics:${versions.appoptics}"
compileOnly "com.appoptics.agent.java:core:${versions.appopticsCore}"
compileOnly "com.appoptics.agent.java:metrics:${versions.appopticsMetrics}"
}

Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.appoptics.opentelemetry.core;

public interface Constants {
String AO_INTERNAL_ATTRIBUTE_PREFIX = "ao.internal.";
String AO_DETAILED_TRACING = AO_INTERNAL_ATTRIBUTE_PREFIX + "detailedTracing";
String AO_METRICS = AO_INTERNAL_ATTRIBUTE_PREFIX + "metrics";
String AO_SAMPLER = AO_INTERNAL_ATTRIBUTE_PREFIX + "sampler";
String AO_KEY_PREFIX = "ao.";
String SW_KEY_PREFIX = "sw.";
String OT_KEY_PREFIX = "ot.";
String SW_INTERNAL_ATTRIBUTE_PREFIX = SW_KEY_PREFIX + "internal.";
String SW_DETAILED_TRACING = SW_INTERNAL_ATTRIBUTE_PREFIX + "detailedTracing";
String SW_METRICS = SW_INTERNAL_ATTRIBUTE_PREFIX + "metrics";
String SW_SAMPLER = SW_INTERNAL_ATTRIBUTE_PREFIX + "sampler";
String W3C_KEY_PREFIX = "w3c.";
String SW_UPSTREAM_TRACESTATE = SW_KEY_PREFIX + W3C_KEY_PREFIX + "tracestate";
String SW_PARENT_ID = SW_KEY_PREFIX + "parent_id";
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package com.appoptics.opentelemetry.core;

import com.tracelytics.ext.google.common.base.Strings;
import com.tracelytics.joboe.Metadata;
import com.tracelytics.joboe.OboeException;
import com.tracelytics.joboe.Constants;
import io.opentelemetry.api.trace.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -17,29 +15,22 @@
import static com.appoptics.opentelemetry.core.Constants.*;

public class Util {
private static Logger logger = LoggerFactory.getLogger(Util.class.getName());
private static String APPOPTICS_TRACE_STATE_KEY = "appoptics";
private static byte EXIT_OP_ID_MASK = 0xf;
private static final Logger logger = LoggerFactory.getLogger(Util.class.getName());
private static final byte EXIT_OP_ID_MASK = 0xf;

/**
* Build an AO x-trace ID from OT span context. Take note that we will have to check the value of `appoptics` in
* `tracestate` first as AO x-trace ID has longer task ID than its OT counterpart traceid. More details in
* https://github.com/librato/joboe/issues/1079
/** Converts an OpenTelemetry span context to a hex string.
*
* @param context
* @return
*/
public static String buildXTraceId(SpanContext context) {
String aoId = context.getTraceState().get(APPOPTICS_TRACE_STATE_KEY);

String traceId = context.getTraceId();
if (aoId != null) {
try {
traceId = new Metadata(aoId).taskHexString();
} catch (OboeException e) {
logger.warn("Failed to convert appoptics trace state [" + aoId + "] to OT trace id", e);
}
}
return buildXTraceId(traceId, context.getSpanId(), context.isSampled());
public static String W3CContextToHexString(SpanContext context) {
return Metadata.CURRENT_VERSION_HEXSTRING
+ Metadata.HEXSTRING_DELIMETER
+ context.getTraceId()
+ Metadata.HEXSTRING_DELIMETER
+ context.getSpanId()
+ Metadata.HEXSTRING_DELIMETER
+ context.getTraceFlags().asHex();
}

/**
Expand All @@ -59,25 +50,6 @@ public static Metadata buildSpanExitMetadata(SpanContext context) {
return exitContext;
}

/**
* Builds an AO x-trace ID with OT trace id and span id
*
* @param traceId
* @param spanId
* @param isSampled
* @return
*/
public static String buildXTraceId(String traceId, String spanId, boolean isSampled) {
final String HEADER = "2B";
String hexString = HEADER +
Strings.padEnd(traceId, Constants.MAX_TASK_ID_LEN * 2, '0') +
Strings.padEnd(spanId, Constants.MAX_OP_ID_LEN * 2, '0');
hexString += isSampled ? "01" : "00";


return hexString.toUpperCase();
}

/**
* Builds an AO metadata with OT span context
*
Expand All @@ -86,15 +58,12 @@ public static String buildXTraceId(String traceId, String spanId, boolean isSamp
*/
public static Metadata buildMetadata(SpanContext context) {
try {
Metadata metadata = new Metadata(buildXTraceId(context));
metadata.setTraceId(toTraceId(context.getTraceIdBytes()));
return metadata;
return new Metadata(W3CContextToHexString(context));
} catch (OboeException e) {
return null;
}
}


/**
* Generate a deterministic AO trace id from the OT trace id bytes
* @param traceIdBytes
Expand All @@ -116,34 +85,18 @@ public static Long toTraceId(byte[] traceIdBytes) {
* @return
*/
public static SpanContext toSpanContext(String xTrace, boolean isRemote) {
W3TraceContextHolder w3TraceContext = toW3TraceContext(xTrace);
return isRemote
? SpanContext.createFromRemoteParent(w3TraceContext.traceId, w3TraceContext.spanId, w3TraceContext.traceFlags, TraceState.getDefault())
: SpanContext.create(w3TraceContext.traceId, w3TraceContext.spanId, w3TraceContext.traceFlags, TraceState.getDefault());
}

/**
* Builds a w3c formatted trace context with AO x-trace ID
* @param xTrace
* @return
*/
public static W3TraceContextHolder toW3TraceContext(String xTrace) {
Metadata metadata;
Metadata metadata = null;
try {
metadata = new Metadata(xTrace);
} catch (OboeException e) {
e.printStackTrace();
return null;
return SpanContext.getInvalid();
}

String w3TraceId = TraceId.fromBytes(metadata.getTaskID());
String w3SpanId = SpanId.fromBytes(metadata.getOpID());
TraceFlags w3TraceFlags = metadata.isSampled() ? TraceFlags.getSampled() : TraceFlags.getDefault();

return new W3TraceContextHolder(w3TraceId, w3SpanId, w3TraceFlags);
return isRemote
? SpanContext.createFromRemoteParent(metadata.taskHexString(), metadata.opHexString(), TraceFlags.fromByte(metadata.getFlags()), TraceState.getDefault())
: SpanContext.create(metadata.taskHexString(), metadata.opHexString(), TraceFlags.fromByte(metadata.getFlags()), TraceState.getDefault());
}


public static String parsePath(String url) {
if (url != null) {
try {
Expand All @@ -155,19 +108,6 @@ public static String parsePath(String url) {
return null;
}


public static class W3TraceContextHolder {
public final String traceId;
public final String spanId;
public final TraceFlags traceFlags;

W3TraceContextHolder(String traceId, String spanId, TraceFlags traceFlags) {
this.traceId = traceId;
this.spanId = spanId;
this.traceFlags = traceFlags;
}
}

public static Map<String, Object> keyValuePairsToMap(Object... keyValuePairs) {
Map<String, Object> map = new HashMap<String, Object>();
if (keyValuePairs.length % 2 == 1) {
Expand Down Expand Up @@ -198,8 +138,8 @@ public static void setSpanAttributes(Span span, Map<String, ?> attributes) {
for (Map.Entry<String, ?> entry : attributes.entrySet()) {
Object value = entry.getValue();
String key = entry.getKey();
if (!key.startsWith(AO_KEY_PREFIX)) {
key = AO_KEY_PREFIX + key;
if (!key.startsWith(SW_KEY_PREFIX)) {
key = SW_KEY_PREFIX + key;
}
if (value instanceof String) {
span.setAttribute(key, (String) value);
Expand Down Expand Up @@ -229,8 +169,8 @@ public static void setSpanAttributes(SpanBuilder spanBuilder, Map<String, ?> att
for (Map.Entry<String, ?> entry : attributes.entrySet()) {
Object value = entry.getValue();
String key = entry.getKey();
if (!key.startsWith(AO_KEY_PREFIX)) {
key = AO_KEY_PREFIX + key;
if (!key.startsWith(SW_KEY_PREFIX)) {
key = SW_KEY_PREFIX + key;
}

if (value instanceof String) {
Expand Down
4 changes: 2 additions & 2 deletions custom/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ dependencies {
implementation project(path: ":core-bootstrap")

implementation "org.slf4j:slf4j-api:1.6.2"
compileOnly "com.appoptics.agent.java:core:${versions.appoptics}"
compileOnly "com.appoptics.agent.java:metrics:${versions.appoptics}"
compileOnly "com.appoptics.agent.java:core:${versions.appopticsCore}"
compileOnly "com.appoptics.agent.java:metrics:${versions.appopticsMetrics}"

compileOnly "com.google.auto.service:auto-service-annotations:1.0-rc6"
annotationProcessor "com.google.auto.service:auto-service:1.0-rc6"
Expand Down
Loading

0 comments on commit 2e44b5b

Please sign in to comment.