Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ link traces with the profiling data, and find specific lines of code related to
* Because of how sampling profilers work, spans shorter than the sample interval may not be captured. By default pyroscope CPU profiler probes stack traces 100 times per second, meaning that spans shorter than 10ms may not be captured.


Java code can be easily instrumented with otel-profiling-java package -
a `OpenTelemetry` implementation, that annotates profiling data with span IDs which makes it possible to filter
out profile of a particular trace span in Pyroscope.
Java code can be easily instrumented with the otel-profiling-java package, an `OpenTelemetry` implementation that annotates profiling data with `trace_id` and `span_id` labels, which makes it possible to filter the profile of a particular trace (or trace span) in Pyroscope.

Visit [docs](https://grafana.com/docs/pyroscope/latest/configure-client/trace-span-profiles/java-span-profiles/) page for usage and configuration documentation.

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pyroscope_version=2.5.1
pyroscope_version=2.6.0
# x-release-please-start-version
otel_profiling_version=2.0.6
# x-release-please-end
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ public void onStart(Context parentContext, ReadWriteSpan span) {

span.setAttribute(ATTRIBUTE_KEY_PROFILE_ID, strProfileId);
asprof.setTracingContext(spanId, spanName);
// W3C trace ID is 32 hex chars (128 bits). Parse directly into two longs
// to avoid the String#substring allocations on this hot path.
String traceId = span.getSpanContext().getTraceId();
try {
asprof.setTraceId(parseHex64(traceId, 0), parseHex64(traceId, 16));
} catch (NumberFormatException | IndexOutOfBoundsException e) {
asprof.setTraceId(0, 0);
}
}

@Override
Expand All @@ -71,6 +79,7 @@ public void onEnd(ReadableSpan span) {
return;
}
asprof.setTracingContext(0, 0);
asprof.setTraceId(0L, 0L);
}

public static long parseSpanId(String strProfileId) {
Expand All @@ -84,6 +93,25 @@ public static long parseSpanId(String strProfileId) {
}
}

static long parseHex64(String s, int offset) {
long result = 0L;
for (int i = 0; i < 16; i++) {
int c = s.charAt(offset + i);
int nibble;
if (c >= '0' && c <= '9') {
nibble = c - '0';
} else if (c >= 'a' && c <= 'f') {
nibble = c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
nibble = c - 'A' + 10;
} else {
throw new NumberFormatException("invalid hex char in trace_id at index " + (offset + i));
}
result = (result << 4) | nibble;
}
return result;
}

public static boolean isRootSpan(ReadableSpan span) {
SpanContext parent = span.getParentSpanContext();
boolean noParent = parent == SpanContext.getInvalid();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,21 @@ public void onStart(Context parentContext, ReadWriteSpan span) {

span.setAttribute(ATTRIBUTE_KEY_PROFILE_ID, strProfileId);
api.setTracingContext(spanId, spanName);
try {
api.setTraceId(span.getSpanContext().getTraceId());
} catch (NumberFormatException | IndexOutOfBoundsException e) {
api.clearTraceId();
}
}

@Override
public void onEnd(ReadableSpan span) {
if (configuration.rootSpanOnly && !isRootSpan(span)) {
return;
}
getProfiler().setTracingContext(0, 0);
ProfilerApi api = getProfiler();
api.setTracingContext(0, 0);
api.clearTraceId();
}

public static long parseSpanId(String strProfileId) {
Expand Down
Loading