From f64d12ccb34eedad7fc49b45a5c5aa4459e07e79 Mon Sep 17 00:00:00 2001 From: Tim Quinn Date: Wed, 10 Apr 2024 19:31:58 -0500 Subject: [PATCH] Enhance unwrap; add test to check unwrapping as a stand-in for JFR mapping --- .../opentelemetry/OpenTelemetrySpan.java | 108 ++++++++++-------- .../TestSpanLifeCycleListenerUnwrap.java | 78 +++++++++++++ .../opentracing/OpenTracingSpan.java | 108 ++++++++++-------- .../tracing/providers/zipkin/ZipkinSpan.java | 14 +++ 4 files changed, 208 insertions(+), 100 deletions(-) create mode 100644 tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestSpanLifeCycleListenerUnwrap.java diff --git a/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpan.java b/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpan.java index 362f272e1a2..7bf4dc958c0 100644 --- a/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpan.java +++ b/tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpan.java @@ -236,67 +236,75 @@ private Attributes toAttributes(Map attributes) { private record Limited(OpenTelemetrySpan delegate) implements Span { @Override - public Span tag(String key, String value) { - delegate.tag(key, value); - return this; - } + public Span tag(String key, String value) { + delegate.tag(key, value); + return this; + } - @Override - public Span tag(String key, Boolean value) { - delegate.tag(key, value); - return this; - } + @Override + public Span tag(String key, Boolean value) { + delegate.tag(key, value); + return this; + } - @Override - public Span tag(String key, Number value) { - delegate.tag(key, value); - return this; - } + @Override + public Span tag(String key, Number value) { + delegate.tag(key, value); + return this; + } - @Override - public void status(Status status) { - throw new UnsupportedOperationException(); - } + @Override + public void status(Status status) { + throw new UnsupportedOperationException(); + } - @Override - public SpanContext context() { - return delegate.context(); - } + @Override + public SpanContext context() { + return delegate.context(); + } - @Override - public void addEvent(String name, Map attributes) { - delegate.addEvent(name, attributes); - } + @Override + public void addEvent(String name, Map attributes) { + delegate.addEvent(name, attributes); + } - @Override - public void end() { - throw new UnsupportedOperationException(); - } + @Override + public void end() { + throw new UnsupportedOperationException(); + } - @Override - public void end(Throwable t) { - throw new UnsupportedOperationException(); - } + @Override + public void end(Throwable t) { + throw new UnsupportedOperationException(); + } - @Override - public Scope activate() { - throw new UnsupportedOperationException(); - } + @Override + public Scope activate() { + throw new UnsupportedOperationException(); + } - @Override - public Span baggage(String key, String value) { - delegate.baggage().set(key, value); - return this; - } + @Override + public Span baggage(String key, String value) { + delegate.baggage().set(key, value); + return this; + } - @Override - public Optional baggage(String key) { - return delegate.baggage(key); - } + @Override + public Optional baggage(String key) { + return delegate.baggage(key); + } - @Override - public WritableBaggage baggage() { - return delegate.baggage(); + @Override + public WritableBaggage baggage() { + return delegate.baggage(); + } + + @Override + public T unwrap(Class spanClass) { + if (spanClass.isInstance(this)) { + return spanClass.cast(this); } + return delegate.unwrap(spanClass); } + } } diff --git a/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestSpanLifeCycleListenerUnwrap.java b/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestSpanLifeCycleListenerUnwrap.java new file mode 100644 index 00000000000..49803951be2 --- /dev/null +++ b/tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestSpanLifeCycleListenerUnwrap.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. + * + * 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.helidon.tracing.providers.opentelemetry; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import io.helidon.tracing.Span; +import io.helidon.tracing.SpanLifeCycleListener; +import io.helidon.tracing.Tracer; +import io.helidon.tracing.TracerBuilder; + +import io.opentelemetry.sdk.trace.ReadableSpan; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.is; + +class TestSpanLifeCycleListenerUnwrap { + + @Test + void testSpanListenerUnwrap() { + // Acts as if we were trying to map span information to JFR events. + Tracer tracer = TracerBuilder.create("OTelTracer").build(); + + AtomicReference unwrapResults = new AtomicReference<>(); + + SpanLifeCycleListener l1 = new SpanLifeCycleListener() { + @Override + public void afterStart(Span span) throws UnsupportedOperationException { + io.opentelemetry.api.trace.Span otelSpan = span.unwrap(io.opentelemetry.api.trace.Span.class); + ReadableSpan readableSpan = (ReadableSpan) otelSpan; + unwrapResults.set(UnwrapResults.create(readableSpan)); + } + }; + + tracer.register(l1); + + Span.Builder spanBuilder = tracer.spanBuilder("myOperation"); + spanBuilder.tag("tag1", 3L); + Span span = spanBuilder.start(); + try { + assertThat("Span name", unwrapResults.get().spanName, is("myOperation")); + assertThat("Tracer ID", unwrapResults.get().traceId, is(span.context().traceId())); + assertThat("Span ID", unwrapResults.get().spanId, is(span.context().spanId())); + assertThat("Tags", unwrapResults.get().tags, hasEntry("tag1", 3L)); + } finally { + span.end(); + } + } + + private record UnwrapResults(String traceId, String spanId, String spanName, Map tags) { + + private static UnwrapResults create(ReadableSpan readableSpan) { + Map tags = new HashMap<>(); + readableSpan.toSpanData().getAttributes().forEach((attrKey, value) -> tags.put(attrKey.getKey(), value)); + return new UnwrapResults(readableSpan.getSpanContext().getTraceId(), + readableSpan.getSpanContext().getSpanId(), + readableSpan.getName(), + tags); + } + } +} diff --git a/tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingSpan.java b/tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingSpan.java index 296041b7a70..7c15cdd07de 100644 --- a/tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingSpan.java +++ b/tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingSpan.java @@ -164,67 +164,75 @@ Limited limited() { private record Limited(OpenTracingSpan delegate) implements Span { @Override - public Span tag(String key, String value) { - delegate.tag(key, value); - return this; - } + public Span tag(String key, String value) { + delegate.tag(key, value); + return this; + } - @Override - public Span tag(String key, Boolean value) { - delegate.tag(key, value); - return this; - } + @Override + public Span tag(String key, Boolean value) { + delegate.tag(key, value); + return this; + } - @Override - public Span tag(String key, Number value) { - delegate.tag(key, value); - return this; - } + @Override + public Span tag(String key, Number value) { + delegate.tag(key, value); + return this; + } - @Override - public void status(Status status) { - throw new UnsupportedOperationException(); - } + @Override + public void status(Status status) { + throw new UnsupportedOperationException(); + } - @Override - public SpanContext context() { - return delegate.context(); - } + @Override + public SpanContext context() { + return delegate.context(); + } - @Override - public void addEvent(String name, Map attributes) { - delegate.addEvent(name, attributes); - } + @Override + public void addEvent(String name, Map attributes) { + delegate.addEvent(name, attributes); + } - @Override - public void end() { - throw new UnsupportedOperationException(); - } + @Override + public void end() { + throw new UnsupportedOperationException(); + } - @Override - public void end(Throwable t) { - throw new UnsupportedOperationException(); - } + @Override + public void end(Throwable t) { + throw new UnsupportedOperationException(); + } - @Override - public Scope activate() { - throw new UnsupportedOperationException(); - } + @Override + public Scope activate() { + throw new UnsupportedOperationException(); + } - @Override - public Span baggage(String key, String value) { - delegate.baggage(key, value); - return this; - } + @Override + public Span baggage(String key, String value) { + delegate.baggage(key, value); + return this; + } - @Override - public Optional baggage(String key) { - return delegate.baggage(key); - } + @Override + public Optional baggage(String key) { + return delegate.baggage(key); + } - @Override - public WritableBaggage baggage() { - return delegate.baggage(); + @Override + public WritableBaggage baggage() { + return delegate.baggage(); + } + + @Override + public T unwrap(Class spanClass) { + if (spanClass.isInstance(this)) { + return spanClass.cast(this); } + return delegate.unwrap(spanClass); } + } } diff --git a/tracing/providers/zipkin/src/main/java/io/helidon/tracing/providers/zipkin/ZipkinSpan.java b/tracing/providers/zipkin/src/main/java/io/helidon/tracing/providers/zipkin/ZipkinSpan.java index 375784422ca..3aac6d4b933 100644 --- a/tracing/providers/zipkin/src/main/java/io/helidon/tracing/providers/zipkin/ZipkinSpan.java +++ b/tracing/providers/zipkin/src/main/java/io/helidon/tracing/providers/zipkin/ZipkinSpan.java @@ -297,5 +297,19 @@ public Optional baggage(String key) { public WritableBaggage baggage() { return baggage; } + + @Override + public T unwrap(Class spanClass) { + if (spanClass.isInstance(this)) { + return spanClass.cast(this); + } + Span span = delegateSpan.unwrap(); + if (spanClass.isInstance(span)) { + return spanClass.cast(span); + } + throw new IllegalArgumentException("Cannot provide an instance of " + spanClass.getName() + + ", Zipkin span is: " + delegateSpan.getClass().getName()); + + } } }