From 2ec9749f2035011dc83d08ffe648a967d07cda47 Mon Sep 17 00:00:00 2001 From: Staffan Friberg Date: Thu, 22 Oct 2020 13:10:49 -0500 Subject: [PATCH 01/14] Rewritten for new context implementation Signed-off-by: Staffan Friberg --- sdk_extensions/jfr_events/README.md | 4 + sdk_extensions/jfr_events/build.gradle | 19 +++ .../jfr_events/nbproject/project.properties | 0 .../jfr/JfrContextStorageProvider.java | 47 +++++++ .../sdk/extension/jfr/JfrSpanProcessor.java | 79 +++++++++++ .../sdk/extension/jfr/ScopeEvent.java | 52 ++++++++ .../sdk/extension/jfr/SpanEvent.java | 66 ++++++++++ .../sdk/extension/jfr/package-info.java | 14 ++ ...entelemetry.context.ContextStorageProvider | 1 + .../extension/jfr/JfrSpanProcessorTest.java | 124 ++++++++++++++++++ settings.gradle | 1 + 11 files changed, 407 insertions(+) create mode 100644 sdk_extensions/jfr_events/README.md create mode 100644 sdk_extensions/jfr_events/build.gradle create mode 100644 sdk_extensions/jfr_events/nbproject/project.properties create mode 100644 sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java create mode 100644 sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java create mode 100644 sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java create mode 100644 sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java create mode 100644 sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java create mode 100644 sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider create mode 100644 sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java diff --git a/sdk_extensions/jfr_events/README.md b/sdk_extensions/jfr_events/README.md new file mode 100644 index 00000000000..ccf15c981fa --- /dev/null +++ b/sdk_extensions/jfr_events/README.md @@ -0,0 +1,4 @@ +OpenTelemetry SDK Extension JFR Events +====================================================== + +* Java 11 compatible. diff --git a/sdk_extensions/jfr_events/build.gradle b/sdk_extensions/jfr_events/build.gradle new file mode 100644 index 00000000000..3ba659157af --- /dev/null +++ b/sdk_extensions/jfr_events/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' + + id "ru.vyarus.animalsniffer" +} + +description = 'OpenTelemetry SDK Extension JFR' +ext.moduleName = 'io.opentelemetry.sdk.extension.jfr' + +dependencies { + implementation project(':opentelemetry-api'), + project(':opentelemetry-sdk') + + signature "org.codehaus.mojo.signature:java18:1.0@signature" +} + +tasks.withType(JavaCompile) { + it.options.release = 11 +} diff --git a/sdk_extensions/jfr_events/nbproject/project.properties b/sdk_extensions/jfr_events/nbproject/project.properties new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java new file mode 100644 index 00000000000..9b9f2f81f34 --- /dev/null +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.opentelemetry.sdk.extension.jfr; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.ContextStorage; +import io.opentelemetry.context.ContextStorageProvider; +import io.opentelemetry.context.Scope; +import io.opentelemetry.trace.Span; + +public class JfrContextStorageProvider implements ContextStorageProvider { + + @Override + public ContextStorage get() { + ContextStorage parentStorage = ContextStorage.get(); + return new ContextStorage() { + @Override + public Scope attach(Context toAttach) { + Scope scope = parentStorage.attach(toAttach); + ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); + event.begin(); + return () -> { + event.commit(); + scope.close(); + }; + } + + @Override + public Context current() { + return parentStorage.current(); + } + }; + } +} diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java new file mode 100644 index 00000000000..d657adecc57 --- /dev/null +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -0,0 +1,79 @@ +/* + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.opentelemetry.sdk.extension.jfr; + +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.trace.ReadWriteSpan; +import static java.util.Objects.nonNull; + +import io.opentelemetry.sdk.trace.ReadableSpan; +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.trace.SpanContext; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Span processor to create new JFR events for the Span as they are started, and + * commit on end. + * + *

+ * NOTE: JfrSpanProcessor must be running synchronously to ensure that duration + * is correctly captured. + */ +public class JfrSpanProcessor implements SpanProcessor { + + private final Map spanEvents = new ConcurrentHashMap<>(); + + @Override + public void onStart(ReadWriteSpan span, Context parentContext) { + if (span.getSpanContext().isValid()) { + SpanEvent event = new SpanEvent(span.toSpanData()); + event.begin(); + spanEvents.put(span.getSpanContext(), event); + } + } + + @Override + public boolean isStartRequired() { + return true; + } + + @Override + public void onEnd(ReadableSpan rs) { + SpanEvent event = spanEvents.remove(rs.getSpanContext()); + if (nonNull(event) && event.shouldCommit()) { + event.commit(); + } + } + + @Override + public boolean isEndRequired() { + return true; + } + + @Override + public CompletableResultCode shutdown() { + spanEvents.forEach((id, event) -> event.commit()); + spanEvents.clear(); + return CompletableResultCode.ofSuccess(); + } + + @Override + public CompletableResultCode forceFlush() { + return CompletableResultCode.ofSuccess(); + } +} diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java new file mode 100644 index 00000000000..a544ab2ab58 --- /dev/null +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java @@ -0,0 +1,52 @@ +/* + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.sdk.extension.jfr; + +import io.opentelemetry.trace.SpanContext; +import jdk.jfr.Category; +import jdk.jfr.Description; +import jdk.jfr.Event; +import jdk.jfr.Label; +import jdk.jfr.Name; + +@Name("io.opentelemetry.context.Scope") +@Label("Scope") +@Category("Open Telemetry Tracing") +@Description( + "Open Telemetry trace event corresponding to the span currently " + + "in scope/active on this thread.") +class ScopeEvent extends Event { + + @Label("Trace Id") + private final String traceId; + + @Label("Span Id") + private final String spanId; + + ScopeEvent(SpanContext spanContext) { + this.traceId = spanContext.getTraceIdAsHexString(); + this.spanId = spanContext.getSpanIdAsHexString(); + } + + public String getTraceId() { + return traceId; + } + + public String getSpanId() { + return spanId; + } +} diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java new file mode 100644 index 00000000000..9bd7121a8a7 --- /dev/null +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java @@ -0,0 +1,66 @@ +/* + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.sdk.extension.jfr; + +import io.opentelemetry.sdk.trace.data.SpanData; +import jdk.jfr.Category; +import jdk.jfr.Description; +import jdk.jfr.Event; +import jdk.jfr.Label; +import jdk.jfr.Name; + +@Label("Span") +@Name("io.opentelemetry.trace.Span") +@Category("Open Telemetry Tracing") +@Description("Open Telemetry trace event corresponding to a span.") +class SpanEvent extends Event { + + SpanEvent(SpanData spanData) { + this.operationName = spanData.getName(); + this.traceId = spanData.getTraceId(); + this.spanId = spanData.getSpanId(); + this.parentId = spanData.getParentSpanId(); + } + + @Label("Operation Name") + private final String operationName; + + @Label("Trace Id") + private final String traceId; + + @Label("Span Id") + private final String spanId; + + @Label("Parent Id") + private final String parentId; + + public String getOperationName() { + return operationName; + } + + public String getTraceId() { + return traceId; + } + + public String getSpanId() { + return spanId; + } + + public String getParentId() { + return parentId; + } +} diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java new file mode 100644 index 00000000000..ac7889ff0e5 --- /dev/null +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java @@ -0,0 +1,14 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Capture Spans and Scopes as events in JFR recordings. + * + * @see io.opentelemetry.sdk.extension.jfr.JfrSpanProcessor + */ +@ParametersAreNonnullByDefault +package io.opentelemetry.sdk.extension.jfr; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider b/sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider new file mode 100644 index 00000000000..859f599db4a --- /dev/null +++ b/sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider @@ -0,0 +1 @@ +io.opentelemetry.sdk.extension.jfr.JfrContextStorageProvider diff --git a/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java b/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java new file mode 100644 index 00000000000..1b98582a123 --- /dev/null +++ b/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java @@ -0,0 +1,124 @@ +/* + * Copyright 2020, OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.sdk.extension.jfr; + +import io.opentelemetry.OpenTelemetry; +import static org.junit.Assert.assertEquals; + +import io.opentelemetry.context.Scope; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.trace.Tracer; +import io.opentelemetry.trace.Span; +import io.opentelemetry.trace.TracingContextUtils; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; +import org.junit.Test; + +public class JfrSpanProcessorTest { + + private static final String OPERATION_NAME = "Test Span"; + private final Tracer tracer; + + /** Simple test to validate JFR events for Span and Scope. */ + public JfrSpanProcessorTest() { + tracer = OpenTelemetry.getGlobalTracer("JfrSpanProcessorTest"); + OpenTelemetrySdk.getTracerManagement().addSpanProcessor(new JfrSpanProcessor()); + } + + /** + * Test basic single span. + * + * @throws java.io.IOException on io error + */ + @Test + public void basicSpan() throws IOException { + Path output = Files.createTempFile("test-basic-span", ".jfr"); + + try { + Recording recording = new Recording(); + recording.start(); + Span span; + + try (recording) { + + span = tracer.spanBuilder(OPERATION_NAME).setNoParent().startSpan(); + span.end(); + + recording.dump(output); + } + + List events = RecordingFile.readAllEvents(output); + assertEquals(1, events.size()); + events.stream() + .forEach( + e -> { + assertEquals(span.getSpanContext().getTraceIdAsHexString(), e.getValue("traceId")); + assertEquals(span.getSpanContext().getSpanIdAsHexString(), e.getValue("spanId")); + assertEquals(OPERATION_NAME, e.getValue("operationName")); + }); + + } finally { + Files.delete(output); + } + } + + /** + * Test basic single span with a scope. + * + * @throws java.io.IOException on io error + */ + @Test + public void basicSpanWithScope() throws IOException, InterruptedException { + Path output = Files.createTempFile("test-basic-span-with-scope", ".jfr"); + + try { + Recording recording = new Recording(); + recording.start(); + Span span; + + try (recording) { + span = tracer.spanBuilder(OPERATION_NAME).setNoParent().startSpan(); + try (Scope s = TracingContextUtils.currentContextWith(span)) { + Thread.sleep(10); + } + span.end(); + + recording.dump(output); + } + + List events = RecordingFile.readAllEvents(output); + assertEquals(2, events.size()); + events.stream() + .forEach( + e -> { + assertEquals(span.getSpanContext().getTraceIdAsHexString(), e.getValue("traceId")); + assertEquals(span.getSpanContext().getSpanIdAsHexString(), e.getValue("spanId")); + if ("Span".equals(e.getEventType().getLabel())) { + assertEquals(OPERATION_NAME, e.getValue("operationName")); + } + }); + + } finally { + Files.delete(output); + } + } +} diff --git a/settings.gradle b/settings.gradle index 717dd0d4aee..d21029b8789 100644 --- a/settings.gradle +++ b/settings.gradle @@ -52,6 +52,7 @@ include ":opentelemetry-all", ":opentelemetry-sdk-extension-resources", ":opentelemetry-sdk-extension-tracing-incubator", ":opentelemetry-sdk-extension-jaeger-remote-sampler", + ":opentelemetry-sdk-extension-jfr-events", ":opentelemetry-sdk-extension-zpages", ":opentelemetry-sdk-testing", ":opentelemetry-bom", From f67d52f6820b050a54b3d538c99f22489b859842 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Thu, 22 Oct 2020 13:47:43 -0500 Subject: [PATCH 02/14] remove nb file --- sdk_extensions/jfr_events/nbproject/project.properties | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 sdk_extensions/jfr_events/nbproject/project.properties diff --git a/sdk_extensions/jfr_events/nbproject/project.properties b/sdk_extensions/jfr_events/nbproject/project.properties deleted file mode 100644 index e69de29bb2d..00000000000 From b0b71f1f23410837f7b332c2eacb7c28bdfc779b Mon Sep 17 00:00:00 2001 From: sfriberg Date: Thu, 22 Oct 2020 13:49:57 -0500 Subject: [PATCH 03/14] animalsniffer --- sdk_extensions/jfr_events/build.gradle | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sdk_extensions/jfr_events/build.gradle b/sdk_extensions/jfr_events/build.gradle index 3ba659157af..aee8c5b89d4 100644 --- a/sdk_extensions/jfr_events/build.gradle +++ b/sdk_extensions/jfr_events/build.gradle @@ -1,7 +1,5 @@ plugins { id 'java' - - id "ru.vyarus.animalsniffer" } description = 'OpenTelemetry SDK Extension JFR' @@ -10,8 +8,6 @@ ext.moduleName = 'io.opentelemetry.sdk.extension.jfr' dependencies { implementation project(':opentelemetry-api'), project(':opentelemetry-sdk') - - signature "org.codehaus.mojo.signature:java18:1.0@signature" } tasks.withType(JavaCompile) { From 52e1a4250bca9c3c4bc3b4e30557d16f10a6f167 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Thu, 22 Oct 2020 13:54:20 -0500 Subject: [PATCH 04/14] spotless --- .../jfr/JfrContextStorageProvider.java | 56 +++++------ .../sdk/extension/jfr/JfrSpanProcessor.java | 92 ++++++++----------- .../sdk/extension/jfr/ScopeEvent.java | 15 +-- .../sdk/extension/jfr/SpanEvent.java | 15 +-- .../extension/jfr/JfrSpanProcessorTest.java | 23 ++--- 5 files changed, 73 insertions(+), 128 deletions(-) diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java index 9b9f2f81f34..f3f65869bc2 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java @@ -1,18 +1,8 @@ /* - * Copyright 2020, OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 */ + package io.opentelemetry.sdk.extension.jfr; import io.opentelemetry.context.Context; @@ -23,25 +13,25 @@ public class JfrContextStorageProvider implements ContextStorageProvider { - @Override - public ContextStorage get() { - ContextStorage parentStorage = ContextStorage.get(); - return new ContextStorage() { - @Override - public Scope attach(Context toAttach) { - Scope scope = parentStorage.attach(toAttach); - ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); - event.begin(); - return () -> { - event.commit(); - scope.close(); - }; - } - - @Override - public Context current() { - return parentStorage.current(); - } + @Override + public ContextStorage get() { + ContextStorage parentStorage = ContextStorage.get(); + return new ContextStorage() { + @Override + public Scope attach(Context toAttach) { + Scope scope = parentStorage.attach(toAttach); + ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); + event.begin(); + return () -> { + event.commit(); + scope.close(); }; - } + } + + @Override + public Context current() { + return parentStorage.current(); + } + }; + } } diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java index d657adecc57..2910983c541 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -1,25 +1,15 @@ /* - * Copyright 2020, OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 */ + package io.opentelemetry.sdk.extension.jfr; +import static java.util.Objects.nonNull; + import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.ReadWriteSpan; -import static java.util.Objects.nonNull; - import io.opentelemetry.sdk.trace.ReadableSpan; import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.trace.SpanContext; @@ -27,53 +17,51 @@ import java.util.concurrent.ConcurrentHashMap; /** - * Span processor to create new JFR events for the Span as they are started, and - * commit on end. + * Span processor to create new JFR events for the Span as they are started, and commit on end. * - *

- * NOTE: JfrSpanProcessor must be running synchronously to ensure that duration - * is correctly captured. + *

NOTE: JfrSpanProcessor must be running synchronously to ensure that duration is correctly + * captured. */ public class JfrSpanProcessor implements SpanProcessor { - private final Map spanEvents = new ConcurrentHashMap<>(); + private final Map spanEvents = new ConcurrentHashMap<>(); - @Override - public void onStart(ReadWriteSpan span, Context parentContext) { - if (span.getSpanContext().isValid()) { - SpanEvent event = new SpanEvent(span.toSpanData()); - event.begin(); - spanEvents.put(span.getSpanContext(), event); - } + @Override + public void onStart(ReadWriteSpan span, Context parentContext) { + if (span.getSpanContext().isValid()) { + SpanEvent event = new SpanEvent(span.toSpanData()); + event.begin(); + spanEvents.put(span.getSpanContext(), event); } + } - @Override - public boolean isStartRequired() { - return true; - } + @Override + public boolean isStartRequired() { + return true; + } - @Override - public void onEnd(ReadableSpan rs) { - SpanEvent event = spanEvents.remove(rs.getSpanContext()); - if (nonNull(event) && event.shouldCommit()) { - event.commit(); - } + @Override + public void onEnd(ReadableSpan rs) { + SpanEvent event = spanEvents.remove(rs.getSpanContext()); + if (nonNull(event) && event.shouldCommit()) { + event.commit(); } + } - @Override - public boolean isEndRequired() { - return true; - } + @Override + public boolean isEndRequired() { + return true; + } - @Override - public CompletableResultCode shutdown() { - spanEvents.forEach((id, event) -> event.commit()); - spanEvents.clear(); - return CompletableResultCode.ofSuccess(); - } + @Override + public CompletableResultCode shutdown() { + spanEvents.forEach((id, event) -> event.commit()); + spanEvents.clear(); + return CompletableResultCode.ofSuccess(); + } - @Override - public CompletableResultCode forceFlush() { - return CompletableResultCode.ofSuccess(); - } + @Override + public CompletableResultCode forceFlush() { + return CompletableResultCode.ofSuccess(); + } } diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java index a544ab2ab58..ab406f9edeb 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java @@ -1,17 +1,6 @@ /* - * Copyright 2020, OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 */ package io.opentelemetry.sdk.extension.jfr; diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java index 9bd7121a8a7..fbf95aa0cf9 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java @@ -1,17 +1,6 @@ /* - * Copyright 2020, OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 */ package io.opentelemetry.sdk.extension.jfr; diff --git a/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java b/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java index 1b98582a123..405de017d4e 100644 --- a/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java +++ b/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java @@ -1,28 +1,17 @@ /* - * Copyright 2020, OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 */ package io.opentelemetry.sdk.extension.jfr; -import io.opentelemetry.OpenTelemetry; import static org.junit.Assert.assertEquals; +import io.opentelemetry.OpenTelemetry; import io.opentelemetry.context.Scope; import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.trace.Tracer; import io.opentelemetry.trace.Span; +import io.opentelemetry.trace.Tracer; import io.opentelemetry.trace.TracingContextUtils; import java.io.IOException; import java.nio.file.Files; @@ -40,8 +29,8 @@ public class JfrSpanProcessorTest { /** Simple test to validate JFR events for Span and Scope. */ public JfrSpanProcessorTest() { - tracer = OpenTelemetry.getGlobalTracer("JfrSpanProcessorTest"); - OpenTelemetrySdk.getTracerManagement().addSpanProcessor(new JfrSpanProcessor()); + tracer = OpenTelemetry.getGlobalTracer("JfrSpanProcessorTest"); + OpenTelemetrySdk.getTracerManagement().addSpanProcessor(new JfrSpanProcessor()); } /** From 3c8f01755a2e9f1c4a94871702718ac93c36852a Mon Sep 17 00:00:00 2001 From: sfriberg Date: Fri, 23 Oct 2020 10:44:46 -0500 Subject: [PATCH 05/14] rewrite --- .../jfr/JfrContextStorageProvider.java | 53 +++++++++++-------- .../sdk/extension/jfr/JfrSpanProcessor.java | 2 +- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java index f3f65869bc2..b4f1f38acf4 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java @@ -2,7 +2,6 @@ * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 */ - package io.opentelemetry.sdk.extension.jfr; import io.opentelemetry.context.Context; @@ -13,25 +12,35 @@ public class JfrContextStorageProvider implements ContextStorageProvider { - @Override - public ContextStorage get() { - ContextStorage parentStorage = ContextStorage.get(); - return new ContextStorage() { - @Override - public Scope attach(Context toAttach) { - Scope scope = parentStorage.attach(toAttach); - ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); - event.begin(); - return () -> { - event.commit(); - scope.close(); - }; - } - - @Override - public Context current() { - return parentStorage.current(); - } - }; - } + private static final ContextStorage INSTANCE = new JfrContextStorage(ContextStorage.get()); + + @Override + public ContextStorage get() { + return INSTANCE; + } + + static class JfrContextStorage implements ContextStorage { + + private final ContextStorage wrappedStorage; + + public JfrContextStorage(ContextStorage wrappedStorage) { + this.wrappedStorage = wrappedStorage; + } + + @Override + public Scope attach(Context toAttach) { + Scope scope = wrappedStorage.attach(toAttach); + ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); + event.begin(); + return () -> { + event.commit(); + scope.close(); + }; + } + + @Override + public Context current() { + return wrappedStorage.current(); + } + } } diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java index 2910983c541..f2f34464852 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java +++ b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -27,7 +27,7 @@ public class JfrSpanProcessor implements SpanProcessor { private final Map spanEvents = new ConcurrentHashMap<>(); @Override - public void onStart(ReadWriteSpan span, Context parentContext) { + public void onStart(Context parentContext, ReadWriteSpan span) { if (span.getSpanContext().isValid()) { SpanEvent event = new SpanEvent(span.toSpanData()); event.begin(); From d01fdc306b32656fac2e4531d035ff6380b00a02 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Fri, 13 Nov 2020 17:22:01 -0600 Subject: [PATCH 06/14] Use new ContextStorageWrapper capabilities --- .../jfr-events}/README.md | 0 .../jfr-events}/build.gradle | 0 .../jfr/JfrContextStorageWrapper.java | 36 +++++++++++++++ .../sdk/extension/jfr/JfrSpanProcessor.java | 2 +- .../sdk/extension/jfr/ScopeEvent.java | 2 +- .../sdk/extension/jfr/SpanEvent.java | 14 +++--- .../sdk/extension/jfr/package-info.java | 0 .../extension/jfr/JfrSpanProcessorTest.java | 14 +++--- .../jfr/JfrContextStorageProvider.java | 46 ------------------- ...entelemetry.context.ContextStorageProvider | 1 - 10 files changed, 52 insertions(+), 63 deletions(-) rename {sdk_extensions/jfr_events => sdk-extensions/jfr-events}/README.md (100%) rename {sdk_extensions/jfr_events => sdk-extensions/jfr-events}/build.gradle (100%) create mode 100644 sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java rename {sdk_extensions/jfr_events => sdk-extensions/jfr-events}/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java (97%) rename {sdk_extensions/jfr_events => sdk-extensions/jfr-events}/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java (94%) rename {sdk_extensions/jfr_events => sdk-extensions/jfr-events}/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java (100%) rename {sdk_extensions/jfr_events => sdk-extensions/jfr-events}/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java (100%) rename {sdk_extensions/jfr_events => sdk-extensions/jfr-events}/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java (88%) delete mode 100644 sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java delete mode 100644 sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider diff --git a/sdk_extensions/jfr_events/README.md b/sdk-extensions/jfr-events/README.md similarity index 100% rename from sdk_extensions/jfr_events/README.md rename to sdk-extensions/jfr-events/README.md diff --git a/sdk_extensions/jfr_events/build.gradle b/sdk-extensions/jfr-events/build.gradle similarity index 100% rename from sdk_extensions/jfr_events/build.gradle rename to sdk-extensions/jfr-events/build.gradle diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java new file mode 100644 index 00000000000..2f34022cc13 --- /dev/null +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java @@ -0,0 +1,36 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.extension.jfr; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.ContextStorage; +import io.opentelemetry.context.Scope; + +public class JfrContextStorageWrapper implements ContextStorage { + + private final ContextStorage wrapped; + + public JfrContextStorageWrapper(ContextStorage wrapped) { + this.wrapped = wrapped; + } + + @Override + public Scope attach(Context toAttach) { + Scope scope = wrapped.attach(toAttach); + ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); + event.begin(); + return () -> { + event.commit(); + scope.close(); + }; + } + + @Override + public Context current() { + return wrapped.current(); + } +} diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java similarity index 97% rename from sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java rename to sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java index f2f34464852..25f129e658e 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -7,12 +7,12 @@ import static java.util.Objects.nonNull; +import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.ReadWriteSpan; import io.opentelemetry.sdk.trace.ReadableSpan; import io.opentelemetry.sdk.trace.SpanProcessor; -import io.opentelemetry.trace.SpanContext; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java similarity index 94% rename from sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java rename to sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java index ab406f9edeb..6dc03d86d5e 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java @@ -5,7 +5,7 @@ package io.opentelemetry.sdk.extension.jfr; -import io.opentelemetry.trace.SpanContext; +import io.opentelemetry.api.trace.SpanContext; import jdk.jfr.Category; import jdk.jfr.Description; import jdk.jfr.Event; diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java similarity index 100% rename from sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java rename to sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java index fbf95aa0cf9..d16ddf7a394 100644 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java @@ -18,13 +18,6 @@ @Description("Open Telemetry trace event corresponding to a span.") class SpanEvent extends Event { - SpanEvent(SpanData spanData) { - this.operationName = spanData.getName(); - this.traceId = spanData.getTraceId(); - this.spanId = spanData.getSpanId(); - this.parentId = spanData.getParentSpanId(); - } - @Label("Operation Name") private final String operationName; @@ -37,6 +30,13 @@ class SpanEvent extends Event { @Label("Parent Id") private final String parentId; + SpanEvent(SpanData spanData) { + this.operationName = spanData.getName(); + this.traceId = spanData.getTraceId(); + this.spanId = spanData.getSpanId(); + this.parentId = spanData.getParentSpanId(); + } + public String getOperationName() { return operationName; } diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java similarity index 100% rename from sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java rename to sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/package-info.java diff --git a/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java similarity index 88% rename from sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java rename to sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java index 405de017d4e..416abf7bf2c 100644 --- a/sdk_extensions/jfr_events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java +++ b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java @@ -7,12 +7,11 @@ import static org.junit.Assert.assertEquals; -import io.opentelemetry.OpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.ContextStorage; import io.opentelemetry.context.Scope; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.trace.Span; -import io.opentelemetry.trace.Tracer; -import io.opentelemetry.trace.TracingContextUtils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -29,8 +28,8 @@ public class JfrSpanProcessorTest { /** Simple test to validate JFR events for Span and Scope. */ public JfrSpanProcessorTest() { + ContextStorage.addWrapper(JfrContextStorageWrapper::new); tracer = OpenTelemetry.getGlobalTracer("JfrSpanProcessorTest"); - OpenTelemetrySdk.getTracerManagement().addSpanProcessor(new JfrSpanProcessor()); } /** @@ -74,6 +73,7 @@ public void basicSpan() throws IOException { * Test basic single span with a scope. * * @throws java.io.IOException on io error + * @throws java.lang.InterruptedException interrupted sleep */ @Test public void basicSpanWithScope() throws IOException, InterruptedException { @@ -86,7 +86,7 @@ public void basicSpanWithScope() throws IOException, InterruptedException { try (recording) { span = tracer.spanBuilder(OPERATION_NAME).setNoParent().startSpan(); - try (Scope s = TracingContextUtils.currentContextWith(span)) { + try (Scope s = span.makeCurrent()) { Thread.sleep(10); } span.end(); diff --git a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java b/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java deleted file mode 100644 index b4f1f38acf4..00000000000 --- a/sdk_extensions/jfr_events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ -package io.opentelemetry.sdk.extension.jfr; - -import io.opentelemetry.context.Context; -import io.opentelemetry.context.ContextStorage; -import io.opentelemetry.context.ContextStorageProvider; -import io.opentelemetry.context.Scope; -import io.opentelemetry.trace.Span; - -public class JfrContextStorageProvider implements ContextStorageProvider { - - private static final ContextStorage INSTANCE = new JfrContextStorage(ContextStorage.get()); - - @Override - public ContextStorage get() { - return INSTANCE; - } - - static class JfrContextStorage implements ContextStorage { - - private final ContextStorage wrappedStorage; - - public JfrContextStorage(ContextStorage wrappedStorage) { - this.wrappedStorage = wrappedStorage; - } - - @Override - public Scope attach(Context toAttach) { - Scope scope = wrappedStorage.attach(toAttach); - ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); - event.begin(); - return () -> { - event.commit(); - scope.close(); - }; - } - - @Override - public Context current() { - return wrappedStorage.current(); - } - } -} diff --git a/sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider b/sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider deleted file mode 100644 index 859f599db4a..00000000000 --- a/sdk_extensions/jfr_events/src/main/resources/META-INF/services/io.opentelemetry.context.ContextStorageProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.sdk.extension.jfr.JfrContextStorageProvider From 81a0357f2fc0ba553a2ea0257b5193251911a822 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Mon, 23 Nov 2020 14:47:10 -0600 Subject: [PATCH 07/14] work-around JDK bug --- build.gradle | 2 +- sdk-extensions/jfr-events/build.gradle | 7 +++++++ .../sdk/extension/jfr/JfrSpanProcessorTest.java | 7 ++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0ebdb4206a8..134bb8e11fd 100644 --- a/build.gradle +++ b/build.gradle @@ -370,7 +370,7 @@ configure(opentelemetryProjects) { configProperties["rootDir"] = rootDir } - jacoco { toolVersion = "0.8.5" } + jacoco { toolVersion = "0.8.6" } spotless { java { diff --git a/sdk-extensions/jfr-events/build.gradle b/sdk-extensions/jfr-events/build.gradle index aee8c5b89d4..5d9f01c9acc 100644 --- a/sdk-extensions/jfr-events/build.gradle +++ b/sdk-extensions/jfr-events/build.gradle @@ -13,3 +13,10 @@ dependencies { tasks.withType(JavaCompile) { it.options.release = 11 } + +// Running tests with JDK 15 due to https://bugs.openjdk.java.net/browse/JDK-8245283 +test { + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(15) + } +} \ No newline at end of file diff --git a/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java index 416abf7bf2c..3e703637f7a 100644 --- a/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java +++ b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java @@ -12,6 +12,7 @@ import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.ContextStorage; import io.opentelemetry.context.Scope; +import io.opentelemetry.sdk.OpenTelemetrySdk; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -26,9 +27,13 @@ public class JfrSpanProcessorTest { private static final String OPERATION_NAME = "Test Span"; private final Tracer tracer; + static { + ContextStorage.addWrapper(JfrContextStorageWrapper::new); + OpenTelemetrySdk.getGlobalTracerManagement().addSpanProcessor(new JfrSpanProcessor()); + } + /** Simple test to validate JFR events for Span and Scope. */ public JfrSpanProcessorTest() { - ContextStorage.addWrapper(JfrContextStorageWrapper::new); tracer = OpenTelemetry.getGlobalTracer("JfrSpanProcessorTest"); } From 146c7ea0a7d328c192fad79fd40685bafeb231ae Mon Sep 17 00:00:00 2001 From: sfriberg Date: Mon, 23 Nov 2020 14:58:52 -0600 Subject: [PATCH 08/14] update junit --- .../opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java index 3e703637f7a..9b25551c074 100644 --- a/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java +++ b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.sdk.extension.jfr; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; @@ -20,7 +20,7 @@ import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingFile; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class JfrSpanProcessorTest { From 84f9815138a4e3d98d47151454fe4102eb3aa14e Mon Sep 17 00:00:00 2001 From: sfriberg Date: Mon, 23 Nov 2020 15:17:51 -0600 Subject: [PATCH 09/14] update readme --- sdk-extensions/jfr-events/README.md | 19 +++++++++++++++++-- sdk-extensions/jfr-events/build.gradle | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/sdk-extensions/jfr-events/README.md b/sdk-extensions/jfr-events/README.md index ccf15c981fa..cd20cce8326 100644 --- a/sdk-extensions/jfr-events/README.md +++ b/sdk-extensions/jfr-events/README.md @@ -1,4 +1,19 @@ -OpenTelemetry SDK Extension JFR Events +OpenTelemetry SDK Extension Java Flight Recorder (JFR) Events ====================================================== -* Java 11 compatible. +Create JFR events that can be recorded and viewed in Java Mission Control (JMC). +* Creates Open Telemetry Tracing/Span events for spans + * The thread and stracktrace will be of the thead ending the span which might be different than the thread creating the span. + * Has the fields + * Operation Name + * Trace ID + * Parent Span ID + * Span ID +* Creates Open Telemetry Tracing/Scope events for scopes + * Thread will match the thread the scope was active in and the stacktrace will be when scope was closed + * Multiple scopes might be collected for a single span + * Has the fields + * Trace ID + * Span ID +* Supports the Open Source version of JFR in Java 11. + * Might support back port to OpenJDK 8, but not tested and classes are built with JDK 11 bytecode. diff --git a/sdk-extensions/jfr-events/build.gradle b/sdk-extensions/jfr-events/build.gradle index 5d9f01c9acc..195f0c5c784 100644 --- a/sdk-extensions/jfr-events/build.gradle +++ b/sdk-extensions/jfr-events/build.gradle @@ -19,4 +19,4 @@ test { javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(15) } -} \ No newline at end of file +} From 94da981b7eb63c7eced9d2a62f41efab528dc84f Mon Sep 17 00:00:00 2001 From: sfriberg Date: Mon, 23 Nov 2020 15:26:49 -0600 Subject: [PATCH 10/14] Update build script --- sdk-extensions/jfr-events/build.gradle | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sdk-extensions/jfr-events/build.gradle b/sdk-extensions/jfr-events/build.gradle index 195f0c5c784..3e40c5bda42 100644 --- a/sdk-extensions/jfr-events/build.gradle +++ b/sdk-extensions/jfr-events/build.gradle @@ -14,9 +14,11 @@ tasks.withType(JavaCompile) { it.options.release = 11 } -// Running tests with JDK 15 due to https://bugs.openjdk.java.net/browse/JDK-8245283 +testJava8 { + enabled = false +} + test { - javaLauncher = javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(15) - } + // Disabled due to https://bugs.openjdk.java.net/browse/JDK-8245283 + jacoco.enabled = false } From 9e6856945df1fb6d18ea287bd1fa82a9c2f931a9 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Tue, 24 Nov 2020 09:34:17 -0600 Subject: [PATCH 11/14] PR comments --- sdk-extensions/jfr-events/build.gradle | 1 + .../jfr/JfrContextStorageWrapper.java | 4 +- .../sdk/extension/jfr/JfrSpanProcessor.java | 71 +++++++++++++++++-- .../sdk/extension/jfr/ScopeEvent.java | 5 +- .../sdk/extension/jfr/SpanEvent.java | 11 ++- .../extension/jfr/JfrSpanProcessorTest.java | 2 +- 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/sdk-extensions/jfr-events/build.gradle b/sdk-extensions/jfr-events/build.gradle index 3e40c5bda42..e3a455051fc 100644 --- a/sdk-extensions/jfr-events/build.gradle +++ b/sdk-extensions/jfr-events/build.gradle @@ -8,6 +8,7 @@ ext.moduleName = 'io.opentelemetry.sdk.extension.jfr' dependencies { implementation project(':opentelemetry-api'), project(':opentelemetry-sdk') + implementation libraries.guava } tasks.withType(JavaCompile) { diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java index 2f34022cc13..8754259f148 100644 --- a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrContextStorageWrapper.java @@ -24,7 +24,9 @@ public Scope attach(Context toAttach) { ScopeEvent event = new ScopeEvent(Span.fromContext(toAttach).getSpanContext()); event.begin(); return () -> { - event.commit(); + if (event.shouldCommit()) { + event.commit(); + } scope.close(); }; } diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java index 25f129e658e..6572289085e 100644 --- a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -7,14 +7,17 @@ import static java.util.Objects.nonNull; +import com.google.common.collect.MapMaker; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.ReadWriteSpan; import io.opentelemetry.sdk.trace.ReadableSpan; import io.opentelemetry.sdk.trace.SpanProcessor; +import java.util.Collection; +import java.util.Collections; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.Set; /** * Span processor to create new JFR events for the Span as they are started, and commit on end. @@ -24,7 +27,8 @@ */ public class JfrSpanProcessor implements SpanProcessor { - private final Map spanEvents = new ConcurrentHashMap<>(); + private volatile Map spanEvents = + new MapMaker().concurrencyLevel(16).initialCapacity(128).weakKeys().makeMap(); @Override public void onStart(Context parentContext, ReadWriteSpan span) { @@ -55,13 +59,66 @@ public boolean isEndRequired() { @Override public CompletableResultCode shutdown() { - spanEvents.forEach((id, event) -> event.commit()); - spanEvents.clear(); + spanEvents = new NoopMap<>(); return CompletableResultCode.ofSuccess(); } - @Override - public CompletableResultCode forceFlush() { - return CompletableResultCode.ofSuccess(); + private static class NoopMap implements Map { + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public V get(Object key) { + return null; + } + + @Override + public V put(K key, V value) { + return null; + } + + @Override + public V remove(Object key) { + return null; + } + + @Override + public void putAll(Map m) {} + + @Override + public void clear() {} + + @Override + public Set keySet() { + return Collections.emptySet(); + } + + @Override + public Collection values() { + return Collections.emptyList(); + } + + @Override + public Set> entrySet() { + return Collections.emptySet(); + } } } diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java index 6dc03d86d5e..cae0e8dc2dd 100644 --- a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/ScopeEvent.java @@ -20,10 +20,7 @@ + "in scope/active on this thread.") class ScopeEvent extends Event { - @Label("Trace Id") private final String traceId; - - @Label("Span Id") private final String spanId; ScopeEvent(SpanContext spanContext) { @@ -31,10 +28,12 @@ class ScopeEvent extends Event { this.spanId = spanContext.getSpanIdAsHexString(); } + @Label("Trace Id") public String getTraceId() { return traceId; } + @Label("Span Id") public String getSpanId() { return spanId; } diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java index d16ddf7a394..1e239b92937 100644 --- a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/SpanEvent.java @@ -18,16 +18,9 @@ @Description("Open Telemetry trace event corresponding to a span.") class SpanEvent extends Event { - @Label("Operation Name") private final String operationName; - - @Label("Trace Id") private final String traceId; - - @Label("Span Id") private final String spanId; - - @Label("Parent Id") private final String parentId; SpanEvent(SpanData spanData) { @@ -37,18 +30,22 @@ class SpanEvent extends Event { this.parentId = spanData.getParentSpanId(); } + @Label("Operation Name") public String getOperationName() { return operationName; } + @Label("Trace Id") public String getTraceId() { return traceId; } + @Label("Span Id") public String getSpanId() { return spanId; } + @Label("Parent Id") public String getParentId() { return parentId; } diff --git a/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java index 9b25551c074..feeb34528ce 100644 --- a/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java +++ b/sdk-extensions/jfr-events/src/test/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessorTest.java @@ -22,7 +22,7 @@ import jdk.jfr.consumer.RecordingFile; import org.junit.jupiter.api.Test; -public class JfrSpanProcessorTest { +class JfrSpanProcessorTest { private static final String OPERATION_NAME = "Test Span"; private final Tracer tracer; From 97e8001e8d29b1605ef03be49542f4c5e38682f0 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Tue, 24 Nov 2020 09:36:59 -0600 Subject: [PATCH 12/14] Update sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java Co-authored-by: Anuraag Agrawal --- .../io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java index 6572289085e..2cd5561d20e 100644 --- a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -47,7 +47,7 @@ public boolean isStartRequired() { @Override public void onEnd(ReadableSpan rs) { SpanEvent event = spanEvents.remove(rs.getSpanContext()); - if (nonNull(event) && event.shouldCommit()) { + if (event != null && event.shouldCommit()) { event.commit(); } } From e5a88a766a5656acbbe8e39b6f4195855dfd78b9 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Tue, 24 Nov 2020 09:37:30 -0600 Subject: [PATCH 13/14] Update JfrSpanProcessor.java --- .../io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java index 2cd5561d20e..460df01eda1 100644 --- a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -5,8 +5,6 @@ package io.opentelemetry.sdk.extension.jfr; -import static java.util.Objects.nonNull; - import com.google.common.collect.MapMaker; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; From 7eb048d1b08f3343e9c466a63e0b26eb50cb8a09 Mon Sep 17 00:00:00 2001 From: sfriberg Date: Tue, 24 Nov 2020 09:56:05 -0600 Subject: [PATCH 14/14] Update comment --- .../io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java index 460df01eda1..2588b19f55b 100644 --- a/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java +++ b/sdk-extensions/jfr-events/src/main/java/io/opentelemetry/sdk/extension/jfr/JfrSpanProcessor.java @@ -20,8 +20,9 @@ /** * Span processor to create new JFR events for the Span as they are started, and commit on end. * - *

NOTE: JfrSpanProcessor must be running synchronously to ensure that duration is correctly - * captured. + *

NOTE: The JfrSpanProcessor measures the timing of spans, avoid if possible to wrap it with any + * other SpanProcessor which may affect timings. When possible, register it first before any other + * processors to allow the most accurate measurements. */ public class JfrSpanProcessor implements SpanProcessor {