Skip to content

Commit aa2dbfb

Browse files
authored
feat: Add support for JFR contextual information (#2739)
1 parent 2ecad69 commit aa2dbfb

5 files changed

Lines changed: 48 additions & 4 deletions

File tree

jfr-events/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ Create JFR events that can be recorded and viewed in Java Mission Control (JMC).
88
* The thread and stacktrace will be of the thread ending the span, which might
99
be different from the thread creating the span.
1010
* Has the fields
11-
* Operation Name
11+
* Operation Name (`@Contextual`)
1212
* Trace ID
1313
* Parent Span ID
1414
* Span ID
1515
* Creates Open Telemetry Tracing/Scope events for scopes
1616
* Thread will match the thread the scope was active in and the stacktrace will be when scope was closed
1717
* Multiple scopes might be collected for a single span
1818
* Has the fields
19-
* Trace ID
19+
* Trace ID (`@Contextual`)
2020
* Span ID
2121
* Supports the Open Source version of JFR in Java 11.
2222
* Might support back port to OpenJDK 8, but not tested and classes are built with JDK 11 bytecode.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.jfrevent;
7+
8+
import java.lang.annotation.ElementType;
9+
import java.lang.annotation.Retention;
10+
import java.lang.annotation.RetentionPolicy;
11+
import java.lang.annotation.Target;
12+
import jdk.jfr.Label;
13+
import jdk.jfr.MetadataDefinition;
14+
import jdk.jfr.Name;
15+
16+
/**
17+
* Meta-annotation to support @Contextual without compiling against JDK 25.
18+
*
19+
* @see <a href="https://bugs.openjdk.org/browse/JDK-8356699">JDK-8356699</a>
20+
*/
21+
@MetadataDefinition
22+
@Label("Context")
23+
@Retention(RetentionPolicy.RUNTIME)
24+
@Target({ElementType.FIELD})
25+
@Name("jdk.jfr.Contextual")
26+
@interface Contextual {}

jfr-events/src/main/java/io/opentelemetry/contrib/jfrevent/ScopeEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
+ "in scope/active on this thread.")
2121
class ScopeEvent extends Event {
2222

23-
private final String traceId;
23+
@Contextual private final String traceId;
2424
private final String spanId;
2525

2626
ScopeEvent(SpanContext spanContext) {

jfr-events/src/main/java/io/opentelemetry/contrib/jfrevent/SpanEvent.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
@Description("Open Telemetry trace event corresponding to a span.")
1919
class SpanEvent extends Event {
2020

21-
private final String operationName;
21+
@Contextual private final String operationName;
2222
private final String traceId;
2323
private final String spanId;
2424
private final String parentId;

jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.nio.file.Files;
1717
import java.nio.file.Path;
1818
import java.util.List;
19+
import java.util.stream.Collectors;
1920
import jdk.jfr.Recording;
2021
import jdk.jfr.consumer.RecordedEvent;
2122
import jdk.jfr.consumer.RecordingFile;
@@ -79,6 +80,14 @@ void basicSpan() throws IOException {
7980
assertThat(events)
8081
.extracting(e -> e.getValue("operationName"))
8182
.containsExactly(OPERATION_NAME);
83+
assertThat(events)
84+
.extracting(
85+
e ->
86+
e.getFields().stream()
87+
.filter(f -> f.getName().equals("operationName"))
88+
.map(d -> d.getAnnotation(Contextual.class))
89+
.collect(Collectors.toList()))
90+
.doesNotContainNull();
8291
} finally {
8392
Files.delete(output);
8493
}
@@ -121,6 +130,15 @@ void basicSpanWithScope() throws IOException, InterruptedException {
121130
.filteredOn(e -> "Span".equals(e.getEventType().getLabel()))
122131
.extracting(e -> e.getValue("operationName"))
123132
.containsExactly(OPERATION_NAME);
133+
assertThat(events)
134+
.filteredOn(e -> "Scope".equals(e.getEventType().getLabel()))
135+
.extracting(
136+
e ->
137+
e.getFields().stream()
138+
.filter(f -> f.getName().equals("traceId"))
139+
.map(d -> d.getAnnotation(Contextual.class))
140+
.collect(Collectors.toList()))
141+
.doesNotContainNull();
124142

125143
} finally {
126144
Files.delete(output);

0 commit comments

Comments
 (0)