66package io .opentelemetry .maven ;
77
88import io .opentelemetry .api .OpenTelemetry ;
9- import io .opentelemetry .api .common .Attributes ;
10- import io .opentelemetry .api .common .AttributesBuilder ;
119import io .opentelemetry .api .trace .Tracer ;
12- import io .opentelemetry .api .trace .propagation .W3CTraceContextPropagator ;
1310import io .opentelemetry .context .propagation .ContextPropagators ;
14- import io .opentelemetry .exporter .otlp .trace .OtlpGrpcSpanExporter ;
15- import io .opentelemetry .exporter .otlp .trace .OtlpGrpcSpanExporterBuilder ;
1611import io .opentelemetry .maven .semconv .MavenOtelSemanticAttributes ;
1712import io .opentelemetry .sdk .OpenTelemetrySdk ;
13+ import io .opentelemetry .sdk .autoconfigure .OpenTelemetrySdkAutoConfiguration ;
1814import io .opentelemetry .sdk .common .CompletableResultCode ;
19- import io .opentelemetry .sdk .resources .Resource ;
20- import io .opentelemetry .sdk .trace .SdkTracerProvider ;
21- import io .opentelemetry .sdk .trace .export .BatchSpanProcessor ;
2215import io .opentelemetry .sdk .trace .export .SpanExporter ;
2316import io .opentelemetry .semconv .resource .attributes .ResourceAttributes ;
24- import java .time .Duration ;
2517import java .util .Map ;
2618import java .util .concurrent .TimeUnit ;
2719import org .apache .maven .rtinfo .RuntimeInformation ;
3628/**
3729 * Service to configure the {@link OpenTelemetry} instance.
3830 *
39- * <p>Mimic the <a
40- * href="https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure">OpenTelemetry
41- * SDK Autoconfigure</a> that can't be used due to class loading issues when declaring the Maven
42- * OpenTelemetry extension using the pom.xml {@code <extension>} declaration.
31+ * <p>Rely on the OpenTelemetry SDK AutoConfiguration extension. Parameters are passed as system
32+ * properties.
4333 *
44- * <p>The OpenTelemetry SDK Autoconfigure extension registers a <a
45- * href="https://github.com/open-telemetry/opentelemetry-java/blob/v1.6.0/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfiguration.java#L58">
46- * JVM shutdown hook on {@code SdkTracerProvider#close()}</a> that is incompatible with the fact
47- * that Maven extensions are unloaded before the JVM shuts down, requiring to close the trace
48- * provider earlier in the lifecycle of the Maven build, and causing {@link NoClassDefFoundError}
49- * when the shutdown hook is invoked.
34+ * <p>TODO: verify how we could use a composite {@link
35+ * io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties} combining the config passed by JVM
36+ * system properties and environment variables with overrides injected by the Otel Maven Extension
5037 */
5138@ Component (role = OpenTelemetrySdkService .class , hint = "opentelemetry-service" )
5239public final class OpenTelemetrySdkService implements Initializable , Disposable {
@@ -55,7 +42,7 @@ public final class OpenTelemetrySdkService implements Initializable, Disposable
5542
5643 @ Requirement private RuntimeInformation runtimeInformation ;
5744
58- private OpenTelemetry openTelemetry ;
45+ private OpenTelemetry openTelemetry = OpenTelemetry . noop () ;
5946 private OpenTelemetrySdk openTelemetrySdk ;
6047
6148 private Tracer tracer ;
@@ -64,6 +51,18 @@ public final class OpenTelemetrySdkService implements Initializable, Disposable
6451
6552 private boolean mojosInstrumentationEnabled ;
6653
54+ /**
55+ * Note: the JVM shutdown hook defined by the {@code
56+ * io.opentelemetry.sdk.autoconfigure.TracerProviderConfiguration} v1.7.0 does NOT cause
57+ * classloading issues even when Maven Plexus has unloaded the classes of the Otel Maven Extension
58+ * before the shutdown hook is invoked.
59+ *
60+ * <p>TODO create a feature request on {@code
61+ * io.opentelemetry.sdk.autoconfigure.TracerProviderConfiguration} to support the capability to
62+ * not register a JVM shutdown hook at initialization time (see
63+ * https://github.com/open-telemetry/opentelemetry-java/blob/v1.7.0/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfiguration.java#L58
64+ * )
65+ */
6766 @ Override
6867 public synchronized void dispose () {
6968 logger .debug ("OpenTelemetry: dispose OpenTelemetrySdkService..." );
@@ -87,78 +86,53 @@ public synchronized void dispose() {
8786 logger .debug ("OpenTelemetry: OpenTelemetrySdkService disposed" );
8887 }
8988
90- /** TODO add support for `OTEL_EXPORTER_OTLP_CERTIFICATE` */
9189 @ Override
9290 public void initialize () throws InitializationException {
9391 logger .debug ("OpenTelemetry: initialize OpenTelemetrySdkService..." );
94- // OTEL_EXPORTER_OTLP_ENDPOINT
95- String otlpEndpoint =
96- System .getProperty (
97- "otel.exporter.otlp.endpoint" , System .getenv ("OTEL_EXPORTER_OTLP_ENDPOINT" ));
98- if (StringUtils .isBlank (otlpEndpoint )) {
92+ if (StringUtils .isBlank (
93+ OtelUtils .getSystemPropertyOrEnvironmentVariable (
94+ "otel.exporter.otlp.endpoint" , "OTEL_EXPORTER_OTLP_ENDPOINT" , null ))) {
9995 logger .debug (
100- "OpenTelemetry: No -Dotel.exporter.otlp.endpoint property or OTEL_EXPORTER_OTLP_ENDPOINT environment variable found, use a NOOP tracer" );
101- this . openTelemetry = OpenTelemetry . noop ( );
96+ "OpenTelemetry: No -Dotel.exporter.otlp.endpoint property or OTEL_EXPORTER_OTLP_ENDPOINT "
97+ + "environment variable found, use a NOOP OpenTelemetry SDK" );
10298 } else {
103- // OtlpGrpcSpanExporterBuilder spanExporterBuilder = OtlpGrpcSpanExporter.builder();
104- OtlpGrpcSpanExporterBuilder spanExporterBuilder = OtlpGrpcSpanExporter .builder ();
105- spanExporterBuilder .setEndpoint (otlpEndpoint );
106-
107- // OTEL_EXPORTER_OTLP_HEADERS
108- String otlpExporterHeadersAsString =
109- System .getProperty (
110- "otel.exporter.otlp.headers" , System .getenv ("OTEL_EXPORTER_OTLP_HEADERS" ));
111- Map <String , String > otlpExporterHeaders =
112- OtelUtils .getCommaSeparatedMap (otlpExporterHeadersAsString );
113- otlpExporterHeaders .forEach (spanExporterBuilder ::addHeader );
114-
115- // OTEL_EXPORTER_OTLP_TIMEOUT
116- String otlpExporterTimeoutMillis =
117- System .getProperty (
118- "otel.exporter.otlp.timeout" , System .getenv ("OTEL_EXPORTER_OTLP_TIMEOUT" ));
119- if (StringUtils .isNotBlank (otlpExporterTimeoutMillis )) {
120- try {
121- spanExporterBuilder .setTimeout (
122- Duration .ofMillis (Long .parseLong (otlpExporterTimeoutMillis )));
123- } catch (NumberFormatException e ) {
124- logger .warn ("OpenTelemetry: Skip invalid OTLP timeout " + otlpExporterTimeoutMillis , e );
99+ {
100+ // Don't use a {@code io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider} to inject
101+ // Maven runtime attributes due to a classloading issue when loading the Maven OpenTelemetry
102+ // extension as a pom.xml {@code <extension>}.
103+ String initialCommaSeparatedAttributes =
104+ OtelUtils .getSystemPropertyOrEnvironmentVariable (
105+ "otel.resource.attributes" , "OTEL_RESOURCE_ATTRIBUTES" , "" );
106+ Map <String , String > attributes =
107+ OtelUtils .getCommaSeparatedMap (initialCommaSeparatedAttributes );
108+
109+ // service.name
110+ String serviceName =
111+ OtelUtils .getSystemPropertyOrEnvironmentVariable (
112+ "otel.service.name" , "OTEL_SERVICE_NAME" , null );
113+
114+ if (!attributes .containsKey (ResourceAttributes .SERVICE_NAME .getKey ())
115+ && StringUtils .isBlank (serviceName )) {
116+ // service.name is not defined in passed configuration, we define it
117+ attributes .put (
118+ ResourceAttributes .SERVICE_NAME .getKey (),
119+ MavenOtelSemanticAttributes .ServiceNameValues .SERVICE_NAME_VALUE );
120+ }
121+
122+ // service.version
123+ final String mavenVersion = this .runtimeInformation .getMavenVersion ();
124+ if (!attributes .containsKey (ResourceAttributes .SERVICE_VERSION .getKey ())) {
125+ attributes .put (ResourceAttributes .SERVICE_VERSION .getKey (), mavenVersion );
125126 }
126- }
127127
128- this .spanExporter = spanExporterBuilder .build ();
129-
130- // OTEL_RESOURCE_ATTRIBUTES
131- AttributesBuilder resourceAttributesBuilder = Attributes .builder ();
132- Resource mavenResource = getMavenResource ();
133- resourceAttributesBuilder .putAll (mavenResource .getAttributes ());
134- String otelResourceAttributesAsString =
135- System .getProperty ("otel.resource.attributes" , System .getenv ("OTEL_RESOURCE_ATTRIBUTES" ));
136- if (StringUtils .isNotBlank (otelResourceAttributesAsString )) {
137- Map <String , String > otelResourceAttributes =
138- OtelUtils .getCommaSeparatedMap (otelResourceAttributesAsString );
139- // see io.opentelemetry.sdk.autoconfigure.EnvironmentResource.getAttributes
140- otelResourceAttributes .forEach (resourceAttributesBuilder ::put );
128+ String newCommaSeparatedAttributes = OtelUtils .getCommaSeparatedString (attributes );
129+ logger .debug (
130+ "OpenTelemetry: Initial resource attributes: {}" , initialCommaSeparatedAttributes );
131+ logger .debug ("OpenTelemetry: Use resource attributes: {}" , newCommaSeparatedAttributes );
132+ System .setProperty ("otel.resource.attributes" , newCommaSeparatedAttributes );
141133 }
142- final Attributes resourceAttributes = resourceAttributesBuilder .build ();
143134
144- logger .debug (
145- "OpenTelemetry: Export OpenTelemetry traces to {} with attributes: {}" ,
146- otlpEndpoint ,
147- resourceAttributes );
148-
149- final BatchSpanProcessor batchSpanProcessor =
150- BatchSpanProcessor .builder (spanExporter ).build ();
151- SdkTracerProvider sdkTracerProvider =
152- SdkTracerProvider .builder ()
153- .setResource (Resource .create (resourceAttributes ))
154- .addSpanProcessor (batchSpanProcessor )
155- .build ();
156-
157- this .openTelemetrySdk =
158- OpenTelemetrySdk .builder ()
159- .setTracerProvider (sdkTracerProvider )
160- .setPropagators (ContextPropagators .create (W3CTraceContextPropagator .getInstance ()))
161- .build ();
135+ this .openTelemetrySdk = OpenTelemetrySdkAutoConfiguration .initialize (false );
162136 this .openTelemetry = this .openTelemetrySdk ;
163137 }
164138
@@ -180,21 +154,6 @@ public Tracer getTracer() {
180154 return tracer ;
181155 }
182156
183- /**
184- * Don't use a {@code io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider} due to classloading
185- * issue when loading the Maven OpenTelemetry extension as a pom.xml {@code <extension>}.
186- */
187- protected Resource getMavenResource () {
188- final String mavenVersion = this .runtimeInformation .getMavenVersion ();
189- final Attributes attributes =
190- Attributes .of (
191- ResourceAttributes .SERVICE_NAME ,
192- MavenOtelSemanticAttributes .ServiceNameValues .SERVICE_NAME_VALUE ,
193- ResourceAttributes .SERVICE_VERSION ,
194- mavenVersion );
195- return Resource .create (attributes );
196- }
197-
198157 /** Returns the {@link ContextPropagators} for this {@link OpenTelemetry}. */
199158 public ContextPropagators getPropagators () {
200159 return openTelemetry .getPropagators ();
0 commit comments