Skip to content

Commit 536cf9f

Browse files
committed
Create a bridge to instanciate StandardComponentId objects
1 parent 1dadceb commit 536cf9f

File tree

8 files changed

+174
-27
lines changed

8 files changed

+174
-27
lines changed

bom/application/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<resteasy-microprofile.version>3.0.1.Final</resteasy-microprofile.version>
3030
<resteasy-spring-web.version>3.2.0.Final</resteasy-spring-web.version>
3131
<resteasy.version>6.2.12.Final</resteasy.version>
32-
<opentelemetry-instrumentation.version>2.15.0-alpha</opentelemetry-instrumentation.version> <!-- OTel SDk 1.49.0-->
32+
<opentelemetry-instrumentation.version>2.17.1-alpha</opentelemetry-instrumentation.version> <!-- OTel SDk 1.51.0-->
3333
<opentelemetry-semconv.version>1.32.0-alpha</opentelemetry-semconv.version>
3434
<quarkus-http.version>5.3.5</quarkus-http.version>
3535
<micrometer.version>1.14.7</micrometer.version><!-- keep in sync with hdrhistogram: https://central.sonatype.com/artifact/io.micrometer/micrometer-core -->

extensions/opentelemetry/deployment/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
<groupId>io.quarkus</groupId>
3030
<artifactId>quarkus-arc-deployment</artifactId>
3131
</dependency>
32+
<dependency>
33+
<groupId>io.quarkus.gizmo</groupId>
34+
<artifactId>gizmo2</artifactId>
35+
</dependency>
3236
<dependency>
3337
<groupId>io.quarkus</groupId>
3438
<artifactId>quarkus-vertx-deployment</artifactId>

extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.function.BooleanSupplier;
88
import java.util.logging.Level;
99

10+
import jakarta.enterprise.context.ApplicationScoped;
1011
import jakarta.enterprise.inject.Instance;
1112
import jakarta.inject.Singleton;
1213

@@ -15,22 +16,31 @@
1516
import org.jboss.jandex.DotName;
1617
import org.jboss.jandex.ParameterizedType;
1718
import org.jboss.jandex.Type;
19+
import org.objectweb.asm.Opcodes;
1820

21+
import io.opentelemetry.sdk.internal.StandardComponentId;
1922
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
2023
import io.opentelemetry.sdk.metrics.export.MetricExporter;
2124
import io.opentelemetry.sdk.trace.SpanProcessor;
2225
import io.opentelemetry.sdk.trace.export.SpanExporter;
2326
import io.quarkus.arc.deployment.BeanDiscoveryFinishedBuildItem;
27+
import io.quarkus.arc.deployment.GeneratedBeanBuildItem;
28+
import io.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor;
2429
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
2530
import io.quarkus.arc.deployment.ValidationPhaseBuildItem;
31+
import io.quarkus.arc.processor.MethodDescriptors;
2632
import io.quarkus.deployment.annotations.*;
2733
import io.quarkus.deployment.annotations.Record;
2834
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
2935
import io.quarkus.deployment.builditem.LogCategoryBuildItem;
3036
import io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem;
37+
import io.quarkus.gizmo.ClassCreator;
38+
import io.quarkus.gizmo.MethodCreator;
39+
import io.quarkus.gizmo.MethodDescriptor;
3140
import io.quarkus.opentelemetry.runtime.config.build.OTelBuildConfig;
3241
import io.quarkus.opentelemetry.runtime.config.build.exporter.OtlpExporterBuildConfig;
3342
import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterConfigBuilder;
43+
import io.quarkus.opentelemetry.runtime.exporter.otlp.ExporterBridge;
3444
import io.quarkus.opentelemetry.runtime.exporter.otlp.OTelExporterRecorder;
3545
import io.quarkus.opentelemetry.runtime.exporter.otlp.tracing.LateBoundSpanProcessor;
3646
import io.quarkus.runtime.configuration.ConfigurationException;
@@ -44,6 +54,7 @@ public class OtlpExporterProcessor {
4454
private static final DotName METRIC_EXPORTER = DotName.createSimple(MetricExporter.class.getName());
4555
private static final DotName LOG_RECORD_EXPORTER = DotName.createSimple(LogRecordExporter.class.getName());
4656
private static final DotName OKHTTP_INTERCEPTOR = DotName.createSimple("okhttp3.Interceptor");
57+
private static final String BRIDGE_NAME = "io.opentelemetry.sdk.internal.StandardComponentIdBridge";
4758

4859
static class OtlpTracingExporterEnabled implements BooleanSupplier {
4960
OtlpExporterBuildConfig exportBuildConfig;
@@ -109,6 +120,58 @@ private boolean isTracesOtlp(OTelBuildConfig otelBuildConfig) {
109120
}
110121
}
111122

123+
/**
124+
* Make constructor public for io.opentelemetry.sdk.internal.StandardComponentId
125+
*
126+
* <pre>
127+
* @ApplicationScoped
128+
* public class StandardComponentIdBridge implements ExporterBridge {
129+
* public StandardComponentIdBridge() {
130+
* }
131+
*
132+
* public StandardComponentId createStandardComponentId(StandardComponentId.ExporterType standardType) {
133+
* return new StandardComponentId(standardType);
134+
* }
135+
* }
136+
* </pre>
137+
*/
138+
@BuildStep
139+
void generateBridgeService(BuildProducer<GeneratedBeanBuildItem> generatedBeanClasses) {
140+
// Create a ClassOutput instance
141+
GeneratedBeanGizmoAdaptor gizmoAdaptor = new GeneratedBeanGizmoAdaptor(
142+
generatedBeanClasses);
143+
144+
try (ClassCreator classCreator = ClassCreator.builder()
145+
.className(BRIDGE_NAME)
146+
.interfaces(ExporterBridge.class)
147+
.classOutput(gizmoAdaptor)
148+
.build()) {
149+
150+
classCreator.addAnnotation(ApplicationScoped.class);
151+
MethodCreator constructor = classCreator.getMethodCreator("<init>", "V");
152+
// Invoke super()
153+
constructor.invokeSpecialMethod(
154+
MethodDescriptors.OBJECT_CONSTRUCTOR,
155+
constructor.getThis());
156+
constructor.returnValue(null);
157+
158+
// public static StandardComponentId createStandardComponentId(StandardComponentId.ExporterType standardType)
159+
try (MethodCreator method = classCreator.getMethodCreator("createStandardComponentId",
160+
StandardComponentId.class,
161+
StandardComponentId.ExporterType.class)) {
162+
method.setModifiers(Opcodes.ACC_PUBLIC);
163+
var in = method.getMethodParam(0);
164+
165+
// calls package-private constructor: StandardComponentId(ExporterType standardType)
166+
MethodDescriptor target = MethodDescriptor.ofConstructor(
167+
StandardComponentId.class, StandardComponentId.ExporterType.class);
168+
169+
var result = method.newInstance(target, in);
170+
method.returnValue(result);
171+
}
172+
}
173+
}
174+
112175
@BuildStep
113176
void logging(BuildProducer<LogCategoryBuildItem> log) {
114177
// Reduce the log level of the exporters because it's too much, and we do log important things ourselves.
@@ -156,6 +219,7 @@ void createSpanProcessor(OTelExporterRecorder recorder,
156219
.addInjectionPoint(ParameterizedType.create(DotName.createSimple(Instance.class),
157220
new Type[] { ClassType.create(DotName.createSimple(SpanExporter.class.getName())) }, null))
158221
.addInjectionPoint(ClassType.create(DotName.createSimple(TlsConfigurationRegistry.class)))
222+
.addInjectionPoint(ClassType.create(DotName.createSimple(ExporterBridge.class)))
159223
.createWith(recorder.spanProcessorForOtlp(vertxBuildItem.getVertx()))
160224
.done());
161225
}
@@ -190,6 +254,7 @@ void createMetricsExporterProcessor(
190254
.addInjectionPoint(ParameterizedType.create(DotName.createSimple(Instance.class),
191255
new Type[] { ClassType.create(DotName.createSimple(MetricExporter.class.getName())) }, null))
192256
.addInjectionPoint(ClassType.create(DotName.createSimple(TlsConfigurationRegistry.class)))
257+
.addInjectionPoint(ClassType.create(DotName.createSimple(ExporterBridge.class)))
193258
.createWith(recorder.createMetricExporter(vertxBuildItem.getVertx()))
194259
.done());
195260
}
@@ -224,6 +289,7 @@ void createLogRecordExporterProcessor(
224289
.addInjectionPoint(ParameterizedType.create(DotName.createSimple(Instance.class),
225290
new Type[] { ClassType.create(DotName.createSimple(LogRecordExporter.class.getName())) }, null))
226291
.addInjectionPoint(ClassType.create(DotName.createSimple(TlsConfigurationRegistry.class)))
292+
.addInjectionPoint(ClassType.create(DotName.createSimple(ExporterBridge.class)))
227293
.createWith(recorder.createLogRecordExporter(vertxBuildItem.getVertx()))
228294
.done());
229295
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.quarkus.opentelemetry.deployment.exporter.otlp;
2+
3+
import static io.opentelemetry.sdk.internal.StandardComponentId.ExporterType.OTLP_HTTP_SPAN_EXPORTER;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
7+
import jakarta.inject.Inject;
8+
9+
import org.jboss.shrinkwrap.api.ShrinkWrap;
10+
import org.jboss.shrinkwrap.api.asset.StringAsset;
11+
import org.jboss.shrinkwrap.api.spec.JavaArchive;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.extension.RegisterExtension;
14+
15+
import io.opentelemetry.sdk.internal.ComponentId;
16+
import io.opentelemetry.sdk.internal.StandardComponentId;
17+
import io.quarkus.opentelemetry.deployment.common.exporter.TestSpanExporter;
18+
import io.quarkus.opentelemetry.deployment.common.exporter.TestSpanExporterProvider;
19+
import io.quarkus.opentelemetry.runtime.exporter.otlp.ExporterBridge;
20+
import io.quarkus.test.QuarkusUnitTest;
21+
22+
public class ExportBridgeTest {
23+
@RegisterExtension
24+
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
25+
.setArchiveProducer(
26+
() -> ShrinkWrap.create(JavaArchive.class)
27+
.addClasses(ExporterBridge.class, StandardComponentId.class, ComponentId.class)
28+
.addClasses(TestSpanExporter.class, TestSpanExporterProvider.class)
29+
.addAsResource(new StringAsset(TestSpanExporterProvider.class.getCanonicalName()),
30+
"META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider"))
31+
.withConfigurationResource("resource-config/application-no-metrics.properties");
32+
33+
@Inject
34+
ExporterBridge bridge;
35+
36+
@Test
37+
void testBridge() {
38+
StandardComponentId standardComponentId = bridge.createStandardComponentId(OTLP_HTTP_SPAN_EXPORTER);
39+
assertNotNull(standardComponentId);
40+
assertEquals(OTLP_HTTP_SPAN_EXPORTER, standardComponentId.getStandardType());
41+
}
42+
}

extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterConfigTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88
import org.junit.jupiter.api.Test;
99
import org.junit.jupiter.api.extension.RegisterExtension;
1010

11+
import io.opentelemetry.sdk.internal.ComponentId;
12+
import io.opentelemetry.sdk.internal.StandardComponentId;
1113
import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterRuntimeConfig;
14+
import io.quarkus.opentelemetry.runtime.exporter.otlp.ExporterBridge;
1215
import io.quarkus.test.QuarkusUnitTest;
1316

1417
public class OtlpExporterConfigTest {
1518
@RegisterExtension
1619
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
17-
.withEmptyApplication()
20+
.withApplicationRoot((jar) -> jar
21+
.addClasses(ExporterBridge.class, StandardComponentId.class, ComponentId.class))
1822
.overrideConfigKey("quarkus.otel.traces.exporter", "cdi")
1923
.overrideConfigKey("quarkus.otel.exporter.otlp.protocol", "wrong")
2024
.overrideConfigKey("quarkus.otel.exporter.otlp.traces.protocol", "http/protobuf")

extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/traces/OpenTelemetrySpanSecurityEventsTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
import org.junit.jupiter.api.extension.RegisterExtension;
2020

2121
import io.opentelemetry.api.common.AttributeKey;
22+
import io.opentelemetry.sdk.internal.ComponentId;
23+
import io.opentelemetry.sdk.internal.StandardComponentId;
2224
import io.quarkus.opentelemetry.deployment.common.exporter.TestSpanExporter;
2325
import io.quarkus.opentelemetry.deployment.common.exporter.TestSpanExporterProvider;
26+
import io.quarkus.opentelemetry.runtime.exporter.otlp.ExporterBridge;
2427
import io.quarkus.opentelemetry.runtime.tracing.security.SecurityEventUtil;
2528
import io.quarkus.security.spi.runtime.AbstractSecurityEvent;
2629
import io.quarkus.security.spi.runtime.AuthenticationFailureEvent;
@@ -37,6 +40,7 @@ public class OpenTelemetrySpanSecurityEventsTest {
3740
() -> ShrinkWrap.create(JavaArchive.class)
3841
.addClasses(TestSpanExporter.class, TestSpanExporterProvider.class, EventsResource.class,
3942
CustomSecurityEvent.class)
43+
.addClasses(ExporterBridge.class, StandardComponentId.class, ComponentId.class)
4044
.addAsResource(new StringAsset("""
4145
quarkus.otel.security-events.enabled=true
4246
quarkus.otel.metrics.exporter=none
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.quarkus.opentelemetry.runtime.exporter.otlp;
2+
3+
import io.opentelemetry.sdk.internal.StandardComponentId;
4+
5+
/**
6+
* Bytecode implementation living in the processor.
7+
*/
8+
public interface ExporterBridge {
9+
StandardComponentId createStandardComponentId(StandardComponentId.ExporterType standardType);
10+
}

0 commit comments

Comments
 (0)