Skip to content

Commit 52a5a1b

Browse files
authored
Fix unwrap methods to return cast delegates rather than cast 'this' (#8298)
* Fix unwrap methods to return cast delegates rather than cast 'this' Signed-off-by: Tim Quinn <[email protected]> * Use a JUnit extension to set-up and shutdown OTel for tests * Review comments: add explicit type checking and exception throwing in unwrap implementations instead of simply delegating to Class.cast * Enhance unwrap to handle package-local and public implementations * Enhance unwrap for spans and no-op tracer also * Restore default implementations of unwrap --------- Signed-off-by: Tim Quinn <[email protected]>
1 parent 52d8a5d commit 52a5a1b

File tree

14 files changed

+241
-29
lines changed

14 files changed

+241
-29
lines changed

tracing/providers/opentelemetry/pom.xml

+16
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,20 @@
8989
<scope>test</scope>
9090
</dependency>
9191
</dependencies>
92+
93+
<build>
94+
<plugins>
95+
<plugin>
96+
<groupId>org.apache.maven.plugins</groupId>
97+
<artifactId>maven-surefire-plugin</artifactId>
98+
<configuration>
99+
<properties>
100+
<configurationParameters>
101+
junit.jupiter.extensions.autodetection.enabled = true
102+
</configurationParameters>
103+
</properties>
104+
</configuration>
105+
</plugin>
106+
</plugins>
107+
</build>
92108
</project>

tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpan.java

+12
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ public Optional<String> baggage(String key) {
111111
return Optional.ofNullable(baggage.getEntryValue(key));
112112
}
113113

114+
@Override
115+
public <T> T unwrap(Class<T> spanClass) {
116+
if (spanClass.isInstance(delegate)) {
117+
return spanClass.cast(delegate);
118+
}
119+
if (spanClass.isInstance(this)) {
120+
return spanClass.cast(this);
121+
}
122+
throw new IllegalArgumentException("Cannot provide an instance of " + spanClass.getName()
123+
+ ", telemetry span is: " + delegate.getClass().getName());
124+
}
125+
114126
// Check if OTEL Context is already available in Global Helidon Context.
115127
// If not – use Current context.
116128
private static Context getContext() {

tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpanBuilder.java

+12
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ public Span start(Instant instant) {
9797
return result;
9898
}
9999

100+
@Override
101+
public <T> T unwrap(Class<T> type) {
102+
if (type.isInstance(spanBuilder)) {
103+
return type.cast(spanBuilder);
104+
}
105+
if (type.isInstance(this)) {
106+
return type.cast(this);
107+
}
108+
throw new IllegalArgumentException("Cannot provide an instance of " + type.getName()
109+
+ ", span builder is: " + spanBuilder.getClass().getName());
110+
}
111+
100112
// used to set open telemetry context as parent, to be equivalent in function to
101113
// #parent(SpanContext)
102114
void parent(Context context) {

tracing/providers/opentelemetry/src/main/java/io/helidon/tracing/providers/opentelemetry/OpenTelemetrySpanContext.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tracing.providers.opentelemetry;
17+
18+
import org.junit.jupiter.api.extension.AfterAllCallback;
19+
import org.junit.jupiter.api.extension.BeforeAllCallback;
20+
import org.junit.jupiter.api.extension.Extension;
21+
import org.junit.jupiter.api.extension.ExtensionContext;
22+
23+
public class OtelTestsJunitExtension implements Extension, BeforeAllCallback, AfterAllCallback {
24+
25+
private static final String OTEL_AUTO_CONFIGURE_PROP = "otel.java.global-autoconfigure.enabled";
26+
private static final String OTEL_SDK_DISABLED_PROP = "otel.sdk.disabled";
27+
private String originalOtelSdkAutoConfiguredSetting;
28+
private String originalOtelSdkDisabledSetting;
29+
30+
@Override
31+
public void afterAll(ExtensionContext extensionContext) throws Exception {
32+
if (originalOtelSdkAutoConfiguredSetting != null) {
33+
System.setProperty(OTEL_AUTO_CONFIGURE_PROP, originalOtelSdkAutoConfiguredSetting);
34+
}
35+
if (originalOtelSdkDisabledSetting != null) {
36+
System.setProperty(OTEL_SDK_DISABLED_PROP, originalOtelSdkDisabledSetting);
37+
}
38+
}
39+
40+
@Override
41+
public void beforeAll(ExtensionContext extensionContext) throws Exception {
42+
originalOtelSdkAutoConfiguredSetting = System.setProperty(OTEL_AUTO_CONFIGURE_PROP, "true");
43+
originalOtelSdkDisabledSetting = System.setProperty(OTEL_SDK_DISABLED_PROP, "false");
44+
}
45+
}

tracing/providers/opentelemetry/src/test/java/io/helidon/tracing/providers/opentelemetry/TestSpanAndBaggage.java

-23
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
import io.helidon.tracing.SpanContext;
2727
import io.helidon.tracing.Tracer;
2828

29-
import org.junit.jupiter.api.AfterAll;
30-
import org.junit.jupiter.api.BeforeAll;
3129
import org.junit.jupiter.api.Test;
3230

3331
import static org.hamcrest.MatcherAssert.assertThat;
@@ -37,27 +35,6 @@
3735

3836
class TestSpanAndBaggage {
3937

40-
private static final String OTEL_AUTO_CONFIGURE_PROP = "otel.java.global-autoconfigure.enabled";
41-
private static final String OTEL_SDK_DISABLED_PROP = "otel.sdk.disabled";
42-
private static String originalOtelSdkAutoConfiguredSetting;
43-
private static String originalOtelSdkDisabledSetting;
44-
45-
@BeforeAll
46-
static void init() {
47-
originalOtelSdkAutoConfiguredSetting = System.setProperty(OTEL_AUTO_CONFIGURE_PROP, "true");
48-
originalOtelSdkDisabledSetting = System.setProperty(OTEL_SDK_DISABLED_PROP, "false");
49-
}
50-
51-
@AfterAll
52-
static void wrapup() {
53-
if (originalOtelSdkAutoConfiguredSetting != null) {
54-
System.setProperty(OTEL_AUTO_CONFIGURE_PROP, originalOtelSdkAutoConfiguredSetting);
55-
}
56-
if (originalOtelSdkDisabledSetting != null) {
57-
System.setProperty(OTEL_SDK_DISABLED_PROP, originalOtelSdkDisabledSetting);
58-
}
59-
}
60-
6138
@Test
6239
void testActiveSpanScopeWithoutBaggage() {
6340
Tracer tracer = Tracer.global();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tracing.providers.opentelemetry;
17+
18+
19+
import io.opentelemetry.api.trace.Span;
20+
import io.opentelemetry.api.trace.SpanBuilder;
21+
import io.opentelemetry.api.trace.Tracer;
22+
import org.junit.jupiter.api.Test;
23+
24+
import static org.hamcrest.MatcherAssert.assertThat;
25+
import static org.hamcrest.Matchers.instanceOf;
26+
27+
class TestUnwrap {
28+
29+
@Test
30+
void testTracer() {
31+
var tracer = io.helidon.tracing.Tracer.global();
32+
assertThat("Tracer unwrapped",
33+
tracer.unwrap(Tracer.class),
34+
instanceOf(Tracer.class));
35+
}
36+
37+
@Test
38+
void testSpanAndSpanBuilder() {
39+
var tracer = io.helidon.tracing.Tracer.global();
40+
var spanBuilder = tracer.spanBuilder("test1");
41+
assertThat("Span builder unwrapped",
42+
spanBuilder.unwrap(SpanBuilder.class),
43+
instanceOf(SpanBuilder.class));
44+
45+
var span = spanBuilder.start();
46+
assertThat("Span unwrapped",
47+
span.unwrap(Span.class),
48+
instanceOf(Span.class));
49+
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# Copyright (c) 2024 Oracle and/or its affiliates.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
io.helidon.tracing.providers.opentelemetry.OtelTestsJunitExtension

tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingContext.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingSpan.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -114,9 +114,12 @@ public Optional<String> baggage(String key) {
114114

115115
@Override
116116
public <T> T unwrap(Class<T> spanClass) {
117-
if (spanClass.isAssignableFrom(delegate.getClass())) {
117+
if (spanClass.isInstance(delegate)) {
118118
return spanClass.cast(delegate);
119119
}
120+
if (spanClass.isInstance(this)) {
121+
return spanClass.cast(this);
122+
}
120123
throw new IllegalArgumentException("Cannot provide an instance of " + spanClass.getName()
121124
+ ", open tracing span is: " + delegate.getClass().getName());
122125
}

tracing/providers/opentracing/src/main/java/io/helidon/tracing/providers/opentracing/OpenTracingSpanBuilder.java

+12
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,16 @@ public Span start(Instant instant) {
9999
}
100100
return result;
101101
}
102+
103+
@Override
104+
public <T> T unwrap(Class<T> type) {
105+
if (type.isInstance(delegate)) {
106+
return type.cast(delegate);
107+
}
108+
if (type.isInstance(this)) {
109+
return type.cast(this);
110+
}
111+
throw new IllegalArgumentException("Cannot provide an instance of " + type.getName()
112+
+ ", span builder is: " + delegate.getClass().getName());
113+
}
102114
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.helidon.tracing.providers.opentracing;
17+
18+
import io.opentracing.Span;
19+
import io.opentracing.Tracer;
20+
import org.junit.jupiter.api.Test;
21+
22+
import static org.hamcrest.MatcherAssert.assertThat;
23+
import static org.hamcrest.Matchers.instanceOf;
24+
25+
class TestUnwrap {
26+
27+
@Test
28+
void testTracer() {
29+
var tracer = io.helidon.tracing.Tracer.global();
30+
assertThat("Tracer unwrapped",
31+
tracer.unwrap(Tracer.class),
32+
instanceOf(Tracer.class));
33+
}
34+
35+
@Test
36+
void testSpanAndSpanBuilder() {
37+
var tracer = io.helidon.tracing.Tracer.global();
38+
var spanBuilder = tracer.spanBuilder("test1");
39+
assertThat("Span builder unwrapped",
40+
spanBuilder.unwrap(Tracer.SpanBuilder.class),
41+
instanceOf(Tracer.SpanBuilder.class));
42+
43+
var span = spanBuilder.start();
44+
assertThat("Span unwrapped",
45+
span.unwrap(Span.class),
46+
instanceOf(Span.class));
47+
48+
}
49+
}

tracing/tracing/src/main/java/io/helidon/tracing/NoOpTracer.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -56,6 +56,15 @@ public void inject(io.helidon.tracing.SpanContext spanContext,
5656

5757
}
5858

59+
@Override
60+
public <T> T unwrap(Class<T> tracerClass) {
61+
if (tracerClass.isInstance(this)) {
62+
return tracerClass.cast(this);
63+
}
64+
throw new IllegalArgumentException("Cannot provide an instance of " + tracerClass.getName()
65+
+ ", tracer is: " + getClass().getName());
66+
}
67+
5968
private static class Builder implements Span.Builder<Builder> {
6069
@Override
6170
public Span build() {
@@ -91,6 +100,11 @@ public Builder tag(String key, Number value) {
91100
public Span start(Instant instant) {
92101
return SPAN;
93102
}
103+
104+
@Override
105+
public <T> T unwrap(Class<T> type) {
106+
return type.cast(this);
107+
}
94108
}
95109

96110
private static class Span implements io.helidon.tracing.Span {
@@ -146,6 +160,11 @@ public Span baggage(String key, String value) {
146160
public Optional<String> baggage(String key) {
147161
return Optional.empty();
148162
}
163+
164+
@Override
165+
public <T> T unwrap(Class<T> spanClass) {
166+
return spanClass.cast(this);
167+
}
149168
}
150169

151170
private static class SpanContext implements io.helidon.tracing.SpanContext {

tracing/tracing/src/main/java/io/helidon/tracing/Tracer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022 Oracle and/or its affiliates.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)