From 21d4a016f464211462bb27443987fcb97ce06edf Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 11 Jul 2025 12:06:05 +0200 Subject: [PATCH 01/44] gcp auth --- gcp-auth-extension/build.gradle.kts | 1 + ...thAutoConfigurationCustomizerProvider.java | 19 +- .../gcp/auth/GcpAuthCustomizerProvider.java | 191 ++++++++++++++++++ 3 files changed, 204 insertions(+), 7 deletions(-) create mode 100644 gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java diff --git a/gcp-auth-extension/build.gradle.kts b/gcp-auth-extension/build.gradle.kts index f81e5e521..d606782b0 100644 --- a/gcp-auth-extension/build.gradle.kts +++ b/gcp-auth-extension/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { compileOnly("com.google.auto.service:auto-service-annotations") compileOnly("io.opentelemetry:opentelemetry-api") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") compileOnly("io.opentelemetry:opentelemetry-exporter-otlp") // Only dependencies added to `implementation` configuration will be picked up by Shadow plugin diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index 1de583029..f3ea7b206 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -96,12 +96,7 @@ public class GcpAuthAutoConfigurationCustomizerProvider */ @Override public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { - GoogleCredentials credentials; - try { - credentials = GoogleCredentials.getApplicationDefault(); - } catch (IOException e) { - throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e); - } + GoogleCredentials credentials = getCredentials(); autoConfiguration .addSpanExporterCustomizer( (spanExporter, configProperties) -> @@ -112,6 +107,16 @@ public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { .addResourceCustomizer(GcpAuthAutoConfigurationCustomizerProvider::customizeResource); } + static GoogleCredentials getCredentials() { + GoogleCredentials credentials; + try { + credentials = GoogleCredentials.getApplicationDefault(); + } catch (IOException e) { + throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e); + } + return credentials; + } + @Override public int order() { return Integer.MAX_VALUE - 1; @@ -193,7 +198,7 @@ private static MetricExporter addAuthorizationHeaders( return exporter; } - private static Map getRequiredHeaderMap( + static Map getRequiredHeaderMap( GoogleCredentials credentials, ConfigProperties configProperties) { Map> gcpHeaders; try { diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java new file mode 100644 index 000000000..a06008562 --- /dev/null +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -0,0 +1,191 @@ +package io.opentelemetry.contrib.gcp.auth; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auto.service.AutoService; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchLogRecordProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LoggerProviderModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MeterProviderModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReaderModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpGrpcExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpGrpcMetricExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpHttpExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpHttpMetricExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PushMetricExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleLogRecordProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@AutoService(DeclarativeConfigurationCustomizerProvider.class) +public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { + + @Override + public void customize(DeclarativeConfigurationCustomizer customizer) { + customizer.addModelCustomizer( + model -> { + GoogleCredentials credentials = GcpAuthAutoConfigurationCustomizerProvider.getCredentials(); + // todo pass config bridge + Map headerMap = GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap( + credentials, null); + customizeMeter(model, headerMap); + // todo are loggers supported now (not covered in old variant)? + customizeLogger(model, headerMap); + customizeTracer(model, headerMap); + + return model; + }); + } + + private void customizeMeter(OpenTelemetryConfigurationModel model, + Map headerMap) { + MeterProviderModel meterProvider = model.getMeterProvider(); + if (meterProvider == null) { + return; + } + + for (MetricReaderModel reader : meterProvider.getReaders()) { + if (reader.getPeriodic() != null) { + addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), + headerMap); + } + } + } + + private List> meterModelHeaders( + PushMetricExporterModel exporter) { + ArrayList> list = new ArrayList<>(); + if (exporter == null) { + return list; + } + OtlpGrpcMetricExporterModel grpc = exporter.getOtlpGrpc(); + if (grpc != null) { + list.add(grpc.getHeaders()); + } + OtlpHttpMetricExporterModel http = exporter.getOtlpHttp(); + if (http != null) { + list.add(http.getHeaders()); + } + return list; + } + + private void customizeLogger(OpenTelemetryConfigurationModel model, + Map headerMap) { + LoggerProviderModel loggerProvider = model.getLoggerProvider(); + if (loggerProvider == null) { + return; + } + for (LogRecordProcessorModel processor : loggerProvider.getProcessors()) { + BatchLogRecordProcessorModel batch = processor.getBatch(); + if (batch != null) { + addAuth(logRecordModelHeaders(batch.getExporter()), + headerMap); + } + SimpleLogRecordProcessorModel simple = processor.getSimple(); + if (simple != null) { + addAuth(logRecordModelHeaders(simple.getExporter()), + headerMap); + } + } + } + + private List> logRecordModelHeaders( + LogRecordExporterModel exporter) { + ArrayList> list = new ArrayList<>(); + + if (exporter == null) { + return list; + } + OtlpGrpcExporterModel grpc = exporter.getOtlpGrpc(); + if (grpc != null) { + list.add(grpc.getHeaders()); + } + OtlpHttpExporterModel http = exporter.getOtlpHttp(); + if (http != null) { + list.add(http.getHeaders()); + } + return list; + } + + private void customizeTracer(OpenTelemetryConfigurationModel model, + Map headerMap) { + TracerProviderModel tracerProvider = model.getTracerProvider(); + if (tracerProvider == null) { + return; + } + + // todo here we would want a simplified version of the declarative config bridge + // https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/DeclarativeConfigPropertiesBridge.java +// googleNode(model) + +// if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { + // todo +// String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; +// logger.log( +// Level.WARNING, +// "GCP Authentication Extension is not configured for signal type: {0}. {1}", +// params); +// return; +// } + + for (SpanProcessorModel processor : tracerProvider.getProcessors()) { + BatchSpanProcessorModel batch = processor.getBatch(); + if (batch != null) { + addAuth(spanExporterModelHeaders(batch.getExporter()), + headerMap); + } + SimpleSpanProcessorModel simple = processor.getSimple(); + if (simple != null) { + addAuth(spanExporterModelHeaders(simple.getExporter()), + headerMap); + } + } + } + + private void googleNode(OpenTelemetryConfigurationModel model) { + // todo use declarative config bridge + } + + private List> spanExporterModelHeaders( + SpanExporterModel exporter) { + ArrayList> list = new ArrayList<>(); + + if (exporter == null) { + return list; + } + OtlpGrpcExporterModel grpc = exporter.getOtlpGrpc(); + if (grpc != null) { + list.add(grpc.getHeaders()); + } + OtlpHttpExporterModel http = exporter.getOtlpHttp(); + if (http != null) { + list.add(http.getHeaders()); + } + return list; + } + + private void addAuth( + List> headerConsumers, Map headerMap) { + headerConsumers.forEach( + headers -> addHeaders(headers, headerMap)); + } + + private void addHeaders(List headers, Map add) { + add.forEach( + (key, value) -> { + if (headers.stream().noneMatch(header -> key.equals(header.getName()))) { + headers.add(new NameStringValuePairModel().withName(key).withValue(value)); + } + }); + } +} From f9eb67b8cc6d59a1fcea84aad704133726c7284b Mon Sep 17 00:00:00 2001 From: otelbot <197425009+otelbot@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:07:55 +0000 Subject: [PATCH 02/44] ./gradlew spotlessApply --- ...thAutoConfigurationCustomizerProvider.java | 2 +- .../gcp/auth/GcpAuthCustomizerProvider.java | 67 +++++++++---------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index f3ea7b206..b06359c38 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -107,7 +107,7 @@ public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { .addResourceCustomizer(GcpAuthAutoConfigurationCustomizerProvider::customizeResource); } - static GoogleCredentials getCredentials() { + static GoogleCredentials getCredentials() { GoogleCredentials credentials; try { credentials = GoogleCredentials.getApplicationDefault(); diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index a06008562..e2512aab6 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.contrib.gcp.auth; import com.google.auth.oauth2.GoogleCredentials; @@ -34,10 +39,11 @@ public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustom public void customize(DeclarativeConfigurationCustomizer customizer) { customizer.addModelCustomizer( model -> { - GoogleCredentials credentials = GcpAuthAutoConfigurationCustomizerProvider.getCredentials(); + GoogleCredentials credentials = + GcpAuthAutoConfigurationCustomizerProvider.getCredentials(); // todo pass config bridge - Map headerMap = GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap( - credentials, null); + Map headerMap = + GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap(credentials, null); customizeMeter(model, headerMap); // todo are loggers supported now (not covered in old variant)? customizeLogger(model, headerMap); @@ -47,8 +53,8 @@ public void customize(DeclarativeConfigurationCustomizer customizer) { }); } - private void customizeMeter(OpenTelemetryConfigurationModel model, - Map headerMap) { + private void customizeMeter( + OpenTelemetryConfigurationModel model, Map headerMap) { MeterProviderModel meterProvider = model.getMeterProvider(); if (meterProvider == null) { return; @@ -56,14 +62,12 @@ private void customizeMeter(OpenTelemetryConfigurationModel model, for (MetricReaderModel reader : meterProvider.getReaders()) { if (reader.getPeriodic() != null) { - addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), - headerMap); + addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), headerMap); } } } - private List> meterModelHeaders( - PushMetricExporterModel exporter) { + private List> meterModelHeaders(PushMetricExporterModel exporter) { ArrayList> list = new ArrayList<>(); if (exporter == null) { return list; @@ -79,8 +83,8 @@ private List> meterModelHeaders( return list; } - private void customizeLogger(OpenTelemetryConfigurationModel model, - Map headerMap) { + private void customizeLogger( + OpenTelemetryConfigurationModel model, Map headerMap) { LoggerProviderModel loggerProvider = model.getLoggerProvider(); if (loggerProvider == null) { return; @@ -88,13 +92,11 @@ private void customizeLogger(OpenTelemetryConfigurationModel model, for (LogRecordProcessorModel processor : loggerProvider.getProcessors()) { BatchLogRecordProcessorModel batch = processor.getBatch(); if (batch != null) { - addAuth(logRecordModelHeaders(batch.getExporter()), - headerMap); + addAuth(logRecordModelHeaders(batch.getExporter()), headerMap); } SimpleLogRecordProcessorModel simple = processor.getSimple(); if (simple != null) { - addAuth(logRecordModelHeaders(simple.getExporter()), - headerMap); + addAuth(logRecordModelHeaders(simple.getExporter()), headerMap); } } } @@ -117,8 +119,8 @@ private List> logRecordModelHeaders( return list; } - private void customizeTracer(OpenTelemetryConfigurationModel model, - Map headerMap) { + private void customizeTracer( + OpenTelemetryConfigurationModel model, Map headerMap) { TracerProviderModel tracerProvider = model.getTracerProvider(); if (tracerProvider == null) { return; @@ -126,28 +128,26 @@ private void customizeTracer(OpenTelemetryConfigurationModel model, // todo here we would want a simplified version of the declarative config bridge // https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/DeclarativeConfigPropertiesBridge.java -// googleNode(model) - -// if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { - // todo -// String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; -// logger.log( -// Level.WARNING, -// "GCP Authentication Extension is not configured for signal type: {0}. {1}", -// params); -// return; -// } + // googleNode(model) + + // if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { + // todo + // String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; + // logger.log( + // Level.WARNING, + // "GCP Authentication Extension is not configured for signal type: {0}. {1}", + // params); + // return; + // } for (SpanProcessorModel processor : tracerProvider.getProcessors()) { BatchSpanProcessorModel batch = processor.getBatch(); if (batch != null) { - addAuth(spanExporterModelHeaders(batch.getExporter()), - headerMap); + addAuth(spanExporterModelHeaders(batch.getExporter()), headerMap); } SimpleSpanProcessorModel simple = processor.getSimple(); if (simple != null) { - addAuth(spanExporterModelHeaders(simple.getExporter()), - headerMap); + addAuth(spanExporterModelHeaders(simple.getExporter()), headerMap); } } } @@ -176,8 +176,7 @@ private List> spanExporterModelHeaders( private void addAuth( List> headerConsumers, Map headerMap) { - headerConsumers.forEach( - headers -> addHeaders(headers, headerMap)); + headerConsumers.forEach(headers -> addHeaders(headers, headerMap)); } private void addHeaders(List headers, Map add) { From 35fc448083df63e64484600e381114ab6feef55b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 17:25:05 +0200 Subject: [PATCH 03/44] copy declarative config bridge from instrumentation --- declarative-config-bridge/build.gradle.kts | 17 ++ .../autoconfigure/ConfigPropertiesUtil.java | 55 ++++++ .../DeclarativeConfigPropertiesBridge.java | 158 ++++++++++++++++++ .../ConfigPropertiesUtilTest.java | 87 ++++++++++ ...DeclarativeConfigPropertiesBridgeTest.java | 137 +++++++++++++++ settings.gradle.kts | 1 + 6 files changed, 455 insertions(+) create mode 100644 declarative-config-bridge/build.gradle.kts create mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java create mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java create mode 100644 declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java create mode 100644 declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java diff --git a/declarative-config-bridge/build.gradle.kts b/declarative-config-bridge/build.gradle.kts new file mode 100644 index 000000000..66fb4658b --- /dev/null +++ b/declarative-config-bridge/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id("otel.java-conventions") + id("otel.publish-conventions") +} + +description = "OpenTelemetry extension that provides a bridge for declarative configuration." +otelJava.moduleName.set("io.opentelemetry.contrib.sdk.declarative.config.bridge") + +dependencies { + // We use `compileOnly` dependency because during runtime all necessary classes are provided by + // javaagent itself. + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") +} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java new file mode 100644 index 000000000..af6cc6397 --- /dev/null +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -0,0 +1,55 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sdk.autoconfigure; + +import io.opentelemetry.api.incubator.config.ConfigProvider; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; + +public class ConfigPropertiesUtil { + private ConfigPropertiesUtil() { + } + + /** + * Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. + */ + public static ConfigProperties resolveConfigProperties( + AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { + ConfigProperties sdkConfigProperties = + AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); + if (sdkConfigProperties != null) { + return sdkConfigProperties; + } + ConfigProvider configProvider = + AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); + if (configProvider != null) { + DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); + + if (instrumentationConfig == null) { + instrumentationConfig = DeclarativeConfigProperties.empty(); + } + + return new DeclarativeConfigPropertiesBridge(instrumentationConfig); + } + // Should never happen + throw new IllegalStateException( + "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); + } + + public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel model) { + SdkConfigProvider configProvider = SdkConfigProvider.create(model); + DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); + if (instrumentationConfig == null) { + instrumentationConfig = DeclarativeConfigProperties.empty(); + } + + return new DeclarativeConfigPropertiesBridge(instrumentationConfig); + } +} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java new file mode 100644 index 000000000..0721e4a69 --- /dev/null +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -0,0 +1,158 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sdk.autoconfigure; + +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; + +import javax.annotation.Nullable; +import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; + +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + +/** + * A {@link ConfigProperties} which resolves properties based on {@link + * DeclarativeConfigProperties}. + * + *

Only properties starting with "otel.instrumentation." are resolved. Others return null (or + * default value if provided). + * + *

To resolve: + * + *

    + *
  • "otel.instrumentation" refers to the ".instrumentation.java" node + *
  • The portion of the property after "otel.instrumentation." is split into segments based on + * ".". + *
  • For each N-1 segment, we walk down the tree to find the relevant leaf {@link + * DeclarativeConfigProperties}. + *
  • We extract the property from the resolved {@link DeclarativeConfigProperties} using the + * last segment as the property key. + *
+ * + *

For example, given the following YAML, asking for {@code + * ConfigProperties#getString("otel.instrumentation.common.string_key")} yields "value": + * + *

+ *   instrumentation:
+ *     java:
+ *       common:
+ *         string_key: value
+ * 
+ */ +final class DeclarativeConfigPropertiesBridge implements ConfigProperties { + + private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; + + // The node at .instrumentation.java + private final DeclarativeConfigProperties instrumentationJavaNode; + + DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode) { + instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); + } + + @Nullable + @Override + public String getString(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getString); + } + + @Nullable + @Override + public Boolean getBoolean(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getBoolean); + } + + @Nullable + @Override + public Integer getInt(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt); + } + + @Nullable + @Override + public Long getLong(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + } + + @Nullable + @Override + public Double getDouble(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble); + } + + @Nullable + @Override + public Duration getDuration(String propertyName) { + Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + if (millis == null) { + return null; + } + return Duration.ofMillis(millis); + } + + @Override + public List getList(String propertyName) { + List propertyValue = + getPropertyValue( + propertyName, + (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); + return propertyValue == null ? Collections.emptyList() : propertyValue; + } + + @Override + public Map getMap(String propertyName) { + DeclarativeConfigProperties propertyValue = + getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); + if (propertyValue == null) { + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + propertyValue + .getPropertyKeys() + .forEach( + key -> { + String value = propertyValue.getString(key); + if (value == null) { + return; + } + result.put(key, value); + }); + return Collections.unmodifiableMap(result); + } + + @Nullable + private T getPropertyValue( + String property, BiFunction extractor) { + if (instrumentationJavaNode == null) { + return null; + } + + if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { + property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); + } + // Split the remainder of the property on "." + String[] segments = property.split("\\."); + if (segments.length == 0) { + return null; + } + + // Extract the value by walking to the N-1 entry + DeclarativeConfigProperties target = instrumentationJavaNode; + if (segments.length > 1) { + for (int i = 0; i < segments.length - 1; i++) { + target = target.getStructured(segments[i], empty()); + } + } + String lastPart = segments[segments.length - 1]; + + return extractor.apply(target, lastPart); + } +} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java new file mode 100644 index 000000000..8d88e9783 --- /dev/null +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java @@ -0,0 +1,87 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sdk.autoconfigure; + + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import io.opentelemetry.api.incubator.config.ConfigProvider; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +@SuppressWarnings("DoNotMockAutoValue") +class ConfigPropertiesUtilTest { + @Test + void shouldUseConfigPropertiesForAutoConfiguration() { + ConfigProperties configPropertiesMock = mock(ConfigProperties.class); + AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); + try (MockedStatic autoConfigureUtilMock = + Mockito.mockStatic(AutoConfigureUtil.class)) { + autoConfigureUtilMock + .when(() -> AutoConfigureUtil.getConfig(sdkMock)) + .thenReturn(configPropertiesMock); + + ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock); + + assertThat(configProperties).isSameAs(configPropertiesMock); + } + } + + @Test + void shouldUseConfigProviderForDeclarativeConfiguration() { + String propertyName = "testProperty"; + String expectedValue = "the value"; + DeclarativeConfigProperties javaNodeMock = mock(DeclarativeConfigProperties.class); + when(javaNodeMock.getString(propertyName)).thenReturn(expectedValue); + + DeclarativeConfigProperties instrumentationConfigMock = mock(DeclarativeConfigProperties.class); + when(instrumentationConfigMock.getStructured(eq("java"), any())).thenReturn(javaNodeMock); + + ConfigProvider configProviderMock = mock(ConfigProvider.class); + when(configProviderMock.getInstrumentationConfig()).thenReturn(instrumentationConfigMock); + + AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); + + try (MockedStatic autoConfigureUtilMock = + Mockito.mockStatic(AutoConfigureUtil.class)) { + autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); + autoConfigureUtilMock + .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) + .thenReturn(configProviderMock); + + ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock); + + assertThat(configProperties.getString(propertyName)).isEqualTo(expectedValue); + } + } + + @Test + void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig() { + AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); + ConfigProvider configProviderMock = mock(ConfigProvider.class); + when(configProviderMock.getInstrumentationConfig()).thenReturn(null); + + try (MockedStatic autoConfigureUtilMock = + Mockito.mockStatic(AutoConfigureUtil.class)) { + autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); + autoConfigureUtilMock + .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) + .thenReturn(configProviderMock); + + ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock); + + assertThat(configProperties.getString("testProperty")).isEqualTo(null); + } + } +} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java new file mode 100644 index 000000000..5bff96e16 --- /dev/null +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -0,0 +1,137 @@ +package io.opentelemetry.contrib.sdk.autoconfigure;/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.InstrumentationModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class DeclarativeConfigPropertiesBridgeTest { + + private static final String YAML = + "file_format: 0.4\n" + + "instrumentation/development:\n" + + " java:\n" + + " common:\n" + + " default-enabled: true\n" + + " runtime-telemetry:\n" + + " enabled: false\n" + + " example-instrumentation:\n" + + " string_key: value\n" + + " bool_key: true\n" + + " int_key: 1\n" + + " double_key: 1.1\n" + + " list_key:\n" + + " - value1\n" + + " - value2\n" + + " - true\n" + + " map_key:\n" + + " string_key1: value1\n" + + " string_key2: value2\n" + + " bool_key: true\n" + + " acme:\n" + + " full_name:\n" + + " preserved: true"; + + private ConfigProperties bridge; + private ConfigProperties emptyBridge; + + @BeforeEach + void setup() { + OpenTelemetryConfigurationModel model = + DeclarativeConfiguration.parse( + new ByteArrayInputStream(YAML.getBytes(StandardCharsets.UTF_8))); + SdkConfigProvider configProvider = SdkConfigProvider.create(model); + bridge = + new ConfigPropertiesUtil.DeclarativeConfigPropertiesBridge( + Objects.requireNonNull(configProvider.getInstrumentationConfig())); + + OpenTelemetryConfigurationModel emptyModel = + new OpenTelemetryConfigurationModel() + .withAdditionalProperty("instrumentation/development", new InstrumentationModel()); + SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); + emptyBridge = + new ConfigPropertiesUtil.DeclarativeConfigPropertiesBridge( + Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); + } + + @Test + void getProperties() { + // only properties starting with "otel.instrumentation." are resolved + // asking for properties which don't exist or inaccessible shouldn't result in an error + assertThat(bridge.getString("file_format")).isNull(); + assertThat(bridge.getString("file_format", "foo")).isEqualTo("foo"); + assertThat(emptyBridge.getBoolean("otel.instrumentation.common.default-enabled")).isNull(); + assertThat(emptyBridge.getBoolean("otel.instrumentation.common.default-enabled", true)) + .isTrue(); + + // common cases + assertThat(bridge.getBoolean("otel.instrumentation.common.default-enabled")).isTrue(); + assertThat(bridge.getBoolean("otel.instrumentation.runtime-telemetry.enabled")).isFalse(); + + // check all the types + Map expectedMap = new HashMap<>(); + expectedMap.put("string_key1", "value1"); + expectedMap.put("string_key2", "value2"); + assertThat(bridge.getString("otel.instrumentation.example-instrumentation.string_key")) + .isEqualTo("value"); + assertThat(bridge.getBoolean("otel.instrumentation.example-instrumentation.bool_key")).isTrue(); + assertThat(bridge.getInt("otel.instrumentation.example-instrumentation.int_key")).isEqualTo(1); + assertThat(bridge.getLong("otel.instrumentation.example-instrumentation.int_key")) + .isEqualTo(1L); + assertThat(bridge.getDuration("otel.instrumentation.example-instrumentation.int_key")) + .isEqualTo(Duration.ofMillis(1)); + assertThat(bridge.getDouble("otel.instrumentation.example-instrumentation.double_key")) + .isEqualTo(1.1); + assertThat(bridge.getList("otel.instrumentation.example-instrumentation.list_key")) + .isEqualTo(Arrays.asList("value1", "value2")); + assertThat(bridge.getMap("otel.instrumentation.example-instrumentation.map_key")) + .isEqualTo(expectedMap); + + // asking for properties with the wrong type returns null + assertThat(bridge.getBoolean("otel.instrumentation.example-instrumentation.string_key")) + .isNull(); + assertThat(bridge.getString("otel.instrumentation.example-instrumentation.bool_key")).isNull(); + assertThat(bridge.getString("otel.instrumentation.example-instrumentation.int_key")).isNull(); + assertThat(bridge.getString("otel.instrumentation.example-instrumentation.double_key")) + .isNull(); + assertThat(bridge.getString("otel.instrumentation.example-instrumentation.list_key")).isNull(); + assertThat(bridge.getString("otel.instrumentation.example-instrumentation.map_key")).isNull(); + + // check all the types + assertThat(bridge.getString("otel.instrumentation.other-instrumentation.string_key", "value")) + .isEqualTo("value"); + assertThat(bridge.getBoolean("otel.instrumentation.other-instrumentation.bool_key", true)) + .isTrue(); + assertThat(bridge.getInt("otel.instrumentation.other-instrumentation.int_key", 1)).isEqualTo(1); + assertThat(bridge.getLong("otel.instrumentation.other-instrumentation.int_key", 1L)) + .isEqualTo(1L); + assertThat( + bridge.getDuration( + "otel.instrumentation.other-instrumentation.int_key", Duration.ofMillis(1))) + .isEqualTo(Duration.ofMillis(1)); + assertThat(bridge.getDouble("otel.instrumentation.other-instrumentation.double_key", 1.1)) + .isEqualTo(1.1); + assertThat( + bridge.getList( + "otel.instrumentation.other-instrumentation.list_key", + Arrays.asList("value1", "value2"))) + .isEqualTo(Arrays.asList("value1", "value2")); + assertThat(bridge.getMap("otel.instrumentation.other-instrumentation.map_key", expectedMap)) + .isEqualTo(expectedMap); + + // verify vendor specific property names are preserved in unchanged form (prefix is not stripped + // as for otel.instrumentation.*) + assertThat(bridge.getBoolean("acme.full_name.preserved")).isTrue(); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 5502252e7..b4ff820a4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -43,6 +43,7 @@ include(":baggage-processor") include(":compressors:compressor-zstd") include(":cloudfoundry-resources") include(":consistent-sampling") +include(":declarative-config-bridge") include(":dependencyManagement") include(":disk-buffering") include(":example") From 30d61fc8eb0063dda9e03390fd3436289f0e0763 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 17:25:41 +0200 Subject: [PATCH 04/44] support config bridge --- gcp-auth-extension/build.gradle.kts | 3 + .../contrib/gcp/auth/ConfigurableOption.java | 22 ++- ...thAutoConfigurationCustomizerProvider.java | 41 +++--- .../gcp/auth/GcpAuthCustomizerProvider.java | 131 ++++++++---------- .../auth/GcpAuthCustomizerProviderTest.java | 70 ++++++++++ 5 files changed, 170 insertions(+), 97 deletions(-) create mode 100644 gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java diff --git a/gcp-auth-extension/build.gradle.kts b/gcp-auth-extension/build.gradle.kts index d606782b0..093864c61 100644 --- a/gcp-auth-extension/build.gradle.kts +++ b/gcp-auth-extension/build.gradle.kts @@ -15,6 +15,8 @@ val agent: Configuration by configurations.creating { dependencies { implementation(platform("org.springframework.boot:spring-boot-dependencies:2.7.18")) + implementation(project(":declarative-config-bridge")) + annotationProcessor("com.google.auto.service:auto-service") // We use `compileOnly` dependency because during runtime all necessary classes are provided by // javaagent itself. @@ -37,6 +39,7 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-exporter-otlp") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations") testImplementation("org.awaitility:awaitility") diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java index 639207909..65c1c8e17 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java @@ -9,6 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.util.Locale; import java.util.Optional; +import java.util.function.BiFunction; import java.util.function.Supplier; /** @@ -99,9 +100,16 @@ String getUserReadableName() { * @throws ConfigurationException if neither the environment variable nor the system property is * set. */ - String getConfiguredValue(ConfigProperties configProperties) { - String configuredValue = configProperties.getString(this.getSystemProperty()); - if (configuredValue != null && !configuredValue.isEmpty()) { + T getConfiguredValue(ConfigProperties configProperties, BiFunction extractor) { + T configuredValue = extractor.apply(configProperties, this.getSystemProperty()); + if (configuredValue instanceof String) { + String value = (String) configuredValue; + if (value.isEmpty()) { + configuredValue = null; // Treat empty string as not configured + } + } + + if (configuredValue != null) { return configuredValue; } else { throw new ConfigurationException( @@ -121,10 +129,10 @@ String getConfiguredValue(ConfigProperties configProperties) { * @return The configured value for the option, obtained from the environment variable, system * property, or the fallback function, in that order of precedence. */ - String getConfiguredValueWithFallback( - ConfigProperties configProperties, Supplier fallback) { + T getConfiguredValueWithFallback( + ConfigProperties configProperties, Supplier fallback, BiFunction extractor) { try { - return this.getConfiguredValue(configProperties); + return this.getConfiguredValue(configProperties, extractor); } catch (ConfigurationException e) { return fallback.get(); } @@ -140,7 +148,7 @@ String getConfiguredValueWithFallback( */ Optional getConfiguredValueAsOptional(ConfigProperties configProperties) { try { - return Optional.of(this.getConfiguredValue(configProperties)); + return Optional.of(this.getConfiguredValue(configProperties, ConfigProperties::getString)); } catch (ConfigurationException e) { return Optional.empty(); } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index b06359c38..ef6b40b52 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -25,7 +25,7 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.export.SpanExporter; import java.io.IOException; -import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -83,7 +83,7 @@ public class GcpAuthAutoConfigurationCustomizerProvider *
  • If the configured signal specific endpoint is a known GCP Telemetry API endpoint, * customizes only the signal specific exporter. * - * + *

    * The 'customization' performed includes customizing the exporters by adding required headers to * the export calls made and customizing the resource by adding required resource attributes to * enable GCP integration. @@ -151,17 +151,20 @@ private static MetricExporter customizeMetricExporter( } // Checks if the auth extension is configured to target the passed signal for authentication. - private static boolean isSignalTargeted(String checkSignal, ConfigProperties configProperties) { - String userSpecifiedTargetedSignals = - ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValueWithFallback( - configProperties, () -> SIGNAL_TYPE_ALL); - return Arrays.stream(userSpecifiedTargetedSignals.split(",")) - .map(String::trim) - .anyMatch( + static boolean isSignalTargeted(String checkSignal, ConfigProperties configProperties) { + return + targetSignals(configProperties).stream().anyMatch( targetedSignal -> targetedSignal.equals(checkSignal) || targetedSignal.equals(SIGNAL_TYPE_ALL)); } + static List targetSignals(ConfigProperties configProperties) { + return ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS + .getConfiguredValueWithFallback( + configProperties, () -> Collections.singletonList(SIGNAL_TYPE_ALL), + ConfigProperties::getList); + } + // Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and // OtlpHttpSpanExporter. private static SpanExporter addAuthorizationHeaders( @@ -221,23 +224,29 @@ static Map getRequiredHeaderMap( // Add quota user project header if not detected by the auth library and user provided it via // system properties. if (!flattenedHeaders.containsKey(QUOTA_USER_PROJECT_HEADER)) { - Optional maybeConfiguredQuotaProjectId = - ConfigurableOption.GOOGLE_CLOUD_QUOTA_PROJECT.getConfiguredValueAsOptional( - configProperties); - maybeConfiguredQuotaProjectId.ifPresent( + getQuotaProjectId(configProperties).ifPresent( configuredQuotaProjectId -> flattenedHeaders.put(QUOTA_USER_PROJECT_HEADER, configuredQuotaProjectId)); } return flattenedHeaders; } + static Optional getQuotaProjectId(ConfigProperties configProperties) { + return ConfigurableOption.GOOGLE_CLOUD_QUOTA_PROJECT.getConfiguredValueAsOptional( + configProperties); + } + // Updates the current resource with the attributes required for ingesting OTLP data on GCP. private static Resource customizeResource(Resource resource, ConfigProperties configProperties) { - String gcpProjectId = - ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue(configProperties); Resource res = Resource.create( - Attributes.of(AttributeKey.stringKey(GCP_USER_PROJECT_ID_KEY), gcpProjectId)); + Attributes.of(AttributeKey.stringKey(GCP_USER_PROJECT_ID_KEY), + getProjectId(configProperties))); return resource.merge(res); } + + static String getProjectId(ConfigProperties configProperties) { + return ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue(configProperties, + ConfigProperties::getString); + } } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index e2512aab6..0aee50e95 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -5,15 +5,16 @@ package io.opentelemetry.contrib.gcp.auth; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_TRACES; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.isSignalTargeted; + import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; +import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchLogRecordProcessorModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessorModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordExporterModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordProcessorModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LoggerProviderModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MeterProviderModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReaderModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel; @@ -23,7 +24,6 @@ import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpHttpExporterModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpHttpMetricExporterModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PushMetricExporterModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleLogRecordProcessorModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; @@ -31,35 +31,60 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; @AutoService(DeclarativeConfigurationCustomizerProvider.class) public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { +// private static final String SIGNAL_TARGET_WARNING_FIX_SUGGESTION = +// String.format( +// "You may safely ignore this warning if it is intentional, otherwise please configure the '%s' by exporting valid values to environment variable: %s or by setting valid values in system property: %s.", +// ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getUserReadableName(), +// ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getEnvironmentVariable(), +// ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty()); + + + @Override public void customize(DeclarativeConfigurationCustomizer customizer) { customizer.addModelCustomizer( model -> { + ConfigProperties configProperties = ConfigPropertiesUtil.resolveModel(model); GoogleCredentials credentials = GcpAuthAutoConfigurationCustomizerProvider.getCredentials(); - // todo pass config bridge - Map headerMap = - GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap(credentials, null); - customizeMeter(model, headerMap); - // todo are loggers supported now (not covered in old variant)? - customizeLogger(model, headerMap); - customizeTracer(model, headerMap); + customize(model, credentials, configProperties); return model; }); } - private void customizeMeter( - OpenTelemetryConfigurationModel model, Map headerMap) { + static void customize(OpenTelemetryConfigurationModel model, + GoogleCredentials credentials, ConfigProperties configProperties) { + Map headerMap = + GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap(credentials, + configProperties); + customizeMeter(model, headerMap, configProperties); + customizeTracer(model, headerMap, configProperties); + } + + private static void customizeMeter( + OpenTelemetryConfigurationModel model, Map headerMap, + ConfigProperties configProperties) { MeterProviderModel meterProvider = model.getMeterProvider(); if (meterProvider == null) { return; } + if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { + // todo + // String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; + // logger.log( + // Level.WARNING, + // "GCP Authentication Extension is not configured for signal type: {0}. {1}", + // params); + return; + } + for (MetricReaderModel reader : meterProvider.getReaders()) { if (reader.getPeriodic() != null) { addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), headerMap); @@ -67,7 +92,8 @@ private void customizeMeter( } } - private List> meterModelHeaders(PushMetricExporterModel exporter) { + private static List> meterModelHeaders( + @Nullable PushMetricExporterModel exporter) { ArrayList> list = new ArrayList<>(); if (exporter == null) { return list; @@ -83,62 +109,23 @@ private List> meterModelHeaders(PushMetricExporte return list; } - private void customizeLogger( - OpenTelemetryConfigurationModel model, Map headerMap) { - LoggerProviderModel loggerProvider = model.getLoggerProvider(); - if (loggerProvider == null) { - return; - } - for (LogRecordProcessorModel processor : loggerProvider.getProcessors()) { - BatchLogRecordProcessorModel batch = processor.getBatch(); - if (batch != null) { - addAuth(logRecordModelHeaders(batch.getExporter()), headerMap); - } - SimpleLogRecordProcessorModel simple = processor.getSimple(); - if (simple != null) { - addAuth(logRecordModelHeaders(simple.getExporter()), headerMap); - } - } - } - - private List> logRecordModelHeaders( - LogRecordExporterModel exporter) { - ArrayList> list = new ArrayList<>(); - - if (exporter == null) { - return list; - } - OtlpGrpcExporterModel grpc = exporter.getOtlpGrpc(); - if (grpc != null) { - list.add(grpc.getHeaders()); - } - OtlpHttpExporterModel http = exporter.getOtlpHttp(); - if (http != null) { - list.add(http.getHeaders()); - } - return list; - } - - private void customizeTracer( - OpenTelemetryConfigurationModel model, Map headerMap) { + private static void customizeTracer( + OpenTelemetryConfigurationModel model, Map headerMap, + ConfigProperties configProperties) { TracerProviderModel tracerProvider = model.getTracerProvider(); if (tracerProvider == null) { return; } - // todo here we would want a simplified version of the declarative config bridge - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/DeclarativeConfigPropertiesBridge.java - // googleNode(model) - - // if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { - // todo - // String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; - // logger.log( - // Level.WARNING, - // "GCP Authentication Extension is not configured for signal type: {0}. {1}", - // params); - // return; - // } + if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { + // todo + // String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; + // logger.log( + // Level.WARNING, + // "GCP Authentication Extension is not configured for signal type: {0}. {1}", + // params); + return; + } for (SpanProcessorModel processor : tracerProvider.getProcessors()) { BatchSpanProcessorModel batch = processor.getBatch(); @@ -152,12 +139,8 @@ private void customizeTracer( } } - private void googleNode(OpenTelemetryConfigurationModel model) { - // todo use declarative config bridge - } - - private List> spanExporterModelHeaders( - SpanExporterModel exporter) { + private static List> spanExporterModelHeaders( + @Nullable SpanExporterModel exporter) { ArrayList> list = new ArrayList<>(); if (exporter == null) { @@ -174,12 +157,12 @@ private List> spanExporterModelHeaders( return list; } - private void addAuth( + private static void addAuth( List> headerConsumers, Map headerMap) { headerConsumers.forEach(headers -> addHeaders(headers, headerMap)); } - private void addHeaders(List headers, Map add) { + private static void addHeaders(List headers, Map add) { add.forEach( (key, value) -> { if (headers.stream().noneMatch(header -> key.equals(header.getName()))) { diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java new file mode 100644 index 000000000..5d7fe46e8 --- /dev/null +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java @@ -0,0 +1,70 @@ +package io.opentelemetry.contrib.gcp.auth; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.auth.oauth2.GoogleCredentials; +import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class GcpAuthCustomizerProviderTest { + + @Test + void declarativeConfig() throws IOException { + String yaml = + "file_format: 0.4\n" + + "tracer_provider:\n" + + " processors:\n" + + " - simple:\n" + + " exporter:\n" + + " otlp_http:\n" + + "meter_provider:\n" + + " readers:\n" + + " - periodic:\n" + + " exporter:\n" + + " otlp_http:\n" + + "instrumentation/development:\n" + + " java:\n" + + " google:\n" + + " cloud:\n" + + " project: p\n" + + " quota:\n" + + " project: qp\n" + + " otel:\n" + + " auth:\n" + + " target:\n" + + " signals: [metrics, traces]\n"; + + OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + ConfigProperties properties = ConfigPropertiesUtil.resolveModel(model); + + assertThat( + GcpAuthAutoConfigurationCustomizerProvider.targetSignals(properties)).containsExactly( + "metrics", "traces" + ); + assertThat(GcpAuthAutoConfigurationCustomizerProvider.getProjectId(properties)).isEqualTo( + "p"); + assertThat(GcpAuthAutoConfigurationCustomizerProvider.getQuotaProjectId(properties)).contains( + "qp"); + + GoogleCredentials credentials = mock(GoogleCredentials.class); + when(credentials.getRequestMetadata()) + .thenReturn( + Collections.singletonMap("x-goog-user-project", Collections.singletonList("qp"))); + + GcpAuthCustomizerProvider.customize(model, credentials, properties); + + String header = "headers=\\[io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel@.*\\[name=x-goog-user-project,value=qp]"; + // both metrics and traces should have the header + assertThat(model.toString()).matches(String.format(".*%s.*%s.*", header, header)); + } +} From 0f4954969313a28b1ccefd04ffb1b327b8830b7a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 18:07:01 +0200 Subject: [PATCH 05/44] support config bridge --- .../autoconfigure/ConfigPropertiesUtil.java | 5 + .../DeclarativeConfigPropertiesBridge.java | 207 ++++++++++-------- ...thAutoConfigurationCustomizerProvider.java | 28 ++- .../gcp/auth/GcpAuthCustomizerProvider.java | 65 +++--- .../auth/GcpAuthCustomizerProviderTest.java | 11 + 5 files changed, 168 insertions(+), 148 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index af6cc6397..140a43297 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -52,4 +52,9 @@ public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel mode return new DeclarativeConfigPropertiesBridge(instrumentationConfig); } + + public static String propertyYamlPath(String propertyName) { + // todo test if this is correct + return DeclarativeConfigPropertiesBridge.yamlPath(propertyName); + } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 0721e4a69..c1d835bf5 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -49,110 +49,123 @@ */ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { - private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; - - // The node at .instrumentation.java - private final DeclarativeConfigProperties instrumentationJavaNode; - - DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode) { - instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); - } - - @Nullable - @Override - public String getString(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getString); - } - - @Nullable - @Override - public Boolean getBoolean(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getBoolean); - } - - @Nullable - @Override - public Integer getInt(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt); - } - - @Nullable - @Override - public Long getLong(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); - } - - @Nullable - @Override - public Double getDouble(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble); - } - - @Nullable - @Override - public Duration getDuration(String propertyName) { - Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); - if (millis == null) { - return null; + private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; + + // The node at .instrumentation.java + private final DeclarativeConfigProperties instrumentationJavaNode; + + DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode) { + instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); } - return Duration.ofMillis(millis); - } - - @Override - public List getList(String propertyName) { - List propertyValue = - getPropertyValue( - propertyName, - (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); - return propertyValue == null ? Collections.emptyList() : propertyValue; - } - - @Override - public Map getMap(String propertyName) { - DeclarativeConfigProperties propertyValue = - getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); - if (propertyValue == null) { - return Collections.emptyMap(); + + @Nullable + @Override + public String getString(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getString); } - Map result = new HashMap<>(); - propertyValue - .getPropertyKeys() - .forEach( - key -> { - String value = propertyValue.getString(key); - if (value == null) { - return; - } - result.put(key, value); - }); - return Collections.unmodifiableMap(result); - } - - @Nullable - private T getPropertyValue( - String property, BiFunction extractor) { - if (instrumentationJavaNode == null) { - return null; + + @Nullable + @Override + public Boolean getBoolean(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getBoolean); } - if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { - property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); + @Nullable + @Override + public Integer getInt(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt); } - // Split the remainder of the property on "." - String[] segments = property.split("\\."); - if (segments.length == 0) { - return null; + + @Nullable + @Override + public Long getLong(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + } + + @Nullable + @Override + public Double getDouble(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble); + } + + @Nullable + @Override + public Duration getDuration(String propertyName) { + Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + if (millis == null) { + return null; + } + return Duration.ofMillis(millis); } - // Extract the value by walking to the N-1 entry - DeclarativeConfigProperties target = instrumentationJavaNode; - if (segments.length > 1) { - for (int i = 0; i < segments.length - 1; i++) { - target = target.getStructured(segments[i], empty()); - } + @Override + public List getList(String propertyName) { + List propertyValue = + getPropertyValue( + propertyName, + (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); + return propertyValue == null ? Collections.emptyList() : propertyValue; } - String lastPart = segments[segments.length - 1]; - return extractor.apply(target, lastPart); - } + @Override + public Map getMap(String propertyName) { + DeclarativeConfigProperties propertyValue = + getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); + if (propertyValue == null) { + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + propertyValue + .getPropertyKeys() + .forEach( + key -> { + String value = propertyValue.getString(key); + if (value == null) { + return; + } + result.put(key, value); + }); + return Collections.unmodifiableMap(result); + } + + @Nullable + private T getPropertyValue( + String property, BiFunction extractor) { + if (instrumentationJavaNode == null) { + return null; + } + + String[] segments = getSegments(property); + if (segments.length == 0) { + return null; + } + + // Extract the value by walking to the N-1 entry + DeclarativeConfigProperties target = instrumentationJavaNode; + if (segments.length > 1) { + for (int i = 0; i < segments.length - 1; i++) { + target = target.getStructured(segments[i], empty()); + } + } + String lastPart = segments[segments.length - 1]; + + return extractor.apply(target, lastPart); + } + + private static String[] getSegments(String property) { + if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { + property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); + } + // Split the remainder of the property on "." + return property.split("\\."); + } + + static String yamlPath(String property) { + String[] segments = getSegments(property); + if (segments.length == 0) { + throw new IllegalArgumentException("Invalid property: " + property); + } + + return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; + } } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index ef6b40b52..ed096e1d8 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -124,34 +124,38 @@ public int order() { private static SpanExporter customizeSpanExporter( SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { + if (shouldConfigureExporter(SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, + configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); - } else { - String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; - logger.log( - Level.WARNING, - "GCP Authentication Extension is not configured for signal type: {0}. {1}", - params); } return exporter; } private static MetricExporter customizeMetricExporter( MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (isSignalTargeted(SIGNAL_TYPE_METRICS, configProperties)) { + if (shouldConfigureExporter(SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, + configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); + } + return exporter; + } + + static boolean shouldConfigureExporter(String signal, + String fixSuggestion, + ConfigProperties configProperties) { + if (isSignalTargeted(signal, configProperties)) { + return true; } else { - String[] params = {SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; logger.log( Level.WARNING, "GCP Authentication Extension is not configured for signal type: {0}. {1}", - params); + new String[] {signal, fixSuggestion}); + return false; } - return exporter; } // Checks if the auth extension is configured to target the passed signal for authentication. - static boolean isSignalTargeted(String checkSignal, ConfigProperties configProperties) { + private static boolean isSignalTargeted(String checkSignal, ConfigProperties configProperties) { return targetSignals(configProperties).stream().anyMatch( targetedSignal -> diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index 0aee50e95..7ced14552 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -5,8 +5,9 @@ package io.opentelemetry.contrib.gcp.auth; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_METRICS; import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_TRACES; -import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.isSignalTargeted; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.shouldConfigureExporter; import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; @@ -36,13 +37,12 @@ @AutoService(DeclarativeConfigurationCustomizerProvider.class) public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { -// private static final String SIGNAL_TARGET_WARNING_FIX_SUGGESTION = -// String.format( -// "You may safely ignore this warning if it is intentional, otherwise please configure the '%s' by exporting valid values to environment variable: %s or by setting valid values in system property: %s.", -// ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getUserReadableName(), -// ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getEnvironmentVariable(), -// ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty()); - + static final String SIGNAL_TARGET_WARNING_FIX_SUGGESTION = + String.format( + "You may safely ignore this warning if it is intentional, otherwise please configure the '%s' by setting %s in the configuration file.", + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getUserReadableName(), + ConfigPropertiesUtil.propertyYamlPath( + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty())); @Override @@ -75,19 +75,12 @@ private static void customizeMeter( return; } - if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { - // todo - // String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; - // logger.log( - // Level.WARNING, - // "GCP Authentication Extension is not configured for signal type: {0}. {1}", - // params); - return; - } - - for (MetricReaderModel reader : meterProvider.getReaders()) { - if (reader.getPeriodic() != null) { - addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), headerMap); + if (shouldConfigureExporter(SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, + configProperties)) { + for (MetricReaderModel reader : meterProvider.getReaders()) { + if (reader.getPeriodic() != null) { + addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), headerMap); + } } } } @@ -117,26 +110,20 @@ private static void customizeTracer( return; } - if (!isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { - // todo - // String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; - // logger.log( - // Level.WARNING, - // "GCP Authentication Extension is not configured for signal type: {0}. {1}", - // params); - return; - } - - for (SpanProcessorModel processor : tracerProvider.getProcessors()) { - BatchSpanProcessorModel batch = processor.getBatch(); - if (batch != null) { - addAuth(spanExporterModelHeaders(batch.getExporter()), headerMap); - } - SimpleSpanProcessorModel simple = processor.getSimple(); - if (simple != null) { - addAuth(spanExporterModelHeaders(simple.getExporter()), headerMap); + if (shouldConfigureExporter(SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, + configProperties)) { + for (SpanProcessorModel processor : tracerProvider.getProcessors()) { + BatchSpanProcessorModel batch = processor.getBatch(); + if (batch != null) { + addAuth(spanExporterModelHeaders(batch.getExporter()), headerMap); + } + SimpleSpanProcessorModel simple = processor.getSimple(); + if (simple != null) { + addAuth(spanExporterModelHeaders(simple.getExporter()), headerMap); + } } } + } private static List> spanExporterModelHeaders( diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java index 5d7fe46e8..171c1825f 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java @@ -1,5 +1,6 @@ package io.opentelemetry.contrib.gcp.auth; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthCustomizerProvider.SIGNAL_TARGET_WARNING_FIX_SUGGESTION; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -67,4 +68,14 @@ void declarativeConfig() throws IOException { // both metrics and traces should have the header assertThat(model.toString()).matches(String.format(".*%s.*%s.*", header, header)); } + + @Test + void fixSuggestion() { + assertThat(SIGNAL_TARGET_WARNING_FIX_SUGGESTION) + .isEqualTo("You may safely ignore this warning if it is intentional, " + + "otherwise please configure the 'Target Signals for Google Authentication Extension' " + + "by setting " + + "'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / " + + "'signals' in the configuration file."); + } } From fc7cd07ce2e284ebadcec2995cc2cd0568958d68 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 18:15:47 +0200 Subject: [PATCH 06/44] copy declarative config bridge from instrumentation --- .../contrib/sdk/autoconfigure/ConfigPropertiesUtil.java | 1 - .../sdk/autoconfigure/ConfigPropertiesUtilTest.java | 7 +++++++ .../DeclarativeConfigPropertiesBridgeTest.java | 8 ++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index 140a43297..ee71ccaad 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -54,7 +54,6 @@ public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel mode } public static String propertyYamlPath(String propertyName) { - // todo test if this is correct return DeclarativeConfigPropertiesBridge.yamlPath(propertyName); } } diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java index 8d88e9783..5d74a24a8 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java @@ -6,6 +6,7 @@ package io.opentelemetry.contrib.sdk.autoconfigure; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -84,4 +85,10 @@ void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig( assertThat(configProperties.getString("testProperty")).isEqualTo(null); } } + + @Test + void propertyYamlPath() { + assertThat(ConfigPropertiesUtil.propertyYamlPath("google.otel.auth.target.signals")) + .isEqualTo("'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / 'signals'"); + } } diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index 5bff96e16..34b3a7036 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -3,7 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +import static org.assertj.core.api.Assertions.assertThat; + import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.InstrumentationModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; import java.io.ByteArrayInputStream; @@ -53,7 +57,7 @@ void setup() { new ByteArrayInputStream(YAML.getBytes(StandardCharsets.UTF_8))); SdkConfigProvider configProvider = SdkConfigProvider.create(model); bridge = - new ConfigPropertiesUtil.DeclarativeConfigPropertiesBridge( + new DeclarativeConfigPropertiesBridge( Objects.requireNonNull(configProvider.getInstrumentationConfig())); OpenTelemetryConfigurationModel emptyModel = @@ -61,7 +65,7 @@ void setup() { .withAdditionalProperty("instrumentation/development", new InstrumentationModel()); SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); emptyBridge = - new ConfigPropertiesUtil.DeclarativeConfigPropertiesBridge( + new DeclarativeConfigPropertiesBridge( Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); } From d786ea60a20db5dcf7aef8ed96d829257b9d88b2 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 18:16:20 +0200 Subject: [PATCH 07/44] format --- .../autoconfigure/ConfigPropertiesUtil.java | 71 +++--- .../DeclarativeConfigPropertiesBridge.java | 221 +++++++++--------- .../ConfigPropertiesUtilTest.java | 4 +- ...DeclarativeConfigPropertiesBridgeTest.java | 7 +- .../contrib/gcp/auth/ConfigurableOption.java | 7 +- ...thAutoConfigurationCustomizerProvider.java | 46 ++-- .../gcp/auth/GcpAuthCustomizerProvider.java | 26 ++- .../auth/GcpAuthCustomizerProviderTest.java | 37 +-- 8 files changed, 215 insertions(+), 204 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index ee71ccaad..63db139f9 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -14,46 +14,43 @@ import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; public class ConfigPropertiesUtil { - private ConfigPropertiesUtil() { + private ConfigPropertiesUtil() {} + + /** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */ + public static ConfigProperties resolveConfigProperties( + AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { + ConfigProperties sdkConfigProperties = + AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); + if (sdkConfigProperties != null) { + return sdkConfigProperties; } + ConfigProvider configProvider = + AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); + if (configProvider != null) { + DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); - /** - * Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. - */ - public static ConfigProperties resolveConfigProperties( - AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - ConfigProperties sdkConfigProperties = - AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); - if (sdkConfigProperties != null) { - return sdkConfigProperties; - } - ConfigProvider configProvider = - AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); - if (configProvider != null) { - DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); - - if (instrumentationConfig == null) { - instrumentationConfig = DeclarativeConfigProperties.empty(); - } - - return new DeclarativeConfigPropertiesBridge(instrumentationConfig); - } - // Should never happen - throw new IllegalStateException( - "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); - } - - public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel model) { - SdkConfigProvider configProvider = SdkConfigProvider.create(model); - DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); - if (instrumentationConfig == null) { - instrumentationConfig = DeclarativeConfigProperties.empty(); - } + if (instrumentationConfig == null) { + instrumentationConfig = DeclarativeConfigProperties.empty(); + } - return new DeclarativeConfigPropertiesBridge(instrumentationConfig); + return new DeclarativeConfigPropertiesBridge(instrumentationConfig); } - - public static String propertyYamlPath(String propertyName) { - return DeclarativeConfigPropertiesBridge.yamlPath(propertyName); + // Should never happen + throw new IllegalStateException( + "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); + } + + public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel model) { + SdkConfigProvider configProvider = SdkConfigProvider.create(model); + DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); + if (instrumentationConfig == null) { + instrumentationConfig = DeclarativeConfigProperties.empty(); } + + return new DeclarativeConfigPropertiesBridge(instrumentationConfig); + } + + public static String propertyYamlPath(String propertyName) { + return DeclarativeConfigPropertiesBridge.yamlPath(propertyName); + } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index c1d835bf5..47173f7ac 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -5,18 +5,17 @@ package io.opentelemetry.contrib.sdk.autoconfigure; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; - -import javax.annotation.Nullable; import java.time.Duration; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.BiFunction; - -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; +import javax.annotation.Nullable; /** * A {@link ConfigProperties} which resolves properties based on {@link @@ -49,123 +48,123 @@ */ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { - private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; - - // The node at .instrumentation.java - private final DeclarativeConfigProperties instrumentationJavaNode; - - DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode) { - instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); + private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; + + // The node at .instrumentation.java + private final DeclarativeConfigProperties instrumentationJavaNode; + + DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode) { + instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); + } + + @Nullable + @Override + public String getString(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getString); + } + + @Nullable + @Override + public Boolean getBoolean(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getBoolean); + } + + @Nullable + @Override + public Integer getInt(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt); + } + + @Nullable + @Override + public Long getLong(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + } + + @Nullable + @Override + public Double getDouble(String propertyName) { + return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble); + } + + @Nullable + @Override + public Duration getDuration(String propertyName) { + Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + if (millis == null) { + return null; } - - @Nullable - @Override - public String getString(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getString); + return Duration.ofMillis(millis); + } + + @Override + public List getList(String propertyName) { + List propertyValue = + getPropertyValue( + propertyName, + (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); + return propertyValue == null ? Collections.emptyList() : propertyValue; + } + + @Override + public Map getMap(String propertyName) { + DeclarativeConfigProperties propertyValue = + getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); + if (propertyValue == null) { + return Collections.emptyMap(); } - - @Nullable - @Override - public Boolean getBoolean(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getBoolean); + Map result = new HashMap<>(); + propertyValue + .getPropertyKeys() + .forEach( + key -> { + String value = propertyValue.getString(key); + if (value == null) { + return; + } + result.put(key, value); + }); + return Collections.unmodifiableMap(result); + } + + @Nullable + private T getPropertyValue( + String property, BiFunction extractor) { + if (instrumentationJavaNode == null) { + return null; } - @Nullable - @Override - public Integer getInt(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt); + String[] segments = getSegments(property); + if (segments.length == 0) { + return null; } - @Nullable - @Override - public Long getLong(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + // Extract the value by walking to the N-1 entry + DeclarativeConfigProperties target = instrumentationJavaNode; + if (segments.length > 1) { + for (int i = 0; i < segments.length - 1; i++) { + target = target.getStructured(segments[i], empty()); + } } + String lastPart = segments[segments.length - 1]; - @Nullable - @Override - public Double getDouble(String propertyName) { - return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble); - } - - @Nullable - @Override - public Duration getDuration(String propertyName) { - Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); - if (millis == null) { - return null; - } - return Duration.ofMillis(millis); - } - - @Override - public List getList(String propertyName) { - List propertyValue = - getPropertyValue( - propertyName, - (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); - return propertyValue == null ? Collections.emptyList() : propertyValue; - } + return extractor.apply(target, lastPart); + } - @Override - public Map getMap(String propertyName) { - DeclarativeConfigProperties propertyValue = - getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); - if (propertyValue == null) { - return Collections.emptyMap(); - } - Map result = new HashMap<>(); - propertyValue - .getPropertyKeys() - .forEach( - key -> { - String value = propertyValue.getString(key); - if (value == null) { - return; - } - result.put(key, value); - }); - return Collections.unmodifiableMap(result); + private static String[] getSegments(String property) { + if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { + property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); } - - @Nullable - private T getPropertyValue( - String property, BiFunction extractor) { - if (instrumentationJavaNode == null) { - return null; - } - - String[] segments = getSegments(property); - if (segments.length == 0) { - return null; - } - - // Extract the value by walking to the N-1 entry - DeclarativeConfigProperties target = instrumentationJavaNode; - if (segments.length > 1) { - for (int i = 0; i < segments.length - 1; i++) { - target = target.getStructured(segments[i], empty()); - } - } - String lastPart = segments[segments.length - 1]; - - return extractor.apply(target, lastPart); - } - - private static String[] getSegments(String property) { - if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { - property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); - } - // Split the remainder of the property on "." - return property.split("\\."); + // Split the remainder of the property on "." + return property.split("\\."); + } + + static String yamlPath(String property) { + String[] segments = getSegments(property); + if (segments.length == 0) { + throw new IllegalArgumentException("Invalid property: " + property); } - static String yamlPath(String property) { - String[] segments = getSegments(property); - if (segments.length == 0) { - throw new IllegalArgumentException("Invalid property: " + property); - } - - return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; - } + return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; + } } diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java index 5d74a24a8..9981ffdb2 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java @@ -5,7 +5,6 @@ package io.opentelemetry.contrib.sdk.autoconfigure; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -89,6 +88,7 @@ void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig( @Test void propertyYamlPath() { assertThat(ConfigPropertiesUtil.propertyYamlPath("google.otel.auth.target.signals")) - .isEqualTo("'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / 'signals'"); + .isEqualTo( + "'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / 'signals'"); } } diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index 34b3a7036..caadda60b 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -1,8 +1,13 @@ -package io.opentelemetry.contrib.sdk.autoconfigure;/* +/* * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.contrib.sdk.autoconfigure; /* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java index 65c1c8e17..5756d1224 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java @@ -100,7 +100,8 @@ String getUserReadableName() { * @throws ConfigurationException if neither the environment variable nor the system property is * set. */ - T getConfiguredValue(ConfigProperties configProperties, BiFunction extractor) { + T getConfiguredValue( + ConfigProperties configProperties, BiFunction extractor) { T configuredValue = extractor.apply(configProperties, this.getSystemProperty()); if (configuredValue instanceof String) { String value = (String) configuredValue; @@ -130,7 +131,9 @@ T getConfiguredValue(ConfigProperties configProperties, BiFunction T getConfiguredValueWithFallback( - ConfigProperties configProperties, Supplier fallback, BiFunction extractor) { + ConfigProperties configProperties, + Supplier fallback, + BiFunction extractor) { try { return this.getConfiguredValue(configProperties, extractor); } catch (ConfigurationException e) { diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index ed096e1d8..a54dd677d 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -83,9 +83,9 @@ public class GcpAuthAutoConfigurationCustomizerProvider *

  • If the configured signal specific endpoint is a known GCP Telemetry API endpoint, * customizes only the signal specific exporter. * - *

    - * The 'customization' performed includes customizing the exporters by adding required headers to - * the export calls made and customizing the resource by adding required resource attributes to + * + *

    The 'customization' performed includes customizing the exporters by adding required headers + * to the export calls made and customizing the resource by adding required resource attributes to * enable GCP integration. * * @param autoConfiguration the AutoConfigurationCustomizer to customize. @@ -124,8 +124,8 @@ public int order() { private static SpanExporter customizeSpanExporter( SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (shouldConfigureExporter(SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, - configProperties)) { + if (shouldConfigureExporter( + SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); } return exporter; @@ -133,16 +133,15 @@ private static SpanExporter customizeSpanExporter( private static MetricExporter customizeMetricExporter( MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (shouldConfigureExporter(SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, - configProperties)) { + if (shouldConfigureExporter( + SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); } return exporter; } - static boolean shouldConfigureExporter(String signal, - String fixSuggestion, - ConfigProperties configProperties) { + static boolean shouldConfigureExporter( + String signal, String fixSuggestion, ConfigProperties configProperties) { if (isSignalTargeted(signal, configProperties)) { return true; } else { @@ -156,17 +155,17 @@ static boolean shouldConfigureExporter(String signal, // Checks if the auth extension is configured to target the passed signal for authentication. private static boolean isSignalTargeted(String checkSignal, ConfigProperties configProperties) { - return - targetSignals(configProperties).stream().anyMatch( + return targetSignals(configProperties).stream() + .anyMatch( targetedSignal -> targetedSignal.equals(checkSignal) || targetedSignal.equals(SIGNAL_TYPE_ALL)); } static List targetSignals(ConfigProperties configProperties) { - return ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS - .getConfiguredValueWithFallback( - configProperties, () -> Collections.singletonList(SIGNAL_TYPE_ALL), - ConfigProperties::getList); + return ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValueWithFallback( + configProperties, + () -> Collections.singletonList(SIGNAL_TYPE_ALL), + ConfigProperties::getList); } // Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and @@ -228,9 +227,10 @@ static Map getRequiredHeaderMap( // Add quota user project header if not detected by the auth library and user provided it via // system properties. if (!flattenedHeaders.containsKey(QUOTA_USER_PROJECT_HEADER)) { - getQuotaProjectId(configProperties).ifPresent( - configuredQuotaProjectId -> - flattenedHeaders.put(QUOTA_USER_PROJECT_HEADER, configuredQuotaProjectId)); + getQuotaProjectId(configProperties) + .ifPresent( + configuredQuotaProjectId -> + flattenedHeaders.put(QUOTA_USER_PROJECT_HEADER, configuredQuotaProjectId)); } return flattenedHeaders; } @@ -244,13 +244,13 @@ static Optional getQuotaProjectId(ConfigProperties configProperties) { private static Resource customizeResource(Resource resource, ConfigProperties configProperties) { Resource res = Resource.create( - Attributes.of(AttributeKey.stringKey(GCP_USER_PROJECT_ID_KEY), - getProjectId(configProperties))); + Attributes.of( + AttributeKey.stringKey(GCP_USER_PROJECT_ID_KEY), getProjectId(configProperties))); return resource.merge(res); } static String getProjectId(ConfigProperties configProperties) { - return ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue(configProperties, - ConfigProperties::getString); + return ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue( + configProperties, ConfigProperties::getString); } } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index 7ced14552..90a3d17f2 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -44,7 +44,6 @@ public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustom ConfigPropertiesUtil.propertyYamlPath( ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty())); - @Override public void customize(DeclarativeConfigurationCustomizer customizer) { customizer.addModelCustomizer( @@ -58,25 +57,28 @@ public void customize(DeclarativeConfigurationCustomizer customizer) { }); } - static void customize(OpenTelemetryConfigurationModel model, - GoogleCredentials credentials, ConfigProperties configProperties) { + static void customize( + OpenTelemetryConfigurationModel model, + GoogleCredentials credentials, + ConfigProperties configProperties) { Map headerMap = - GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap(credentials, - configProperties); + GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap( + credentials, configProperties); customizeMeter(model, headerMap, configProperties); customizeTracer(model, headerMap, configProperties); } private static void customizeMeter( - OpenTelemetryConfigurationModel model, Map headerMap, + OpenTelemetryConfigurationModel model, + Map headerMap, ConfigProperties configProperties) { MeterProviderModel meterProvider = model.getMeterProvider(); if (meterProvider == null) { return; } - if (shouldConfigureExporter(SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, - configProperties)) { + if (shouldConfigureExporter( + SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { for (MetricReaderModel reader : meterProvider.getReaders()) { if (reader.getPeriodic() != null) { addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), headerMap); @@ -103,15 +105,16 @@ private static List> meterModelHeaders( } private static void customizeTracer( - OpenTelemetryConfigurationModel model, Map headerMap, + OpenTelemetryConfigurationModel model, + Map headerMap, ConfigProperties configProperties) { TracerProviderModel tracerProvider = model.getTracerProvider(); if (tracerProvider == null) { return; } - if (shouldConfigureExporter(SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, - configProperties)) { + if (shouldConfigureExporter( + SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { for (SpanProcessorModel processor : tracerProvider.getProcessors()) { BatchSpanProcessorModel batch = processor.getBatch(); if (batch != null) { @@ -123,7 +126,6 @@ private static void customizeTracer( } } } - } private static List> spanExporterModelHeaders( diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java index 171c1825f..9ccff6129 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.contrib.gcp.auth; import static io.opentelemetry.contrib.gcp.auth.GcpAuthCustomizerProvider.SIGNAL_TARGET_WARNING_FIX_SUGGESTION; @@ -44,18 +49,16 @@ void declarativeConfig() throws IOException { + " target:\n" + " signals: [metrics, traces]\n"; - OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( - new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + OpenTelemetryConfigurationModel model = + DeclarativeConfiguration.parse( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); ConfigProperties properties = ConfigPropertiesUtil.resolveModel(model); - assertThat( - GcpAuthAutoConfigurationCustomizerProvider.targetSignals(properties)).containsExactly( - "metrics", "traces" - ); - assertThat(GcpAuthAutoConfigurationCustomizerProvider.getProjectId(properties)).isEqualTo( - "p"); - assertThat(GcpAuthAutoConfigurationCustomizerProvider.getQuotaProjectId(properties)).contains( - "qp"); + assertThat(GcpAuthAutoConfigurationCustomizerProvider.targetSignals(properties)) + .containsExactly("metrics", "traces"); + assertThat(GcpAuthAutoConfigurationCustomizerProvider.getProjectId(properties)).isEqualTo("p"); + assertThat(GcpAuthAutoConfigurationCustomizerProvider.getQuotaProjectId(properties)) + .contains("qp"); GoogleCredentials credentials = mock(GoogleCredentials.class); when(credentials.getRequestMetadata()) @@ -64,7 +67,8 @@ void declarativeConfig() throws IOException { GcpAuthCustomizerProvider.customize(model, credentials, properties); - String header = "headers=\\[io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel@.*\\[name=x-goog-user-project,value=qp]"; + String header = + "headers=\\[io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel@.*\\[name=x-goog-user-project,value=qp]"; // both metrics and traces should have the header assertThat(model.toString()).matches(String.format(".*%s.*%s.*", header, header)); } @@ -72,10 +76,11 @@ void declarativeConfig() throws IOException { @Test void fixSuggestion() { assertThat(SIGNAL_TARGET_WARNING_FIX_SUGGESTION) - .isEqualTo("You may safely ignore this warning if it is intentional, " - + "otherwise please configure the 'Target Signals for Google Authentication Extension' " - + "by setting " - + "'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / " - + "'signals' in the configuration file."); + .isEqualTo( + "You may safely ignore this warning if it is intentional, " + + "otherwise please configure the 'Target Signals for Google Authentication Extension' " + + "by setting " + + "'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / " + + "'signals' in the configuration file."); } } From bf9c8e6bace930994168badbd91af3d9995da008 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 18:21:06 +0200 Subject: [PATCH 08/44] cleanup --- .../contrib/gcp/auth/GcpAuthCustomizerProvider.java | 12 +++++------- .../gcp/auth/GcpAuthCustomizerProviderTest.java | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index 90a3d17f2..1b71800e4 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -37,7 +37,7 @@ @AutoService(DeclarativeConfigurationCustomizerProvider.class) public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { - static final String SIGNAL_TARGET_WARNING_FIX_SUGGESTION = + static final String SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION = String.format( "You may safely ignore this warning if it is intentional, otherwise please configure the '%s' by setting %s in the configuration file.", ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getUserReadableName(), @@ -48,10 +48,8 @@ public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustom public void customize(DeclarativeConfigurationCustomizer customizer) { customizer.addModelCustomizer( model -> { - ConfigProperties configProperties = ConfigPropertiesUtil.resolveModel(model); - GoogleCredentials credentials = - GcpAuthAutoConfigurationCustomizerProvider.getCredentials(); - customize(model, credentials, configProperties); + customize(model, GcpAuthAutoConfigurationCustomizerProvider.getCredentials(), + ConfigPropertiesUtil.resolveModel(model)); return model; }); @@ -78,7 +76,7 @@ private static void customizeMeter( } if (shouldConfigureExporter( - SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { + SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION, configProperties)) { for (MetricReaderModel reader : meterProvider.getReaders()) { if (reader.getPeriodic() != null) { addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), headerMap); @@ -114,7 +112,7 @@ private static void customizeTracer( } if (shouldConfigureExporter( - SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { + SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION, configProperties)) { for (SpanProcessorModel processor : tracerProvider.getProcessors()) { BatchSpanProcessorModel batch = processor.getBatch(); if (batch != null) { diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java index 9ccff6129..fd469eae0 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.gcp.auth; -import static io.opentelemetry.contrib.gcp.auth.GcpAuthCustomizerProvider.SIGNAL_TARGET_WARNING_FIX_SUGGESTION; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthCustomizerProvider.SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -75,7 +75,7 @@ void declarativeConfig() throws IOException { @Test void fixSuggestion() { - assertThat(SIGNAL_TARGET_WARNING_FIX_SUGGESTION) + assertThat(SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION) .isEqualTo( "You may safely ignore this warning if it is intentional, " + "otherwise please configure the 'Target Signals for Google Authentication Extension' " From b70486a12d5cd701b56d1fe5ea38a555c4be597d Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 18:22:04 +0200 Subject: [PATCH 09/44] cleanup --- .../contrib/gcp/auth/GcpAuthCustomizerProvider.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index 1b71800e4..297a47596 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -48,7 +48,9 @@ public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustom public void customize(DeclarativeConfigurationCustomizer customizer) { customizer.addModelCustomizer( model -> { - customize(model, GcpAuthAutoConfigurationCustomizerProvider.getCredentials(), + customize( + model, + GcpAuthAutoConfigurationCustomizerProvider.getCredentials(), ConfigPropertiesUtil.resolveModel(model)); return model; From 4d562097bff97556e0d52834aba165ad021b1013 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 18:28:30 +0200 Subject: [PATCH 10/44] fix test --- declarative-config-bridge/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/declarative-config-bridge/build.gradle.kts b/declarative-config-bridge/build.gradle.kts index 66fb4658b..1da7432d0 100644 --- a/declarative-config-bridge/build.gradle.kts +++ b/declarative-config-bridge/build.gradle.kts @@ -14,4 +14,5 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") + testImplementation("org.mockito:mockito-inline") } From 85ec1cba18dc686e20e7ec7d8fcb059a2ec7baed Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 19:14:29 +0200 Subject: [PATCH 11/44] fix --- .../contrib/gcp/auth/ConfigurableOption.java | 65 ++++++------------- ...thAutoConfigurationCustomizerProvider.java | 16 +++-- 2 files changed, 29 insertions(+), 52 deletions(-) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java index 5756d1224..54649c7a6 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java @@ -8,9 +8,8 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.util.Locale; -import java.util.Optional; import java.util.function.BiFunction; -import java.util.function.Supplier; +import javax.annotation.Nullable; /** * An enum representing configurable options for a GCP Authentication Extension. Each option has a @@ -100,60 +99,36 @@ String getUserReadableName() { * @throws ConfigurationException if neither the environment variable nor the system property is * set. */ - T getConfiguredValue( + T getRequiredConfiguredValue( ConfigProperties configProperties, BiFunction extractor) { - T configuredValue = extractor.apply(configProperties, this.getSystemProperty()); - if (configuredValue instanceof String) { - String value = (String) configuredValue; - if (value.isEmpty()) { - configuredValue = null; // Treat empty string as not configured - } - } - - if (configuredValue != null) { - return configuredValue; - } else { + T configuredValue = getConfiguredValue(configProperties, extractor); + if (configuredValue == null) { throw new ConfigurationException( String.format( - "GCP Authentication Extension not configured properly: %s not configured. Configure it by exporting environment variable %s or system property %s", + "GCP Authentication Extension not configured properly: %s not configured. " + + "Configure it by exporting environment variable %s or system property %s", this.userReadableName, this.getEnvironmentVariable(), this.getSystemProperty())); } + return configuredValue; } /** - * Retrieves the value for this option, prioritizing environment variables and system properties. - * If neither an environment variable nor a system property is set for this option, the provided - * fallback function is used to determine the value. + * Retrieves the configured value for this option. This method checks the environment variable + * first and then the system property. * - * @param fallback A {@link Supplier} that provides the default value for the option when it is - * not explicitly configured via an environment variable or system property. - * @return The configured value for the option, obtained from the environment variable, system - * property, or the fallback function, in that order of precedence. + * @return The configured value as a string, or throws an exception if not configured. */ - T getConfiguredValueWithFallback( - ConfigProperties configProperties, - Supplier fallback, - BiFunction extractor) { - try { - return this.getConfiguredValue(configProperties, extractor); - } catch (ConfigurationException e) { - return fallback.get(); + @Nullable + T getConfiguredValue( + ConfigProperties configProperties, BiFunction extractor) { + T configuredValue = extractor.apply(configProperties, this.getSystemProperty()); + if (configuredValue instanceof String) { + String value = (String) configuredValue; + if (value.isEmpty()) { + configuredValue = null; // Treat empty string as not configured + } } - } - /** - * Retrieves the value for this option, prioritizing environment variables before system - * properties. If neither an environment variable nor a system property is set for this option, - * then an empty {@link Optional} is returned. - * - * @return The configured value for the option, if set, obtained from the environment variable, - * system property, or empty {@link Optional}, in that order of precedence. - */ - Optional getConfiguredValueAsOptional(ConfigProperties configProperties) { - try { - return Optional.of(this.getConfiguredValue(configProperties, ConfigProperties::getString)); - } catch (ConfigurationException e) { - return Optional.empty(); - } + return configuredValue; } } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index a54dd677d..8b241755f 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -162,10 +162,11 @@ private static boolean isSignalTargeted(String checkSignal, ConfigProperties con } static List targetSignals(ConfigProperties configProperties) { - return ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValueWithFallback( - configProperties, - () -> Collections.singletonList(SIGNAL_TYPE_ALL), - ConfigProperties::getList); + return Objects.requireNonNull( + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValue( + configProperties, + (properties, name) -> + properties.getList(name, Collections.singletonList(SIGNAL_TYPE_ALL)))); } // Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and @@ -236,8 +237,9 @@ static Map getRequiredHeaderMap( } static Optional getQuotaProjectId(ConfigProperties configProperties) { - return ConfigurableOption.GOOGLE_CLOUD_QUOTA_PROJECT.getConfiguredValueAsOptional( - configProperties); + return Optional.ofNullable( + ConfigurableOption.GOOGLE_CLOUD_QUOTA_PROJECT.getConfiguredValue( + configProperties, ConfigProperties::getString)); } // Updates the current resource with the attributes required for ingesting OTLP data on GCP. @@ -250,7 +252,7 @@ private static Resource customizeResource(Resource resource, ConfigProperties co } static String getProjectId(ConfigProperties configProperties) { - return ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue( + return ConfigurableOption.GOOGLE_CLOUD_PROJECT.getRequiredConfiguredValue( configProperties, ConfigProperties::getString); } } From 83e74a7fbc4a9a6974a56f6ed5da325ad16851d0 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 14 Jul 2025 18:51:19 +0200 Subject: [PATCH 12/44] add property translation for inferred spans --- .../autoconfigure/ConfigPropertiesUtil.java | 10 +++- .../DeclarativeConfigPropertiesBridge.java | 16 ++++++- ...DeclarativeConfigPropertiesBridgeTest.java | 48 ++++++++++++------- inferred-spans/build.gradle.kts | 4 ++ .../InferredSpansCustomizerProvider.java | 29 +++++++++++ 5 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index 63db139f9..e5167c966 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -12,6 +12,8 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.util.Collections; +import java.util.Map; public class ConfigPropertiesUtil { private ConfigPropertiesUtil() {} @@ -33,7 +35,7 @@ public static ConfigProperties resolveConfigProperties( instrumentationConfig = DeclarativeConfigProperties.empty(); } - return new DeclarativeConfigPropertiesBridge(instrumentationConfig); + return new DeclarativeConfigPropertiesBridge(instrumentationConfig, Collections.emptyMap()); } // Should never happen throw new IllegalStateException( @@ -41,13 +43,17 @@ public static ConfigProperties resolveConfigProperties( } public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel model) { + return resolveModel(model, Collections.emptyMap()); + } + + public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel model, Map translationMap) { SdkConfigProvider configProvider = SdkConfigProvider.create(model); DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); if (instrumentationConfig == null) { instrumentationConfig = DeclarativeConfigProperties.empty(); } - return new DeclarativeConfigPropertiesBridge(instrumentationConfig); + return new DeclarativeConfigPropertiesBridge(instrumentationConfig, translationMap); } public static String propertyYamlPath(String propertyName) { diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 47173f7ac..0cb6d17d6 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -52,9 +52,12 @@ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { // The node at .instrumentation.java private final DeclarativeConfigProperties instrumentationJavaNode; + private final Map translationMap; - DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode) { + DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode, + Map translationMap) { instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); + this.translationMap = translationMap; } @Nullable @@ -134,7 +137,7 @@ private T getPropertyValue( return null; } - String[] segments = getSegments(property); + String[] segments = getSegments(translate(property)); if (segments.length == 0) { return null; } @@ -151,6 +154,15 @@ private T getPropertyValue( return extractor.apply(target, lastPart); } + private String translate(String property) { + for (Map.Entry entry : translationMap.entrySet()) { + if (property.startsWith(entry.getKey())) { + return entry.getValue() + property.substring(entry.getKey().length()); + } + } + return property; + } + private static String[] getSegments(String property) { if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index caadda60b..9ed47cd8c 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -4,9 +4,9 @@ */ package io.opentelemetry.contrib.sdk.autoconfigure; /* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ import static org.assertj.core.api.Assertions.assertThat; @@ -19,6 +19,7 @@ import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -57,13 +58,7 @@ class DeclarativeConfigPropertiesBridgeTest { @BeforeEach void setup() { - OpenTelemetryConfigurationModel model = - DeclarativeConfiguration.parse( - new ByteArrayInputStream(YAML.getBytes(StandardCharsets.UTF_8))); - SdkConfigProvider configProvider = SdkConfigProvider.create(model); - bridge = - new DeclarativeConfigPropertiesBridge( - Objects.requireNonNull(configProvider.getInstrumentationConfig())); + bridge = createBridge(Collections.emptyMap()); OpenTelemetryConfigurationModel emptyModel = new OpenTelemetryConfigurationModel() @@ -71,7 +66,18 @@ void setup() { SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); emptyBridge = new DeclarativeConfigPropertiesBridge( - Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); + Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig()), + Collections.emptyMap()); + } + + private static DeclarativeConfigPropertiesBridge createBridge( + Map translationMap) { + OpenTelemetryConfigurationModel model = + DeclarativeConfiguration.parse( + new ByteArrayInputStream(YAML.getBytes(StandardCharsets.UTF_8))); + return new DeclarativeConfigPropertiesBridge( + Objects.requireNonNull(SdkConfigProvider.create(model).getInstrumentationConfig()), + translationMap); } @Test @@ -126,21 +132,31 @@ void getProperties() { assertThat(bridge.getLong("otel.instrumentation.other-instrumentation.int_key", 1L)) .isEqualTo(1L); assertThat( - bridge.getDuration( - "otel.instrumentation.other-instrumentation.int_key", Duration.ofMillis(1))) + bridge.getDuration( + "otel.instrumentation.other-instrumentation.int_key", Duration.ofMillis(1))) .isEqualTo(Duration.ofMillis(1)); assertThat(bridge.getDouble("otel.instrumentation.other-instrumentation.double_key", 1.1)) .isEqualTo(1.1); assertThat( - bridge.getList( - "otel.instrumentation.other-instrumentation.list_key", - Arrays.asList("value1", "value2"))) + bridge.getList( + "otel.instrumentation.other-instrumentation.list_key", + Arrays.asList("value1", "value2"))) .isEqualTo(Arrays.asList("value1", "value2")); assertThat(bridge.getMap("otel.instrumentation.other-instrumentation.map_key", expectedMap)) .isEqualTo(expectedMap); + } + @Test + void vendor() { // verify vendor specific property names are preserved in unchanged form (prefix is not stripped // as for otel.instrumentation.*) assertThat(bridge.getBoolean("acme.full_name.preserved")).isTrue(); } + + @Test + void translation() { + DeclarativeConfigPropertiesBridge propertiesBridge = createBridge( + Collections.singletonMap("acme", "acme.full_name")); + assertThat(propertiesBridge.getBoolean("acme.preserved")).isTrue(); + } } diff --git a/inferred-spans/build.gradle.kts b/inferred-spans/build.gradle.kts index 98d5e33a3..bc89d6da9 100644 --- a/inferred-spans/build.gradle.kts +++ b/inferred-spans/build.gradle.kts @@ -9,10 +9,13 @@ description = "OpenTelemetry Java profiling based inferred spans module" otelJava.moduleName.set("io.opentelemetry.contrib.inferredspans") dependencies { + implementation(project(":declarative-config-bridge")) + annotationProcessor("com.google.auto.service:auto-service") compileOnly("com.google.auto.service:auto-service-annotations") compileOnly("io.opentelemetry:opentelemetry-sdk") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") compileOnly("io.opentelemetry.semconv:opentelemetry-semconv") implementation("com.lmax:disruptor") implementation("org.jctools:jctools-core") @@ -25,6 +28,7 @@ dependencies { testImplementation("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("io.opentelemetry:opentelemetry-sdk") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("io.opentelemetry:opentelemetry-api-incubator") testImplementation("io.opentelemetry:opentelemetry-exporter-logging") diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java new file mode 100644 index 000000000..fa55f06e4 --- /dev/null +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.inferredspans; + +import com.google.auto.service.AutoService; +import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import java.util.Collections; + +@AutoService(DeclarativeConfigurationCustomizerProvider.class) +public class InferredSpansCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { + + @Override + public void customize(DeclarativeConfigurationCustomizer customizer) { + customizer.addModelCustomizer( + model -> { + ConfigProperties configProperties = ConfigPropertiesUtil.resolveModel(model, + Collections.singletonMap("otel.inferred.spans", "inferred_spans")); + + return model; + }); + } + +} From 9fe79a1f383eac69a5122aa1e564a5a6983f8219 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 08:10:49 +0200 Subject: [PATCH 13/44] inferred spans --- .../autoconfigure/ConfigPropertiesUtil.java | 27 +++++---- .../DeclarativeConfigPropertiesBridge.java | 4 +- ...DeclarativeConfigPropertiesBridgeTest.java | 20 +++---- .../InferredSpansAutoConfig.java | 56 +++++++++++-------- .../InferredSpansComponentProvider.java | 33 +++++++++++ .../InferredSpansCustomizerProvider.java | 19 ++++++- .../InferredSpansCustomizerProviderTest.java | 41 ++++++++++++++ 7 files changed, 152 insertions(+), 48 deletions(-) create mode 100644 inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java create mode 100644 inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index e5167c966..da52fb1c9 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -14,6 +14,7 @@ import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; import java.util.Collections; import java.util.Map; +import javax.annotation.Nullable; public class ConfigPropertiesUtil { private ConfigPropertiesUtil() {} @@ -29,13 +30,8 @@ public static ConfigProperties resolveConfigProperties( ConfigProvider configProvider = AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); if (configProvider != null) { - DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); - - if (instrumentationConfig == null) { - instrumentationConfig = DeclarativeConfigProperties.empty(); - } - - return new DeclarativeConfigPropertiesBridge(instrumentationConfig, Collections.emptyMap()); + return resolveInstrumentationConfig( + configProvider.getInstrumentationConfig(), Collections.emptyMap()); } // Should never happen throw new IllegalStateException( @@ -46,9 +42,20 @@ public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel mode return resolveModel(model, Collections.emptyMap()); } - public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel model, Map translationMap) { - SdkConfigProvider configProvider = SdkConfigProvider.create(model); - DeclarativeConfigProperties instrumentationConfig = configProvider.getInstrumentationConfig(); + public static ConfigProperties resolveModel( + OpenTelemetryConfigurationModel model, Map translationMap) { + return resolveInstrumentationConfig( + SdkConfigProvider.create(model).getInstrumentationConfig(), translationMap); + } + + public static ConfigProperties resolveInstrumentationConfig( + @Nullable DeclarativeConfigProperties instrumentationConfig) { + return resolveInstrumentationConfig(instrumentationConfig, Collections.emptyMap()); + } + + public static ConfigProperties resolveInstrumentationConfig( + @Nullable DeclarativeConfigProperties instrumentationConfig, + Map translationMap) { if (instrumentationConfig == null) { instrumentationConfig = DeclarativeConfigProperties.empty(); } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 0cb6d17d6..11a16afbb 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -54,8 +54,8 @@ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { private final DeclarativeConfigProperties instrumentationJavaNode; private final Map translationMap; - DeclarativeConfigPropertiesBridge(DeclarativeConfigProperties instrumentationNode, - Map translationMap) { + DeclarativeConfigPropertiesBridge( + DeclarativeConfigProperties instrumentationNode, Map translationMap) { instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); this.translationMap = translationMap; } diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index 9ed47cd8c..a7722c5b9 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -4,9 +4,9 @@ */ package io.opentelemetry.contrib.sdk.autoconfigure; /* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ import static org.assertj.core.api.Assertions.assertThat; @@ -132,15 +132,15 @@ void getProperties() { assertThat(bridge.getLong("otel.instrumentation.other-instrumentation.int_key", 1L)) .isEqualTo(1L); assertThat( - bridge.getDuration( - "otel.instrumentation.other-instrumentation.int_key", Duration.ofMillis(1))) + bridge.getDuration( + "otel.instrumentation.other-instrumentation.int_key", Duration.ofMillis(1))) .isEqualTo(Duration.ofMillis(1)); assertThat(bridge.getDouble("otel.instrumentation.other-instrumentation.double_key", 1.1)) .isEqualTo(1.1); assertThat( - bridge.getList( - "otel.instrumentation.other-instrumentation.list_key", - Arrays.asList("value1", "value2"))) + bridge.getList( + "otel.instrumentation.other-instrumentation.list_key", + Arrays.asList("value1", "value2"))) .isEqualTo(Arrays.asList("value1", "value2")); assertThat(bridge.getMap("otel.instrumentation.other-instrumentation.map_key", expectedMap)) .isEqualTo(expectedMap); @@ -155,8 +155,8 @@ void vendor() { @Test void translation() { - DeclarativeConfigPropertiesBridge propertiesBridge = createBridge( - Collections.singletonMap("acme", "acme.full_name")); + DeclarativeConfigPropertiesBridge propertiesBridge = + createBridge(Collections.singletonMap("acme", "acme.full_name")); assertThat(propertiesBridge.getBoolean("acme.preserved")).isTrue(); } } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java index 9c8118ec5..39f99808c 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java @@ -44,30 +44,8 @@ public class InferredSpansAutoConfig implements AutoConfigurationCustomizerProvi public void customize(AutoConfigurationCustomizer config) { config.addTracerProviderCustomizer( (providerBuilder, properties) -> { - if (properties.getBoolean(ENABLED_OPTION, false)) { - InferredSpansProcessorBuilder builder = InferredSpansProcessor.builder(); - - PropertiesApplier applier = new PropertiesApplier(properties); - - applier.applyBool(LOGGING_OPTION, builder::profilerLoggingEnabled); - applier.applyBool(DIAGNOSTIC_FILES_OPTION, builder::backupDiagnosticFiles); - applier.applyInt(SAFEMODE_OPTION, builder::asyncProfilerSafeMode); - applier.applyBool(POSTPROCESSING_OPTION, builder::postProcessingEnabled); - applier.applyDuration(SAMPLING_INTERVAL_OPTION, builder::samplingInterval); - applier.applyDuration(MIN_DURATION_OPTION, builder::inferredSpansMinDuration); - applier.applyWildcards(INCLUDED_CLASSES_OPTION, builder::includedClasses); - applier.applyWildcards(EXCLUDED_CLASSES_OPTION, builder::excludedClasses); - applier.applyDuration(INTERVAL_OPTION, builder::profilerInterval); - applier.applyDuration(DURATION_OPTION, builder::profilingDuration); - applier.applyString(LIB_DIRECTORY_OPTION, builder::profilerLibDirectory); - - String parentOverrideHandlerName = properties.getString(PARENT_OVERRIDE_HANDLER_OPTION); - if (parentOverrideHandlerName != null && !parentOverrideHandlerName.isEmpty()) { - builder.parentOverrideHandler( - constructParentOverrideHandler(parentOverrideHandlerName)); - } - - providerBuilder.addSpanProcessor(builder.build()); + if (isEnabled(properties)) { + providerBuilder.addSpanProcessor(create(properties)); } else { log.finest( "Not enabling inferred spans processor because " + ENABLED_OPTION + " is not set"); @@ -76,6 +54,36 @@ public void customize(AutoConfigurationCustomizer config) { }); } + static InferredSpansProcessor create(ConfigProperties properties) { + InferredSpansProcessorBuilder builder = InferredSpansProcessor.builder(); + + PropertiesApplier applier = new PropertiesApplier(properties); + + applier.applyBool(LOGGING_OPTION, builder::profilerLoggingEnabled); + applier.applyBool(DIAGNOSTIC_FILES_OPTION, builder::backupDiagnosticFiles); + applier.applyInt(SAFEMODE_OPTION, builder::asyncProfilerSafeMode); + applier.applyBool(POSTPROCESSING_OPTION, builder::postProcessingEnabled); + applier.applyDuration(SAMPLING_INTERVAL_OPTION, builder::samplingInterval); + applier.applyDuration(MIN_DURATION_OPTION, builder::inferredSpansMinDuration); + applier.applyWildcards(INCLUDED_CLASSES_OPTION, builder::includedClasses); + applier.applyWildcards(EXCLUDED_CLASSES_OPTION, builder::excludedClasses); + applier.applyDuration(INTERVAL_OPTION, builder::profilerInterval); + applier.applyDuration(DURATION_OPTION, builder::profilingDuration); + applier.applyString(LIB_DIRECTORY_OPTION, builder::profilerLibDirectory); + + String parentOverrideHandlerName = properties.getString(PARENT_OVERRIDE_HANDLER_OPTION); + if (parentOverrideHandlerName != null && !parentOverrideHandlerName.isEmpty()) { + builder.parentOverrideHandler(constructParentOverrideHandler(parentOverrideHandlerName)); + } + + InferredSpansProcessor spanProcessor = builder.build(); + return spanProcessor; + } + + static boolean isEnabled(ConfigProperties properties) { + return properties.getBoolean(ENABLED_OPTION, false); + } + @SuppressWarnings("unchecked") private static BiConsumer constructParentOverrideHandler(String name) { try { diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java new file mode 100644 index 000000000..7563f3596 --- /dev/null +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.inferredspans; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class InferredSpansComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "inferred_spans"; + } + + @Override + public SpanProcessor create(DeclarativeConfigProperties config) { + return InferredSpansAutoConfig.create( + ConfigPropertiesUtil.resolveInstrumentationConfig( + config, InferredSpansCustomizerProvider.TRANSLATION_MAP)); + } + + @Override + public Class getType() { + return SpanProcessor.class; + } +} diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java index fa55f06e4..744f9b9e4 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java @@ -10,20 +10,35 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel; import java.util.Collections; +import java.util.Map; @AutoService(DeclarativeConfigurationCustomizerProvider.class) public class InferredSpansCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { + static final Map TRANSLATION_MAP = + Collections.singletonMap("otel.inferred.spans", "inferred_spans"); + @Override public void customize(DeclarativeConfigurationCustomizer customizer) { customizer.addModelCustomizer( model -> { - ConfigProperties configProperties = ConfigPropertiesUtil.resolveModel(model, - Collections.singletonMap("otel.inferred.spans", "inferred_spans")); + ConfigProperties configProperties = + ConfigPropertiesUtil.resolveModel(model, TRANSLATION_MAP); + + TracerProviderModel tracerProvider = model.getTracerProvider(); + if (tracerProvider != null && InferredSpansAutoConfig.isEnabled(configProperties)) { + tracerProvider.getProcessors().add(create()); + } return model; }); } + @SuppressWarnings("NullAway") + private static SpanProcessorModel create() { + return new SpanProcessorModel().withAdditionalProperty("inferred_spans", null); + } } diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java new file mode 100644 index 000000000..3b83a923f --- /dev/null +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.inferredspans; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; + +class InferredSpansCustomizerProviderTest { + + @Test + void declarativeConfig() { + String yaml = + "file_format: 0.4\n" + + "tracer_provider:\n" + + "instrumentation/development:\n" + + " java:\n" + + " inferred_spans:\n" + + " enabled: true\n"; + + OpenTelemetryConfigurationModel model = + DeclarativeConfiguration.parse( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + + new InferredSpansCustomizerProvider() + .customize( + c -> { + OpenTelemetryConfigurationModel configurationModel = c.apply(model); + assertThat(configurationModel.toString()) + .matches( + ".*SpanProcessorModel@.{8}\\[batch=,simple=,additionalProperties=\\{inferred_spans=null}.*"); + }); + } +} From 71f21b7c76b83b1774472e1c9604205cbc2e1a5c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 10:02:24 +0200 Subject: [PATCH 14/44] inferred spans --- .../autoconfigure/ConfigPropertiesUtil.java | 10 ++-- .../DeclarativeConfigPropertiesBridge.java | 28 ++++++++--- ...DeclarativeConfigPropertiesBridgeTest.java | 4 +- .../InferredSpansAutoConfig.java | 26 +++++----- .../InferredSpansComponentProvider.java | 7 ++- .../InferredSpansCustomizerProviderTest.java | 47 ++++++++++--------- 6 files changed, 72 insertions(+), 50 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index da52fb1c9..457e49b90 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -56,11 +56,13 @@ public static ConfigProperties resolveInstrumentationConfig( public static ConfigProperties resolveInstrumentationConfig( @Nullable DeclarativeConfigProperties instrumentationConfig, Map translationMap) { - if (instrumentationConfig == null) { - instrumentationConfig = DeclarativeConfigProperties.empty(); - } + return DeclarativeConfigPropertiesBridge.fromInstrumentationConfig( + instrumentationConfig, translationMap); + } - return new DeclarativeConfigPropertiesBridge(instrumentationConfig, translationMap); + public static ConfigProperties resolveConfig( + @Nullable DeclarativeConfigProperties config, Map translationMap) { + return DeclarativeConfigPropertiesBridge.create(config, translationMap); } public static String propertyYamlPath(String propertyName) { diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 11a16afbb..8acdc32a1 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -50,13 +50,27 @@ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; - // The node at .instrumentation.java - private final DeclarativeConfigProperties instrumentationJavaNode; + @Nullable private final DeclarativeConfigProperties baseNode; private final Map translationMap; - DeclarativeConfigPropertiesBridge( - DeclarativeConfigProperties instrumentationNode, Map translationMap) { - instrumentationJavaNode = instrumentationNode.getStructured("java", empty()); + static DeclarativeConfigPropertiesBridge fromInstrumentationConfig( + @Nullable DeclarativeConfigProperties instrumentationConfig, + Map translationMap) { + if (instrumentationConfig == null) { + instrumentationConfig = DeclarativeConfigProperties.empty(); + } + return new DeclarativeConfigPropertiesBridge( + instrumentationConfig.getStructured("java", empty()), translationMap); + } + + static DeclarativeConfigPropertiesBridge create( + @Nullable DeclarativeConfigProperties node, Map translationMap) { + return new DeclarativeConfigPropertiesBridge(node, translationMap); + } + + private DeclarativeConfigPropertiesBridge( + @Nullable DeclarativeConfigProperties baseNode, Map translationMap) { + this.baseNode = baseNode; this.translationMap = translationMap; } @@ -133,7 +147,7 @@ public Map getMap(String propertyName) { @Nullable private T getPropertyValue( String property, BiFunction extractor) { - if (instrumentationJavaNode == null) { + if (baseNode == null) { return null; } @@ -143,7 +157,7 @@ private T getPropertyValue( } // Extract the value by walking to the N-1 entry - DeclarativeConfigProperties target = instrumentationJavaNode; + DeclarativeConfigProperties target = baseNode; if (segments.length > 1) { for (int i = 0; i < segments.length - 1; i++) { target = target.getStructured(segments[i], empty()); diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index a7722c5b9..e02940d1c 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -65,7 +65,7 @@ void setup() { .withAdditionalProperty("instrumentation/development", new InstrumentationModel()); SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); emptyBridge = - new DeclarativeConfigPropertiesBridge( + DeclarativeConfigPropertiesBridge.fromInstrumentationConfig( Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig()), Collections.emptyMap()); } @@ -75,7 +75,7 @@ private static DeclarativeConfigPropertiesBridge createBridge( OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( new ByteArrayInputStream(YAML.getBytes(StandardCharsets.UTF_8))); - return new DeclarativeConfigPropertiesBridge( + return DeclarativeConfigPropertiesBridge.fromInstrumentationConfig( Objects.requireNonNull(SdkConfigProvider.create(model).getInstrumentationConfig()), translationMap); } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java index 39f99808c..c10b81db6 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java @@ -11,8 +11,10 @@ import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.trace.SpanProcessor; import java.time.Duration; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -44,17 +46,20 @@ public class InferredSpansAutoConfig implements AutoConfigurationCustomizerProvi public void customize(AutoConfigurationCustomizer config) { config.addTracerProviderCustomizer( (providerBuilder, properties) -> { - if (isEnabled(properties)) { - providerBuilder.addSpanProcessor(create(properties)); - } else { - log.finest( - "Not enabling inferred spans processor because " + ENABLED_OPTION + " is not set"); - } + providerBuilder.addSpanProcessor(create(properties, /* enableByDefault= */ false)); return providerBuilder; }); } - static InferredSpansProcessor create(ConfigProperties properties) { + static SpanProcessor create(ConfigProperties properties, boolean enableByDefault) { + if (!properties.getBoolean(ENABLED_OPTION, enableByDefault)) { + log.finest( + "Not creating inferred spans processor because " + + ENABLED_OPTION + + " is not set to true"); + return SpanProcessor.composite(Collections.emptyList()); + } + InferredSpansProcessorBuilder builder = InferredSpansProcessor.builder(); PropertiesApplier applier = new PropertiesApplier(properties); @@ -76,12 +81,7 @@ static InferredSpansProcessor create(ConfigProperties properties) { builder.parentOverrideHandler(constructParentOverrideHandler(parentOverrideHandlerName)); } - InferredSpansProcessor spanProcessor = builder.build(); - return spanProcessor; - } - - static boolean isEnabled(ConfigProperties properties) { - return properties.getBoolean(ENABLED_OPTION, false); + return builder.build(); } @SuppressWarnings("unchecked") diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java index 7563f3596..545bcc80c 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java @@ -10,10 +10,12 @@ import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.trace.SpanProcessor; +import java.util.Collections; @SuppressWarnings("rawtypes") @AutoService(ComponentProvider.class) public class InferredSpansComponentProvider implements ComponentProvider { + @Override public String getName() { return "inferred_spans"; @@ -22,8 +24,9 @@ public String getName() { @Override public SpanProcessor create(DeclarativeConfigProperties config) { return InferredSpansAutoConfig.create( - ConfigPropertiesUtil.resolveInstrumentationConfig( - config, InferredSpansCustomizerProvider.TRANSLATION_MAP)); + ConfigPropertiesUtil.resolveConfig( + config, Collections.singletonMap("otel.inferred.spans.", "")), + /* enableByDefault= */ true); } @Override diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java index 3b83a923f..0e5cc85cd 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java @@ -5,37 +5,40 @@ package io.opentelemetry.contrib.inferredspans; -import static org.assertj.core.api.Assertions.assertThat; - import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import org.junit.jupiter.api.Test; + import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; -import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; class InferredSpansCustomizerProviderTest { + private static final String FQDN = + "spanProcessor=io.opentelemetry.contrib.inferredspans.InferredSpansProcessor"; + + @Test + void enabled() { + assertThat(create("")).contains(FQDN); + } + @Test - void declarativeConfig() { + void disabled() { + assertThat(create("enabled: false")).doesNotContain(FQDN); + } + + private static String create(String enabled) { String yaml = "file_format: 0.4\n" + "tracer_provider:\n" - + "instrumentation/development:\n" - + " java:\n" - + " inferred_spans:\n" - + " enabled: true\n"; - - OpenTelemetryConfigurationModel model = - DeclarativeConfiguration.parse( - new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); - - new InferredSpansCustomizerProvider() - .customize( - c -> { - OpenTelemetryConfigurationModel configurationModel = c.apply(model); - assertThat(configurationModel.toString()) - .matches( - ".*SpanProcessorModel@.{8}\\[batch=,simple=,additionalProperties=\\{inferred_spans=null}.*"); - }); + + " processors:\n" + + " - inferred_spans:\n" + + " " + + enabled + + "\n"; + return DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))) + .toString(); } } From 0618b39c659ea663fe0aa8f05a2474763e4393c5 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 10:24:46 +0200 Subject: [PATCH 15/44] inferred spans --- .../InferredSpansAutoConfig.java | 18 +++----- .../InferredSpansComponentProvider.java | 3 +- .../InferredSpansCustomizerProvider.java | 44 ------------------- .../InferredSpansCustomizerProviderTest.java | 41 +++++++++-------- 4 files changed, 30 insertions(+), 76 deletions(-) delete mode 100644 inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java index c10b81db6..f944841d7 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java @@ -14,7 +14,6 @@ import io.opentelemetry.sdk.trace.SpanProcessor; import java.time.Duration; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -46,20 +45,17 @@ public class InferredSpansAutoConfig implements AutoConfigurationCustomizerProvi public void customize(AutoConfigurationCustomizer config) { config.addTracerProviderCustomizer( (providerBuilder, properties) -> { - providerBuilder.addSpanProcessor(create(properties, /* enableByDefault= */ false)); + if (properties.getBoolean(ENABLED_OPTION, false)) { + providerBuilder.addSpanProcessor(create(properties)); + } else { + log.finest( + "Not enabling inferred spans processor because " + ENABLED_OPTION + " is not set"); + } return providerBuilder; }); } - static SpanProcessor create(ConfigProperties properties, boolean enableByDefault) { - if (!properties.getBoolean(ENABLED_OPTION, enableByDefault)) { - log.finest( - "Not creating inferred spans processor because " - + ENABLED_OPTION - + " is not set to true"); - return SpanProcessor.composite(Collections.emptyList()); - } - + static SpanProcessor create(ConfigProperties properties) { InferredSpansProcessorBuilder builder = InferredSpansProcessor.builder(); PropertiesApplier applier = new PropertiesApplier(properties); diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java index 545bcc80c..21101d639 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java @@ -25,8 +25,7 @@ public String getName() { public SpanProcessor create(DeclarativeConfigProperties config) { return InferredSpansAutoConfig.create( ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap("otel.inferred.spans.", "")), - /* enableByDefault= */ true); + config, Collections.singletonMap("otel.inferred.spans.", ""))); } @Override diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java deleted file mode 100644 index 744f9b9e4..000000000 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.inferredspans; - -import com.google.auto.service.AutoService; -import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; -import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel; -import java.util.Collections; -import java.util.Map; - -@AutoService(DeclarativeConfigurationCustomizerProvider.class) -public class InferredSpansCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { - - static final Map TRANSLATION_MAP = - Collections.singletonMap("otel.inferred.spans", "inferred_spans"); - - @Override - public void customize(DeclarativeConfigurationCustomizer customizer) { - customizer.addModelCustomizer( - model -> { - ConfigProperties configProperties = - ConfigPropertiesUtil.resolveModel(model, TRANSLATION_MAP); - - TracerProviderModel tracerProvider = model.getTracerProvider(); - if (tracerProvider != null && InferredSpansAutoConfig.isEnabled(configProperties)) { - tracerProvider.getProcessors().add(create()); - } - - return model; - }); - } - - @SuppressWarnings("NullAway") - private static SpanProcessorModel create() { - return new SpanProcessorModel().withAdditionalProperty("inferred_spans", null); - } -} diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java index 0e5cc85cd..cca693e42 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.inferredspans; +import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; import org.junit.jupiter.api.Test; @@ -15,30 +16,32 @@ class InferredSpansCustomizerProviderTest { - private static final String FQDN = - "spanProcessor=io.opentelemetry.contrib.inferredspans.InferredSpansProcessor"; - - @Test - void enabled() { - assertThat(create("")).contains(FQDN); - } - @Test - void disabled() { - assertThat(create("enabled: false")).doesNotContain(FQDN); - } - - private static String create(String enabled) { + void declarativeConfig() { String yaml = "file_format: 0.4\n" + "tracer_provider:\n" + " processors:\n" + " - inferred_spans:\n" - + " " - + enabled - + "\n"; - return DeclarativeConfiguration.parseAndCreate( - new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))) - .toString(); + + " backup:\n" + + " diagnostic:\n" + + " files: true\n"; + + OpenTelemetrySdk sdk = + DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + + assertThat(sdk) + .extracting("tracerProvider") + .extracting("delegate") + .extracting("sharedState") + .extracting("activeSpanProcessor") + .extracting("profiler") + .extracting("config") + .extracting("backupDiagnosticFiles") + .isEqualTo(true); + + assertThat(sdk.toString()) + .contains("spanProcessor=io.opentelemetry.contrib.inferredspans.InferredSpansProcessor"); } } From 27fc12548e3079e8a39bb5fdaf08ac697b198b55 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 10:49:17 +0200 Subject: [PATCH 16/44] baggage processor --- baggage-processor/build.gradle.kts | 6 +++ .../BaggageLogRecordComponentProvider.java | 33 +++++++++++++++ .../processor/BaggageLogRecordProcessor.java | 12 +++++- .../processor/BaggageProcessorCustomizer.java | 41 ++++++++++++------- .../BaggageSpanComponentProvider.java | 33 +++++++++++++++ .../processor/BaggageSpanProcessor.java | 12 +++++- ...re.spi.AutoConfigurationCustomizerProvider | 1 - 7 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java create mode 100644 baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java delete mode 100644 baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider diff --git a/baggage-processor/build.gradle.kts b/baggage-processor/build.gradle.kts index 017158399..dac7f8cd0 100644 --- a/baggage-processor/build.gradle.kts +++ b/baggage-processor/build.gradle.kts @@ -8,11 +8,17 @@ description = "OpenTelemetry Baggage Span Processor" otelJava.moduleName.set("io.opentelemetry.contrib.baggage.processor") dependencies { + implementation(project(":declarative-config-bridge")) + + annotationProcessor("com.google.auto.service:auto-service") + compileOnly("com.google.auto.service:auto-service-annotations") api("io.opentelemetry:opentelemetry-api") api("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("org.mockito:mockito-inline") testImplementation("com.google.guava:guava") diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java new file mode 100644 index 000000000..3adaf9ff8 --- /dev/null +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.logs.LogRecordProcessor; +import java.util.Collections; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class BaggageLogRecordComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "baggage"; + } + + @Override + public LogRecordProcessor create(DeclarativeConfigProperties config) { + return BaggageProcessorCustomizer.createBaggageLogRecordProcessor(ConfigPropertiesUtil.resolveConfig( + config, Collections.singletonMap(BaggageProcessorCustomizer.LOG_PREFIX, ""))); + } + + @Override + public Class getType() { + return LogRecordProcessor.class; + } +} diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java index 4e8c91505..79fcbc313 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java @@ -23,17 +23,23 @@ public class BaggageLogRecordProcessor implements LogRecordProcessor { * created log record. */ public static BaggageLogRecordProcessor allowAllBaggageKeys() { - return new BaggageLogRecordProcessor(baggageKey -> true); + return new BaggageLogRecordProcessor(baggageKey -> true, false); } private final Predicate baggageKeyPredicate; + private boolean empty; /** * Creates a new {@link BaggageLogRecordProcessor} that copies only baggage entries with keys that * pass the provided filter into the newly created log record. */ public BaggageLogRecordProcessor(Predicate baggageKeyPredicate) { + this(baggageKeyPredicate, false); // we don't know if the predicate matches any keys + } + + BaggageLogRecordProcessor(Predicate baggageKeyPredicate, boolean empty) { this.baggageKeyPredicate = baggageKeyPredicate; + this.empty = empty; } @Override @@ -46,4 +52,8 @@ public void onEmit(Context context, ReadWriteLogRecord logRecord) { } }); } + + boolean isEmpty() { + return empty; + } } diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index da35512a3..b7dad1baf 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.baggage.processor; +import com.google.auto.service.AutoService; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -12,7 +13,11 @@ import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import java.util.List; +@AutoService(AutoConfigurationCustomizerProvider.class) public class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider { + static final String SPAN_PREFIX = "otel.java.experimental.span-attributes."; + static final String LOG_PREFIX = "otel.java.experimental.log-attributes."; + @Override public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { autoConfigurationCustomizer @@ -30,39 +35,47 @@ public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { private static void addSpanProcessor( SdkTracerProviderBuilder sdkTracerProviderBuilder, ConfigProperties config) { - List keys = - config.getList("otel.java.experimental.span-attributes.copy-from-baggage.include"); - - if (keys.isEmpty()) { + BaggageSpanProcessor processor = createBaggageSpanProcessor(config); + if (processor.isEmpty()) { return; } + sdkTracerProviderBuilder.addSpanProcessor(processor); + } - sdkTracerProviderBuilder.addSpanProcessor(createBaggageSpanProcessor(keys)); + static BaggageSpanProcessor createBaggageSpanProcessor(ConfigProperties config) { + return createBaggageSpanProcessor( + config.getList(SPAN_PREFIX + "copy-from-baggage.include")); } static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { - if (keys.size() == 1 && keys.get(0).equals("*")) { + if (matchAll(keys)) { return BaggageSpanProcessor.allowAllBaggageKeys(); } - return new BaggageSpanProcessor(keys::contains); + return new BaggageSpanProcessor(keys::contains, keys.isEmpty()); } private static void addLogRecordProcessor( SdkLoggerProviderBuilder sdkLoggerProviderBuilder, ConfigProperties config) { - List keys = - config.getList("otel.java.experimental.log-attributes.copy-from-baggage.include"); - - if (keys.isEmpty()) { + BaggageLogRecordProcessor processor = createBaggageLogRecordProcessor(config); + if (processor.isEmpty()) { return; } + sdkLoggerProviderBuilder.addLogRecordProcessor(processor); + } - sdkLoggerProviderBuilder.addLogRecordProcessor(createBaggageLogRecordProcessor(keys)); + static BaggageLogRecordProcessor createBaggageLogRecordProcessor(ConfigProperties config) { + return createBaggageLogRecordProcessor( + config.getList(LOG_PREFIX + "copy-from-baggage.include")); } static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List keys) { - if (keys.size() == 1 && keys.get(0).equals("*")) { + if (matchAll(keys)) { return BaggageLogRecordProcessor.allowAllBaggageKeys(); } - return new BaggageLogRecordProcessor(keys::contains); + return new BaggageLogRecordProcessor(keys::contains, keys.isEmpty()); + } + + private static boolean matchAll(List keys) { + return keys.size() == 1 && keys.get(0).equals("*"); } } diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java new file mode 100644 index 000000000..c0ae434c3 --- /dev/null +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; +import java.util.Collections; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class BaggageSpanComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "baggage"; + } + + @Override + public SpanProcessor create(DeclarativeConfigProperties config) { + return BaggageProcessorCustomizer.createBaggageSpanProcessor(ConfigPropertiesUtil.resolveConfig( + config, Collections.singletonMap(BaggageProcessorCustomizer.SPAN_PREFIX, ""))); + } + + @Override + public Class getType() { + return SpanProcessor.class; + } +} diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java index 5f0f53d03..e9c4798fc 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java @@ -18,13 +18,19 @@ */ public class BaggageSpanProcessor implements SpanProcessor { private final Predicate baggageKeyPredicate; + private boolean empty; /** * Creates a new {@link BaggageSpanProcessor} that copies only baggage entries with keys that pass * the provided filter into the newly created {@link io.opentelemetry.api.trace.Span}. */ public BaggageSpanProcessor(Predicate baggageKeyPredicate) { + this(baggageKeyPredicate, false); // we don't know if the predicate matches any keys + } + + BaggageSpanProcessor(Predicate baggageKeyPredicate, boolean empty) { this.baggageKeyPredicate = baggageKeyPredicate; + this.empty = empty; } /** @@ -32,7 +38,7 @@ public BaggageSpanProcessor(Predicate baggageKeyPredicate) { * created {@link io.opentelemetry.api.trace.Span}. */ public static BaggageSpanProcessor allowAllBaggageKeys() { - return new BaggageSpanProcessor(baggageKey -> true); + return new BaggageSpanProcessor(baggageKey -> true, false); } @Override @@ -58,4 +64,8 @@ public void onEnd(ReadableSpan span) {} public boolean isEndRequired() { return false; } + + boolean isEmpty() { + return empty; + } } diff --git a/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider b/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider deleted file mode 100644 index 8eb4afb06..000000000 --- a/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.contrib.baggage.processor.BaggageProcessorCustomizer From d27d7ce1798f4c593c6eb91b91750c58f0b26cef Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 10:55:11 +0200 Subject: [PATCH 17/44] format --- .../baggage/processor/BaggageLogRecordComponentProvider.java | 5 +++-- .../baggage/processor/BaggageProcessorCustomizer.java | 3 +-- .../baggage/processor/BaggageSpanComponentProvider.java | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java index 3adaf9ff8..b50b51572 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java @@ -22,8 +22,9 @@ public String getName() { @Override public LogRecordProcessor create(DeclarativeConfigProperties config) { - return BaggageProcessorCustomizer.createBaggageLogRecordProcessor(ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap(BaggageProcessorCustomizer.LOG_PREFIX, ""))); + return BaggageProcessorCustomizer.createBaggageLogRecordProcessor( + ConfigPropertiesUtil.resolveConfig( + config, Collections.singletonMap(BaggageProcessorCustomizer.LOG_PREFIX, ""))); } @Override diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index b7dad1baf..effcab6e2 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -43,8 +43,7 @@ private static void addSpanProcessor( } static BaggageSpanProcessor createBaggageSpanProcessor(ConfigProperties config) { - return createBaggageSpanProcessor( - config.getList(SPAN_PREFIX + "copy-from-baggage.include")); + return createBaggageSpanProcessor(config.getList(SPAN_PREFIX + "copy-from-baggage.include")); } static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java index c0ae434c3..e37251bb9 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java @@ -22,8 +22,9 @@ public String getName() { @Override public SpanProcessor create(DeclarativeConfigProperties config) { - return BaggageProcessorCustomizer.createBaggageSpanProcessor(ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap(BaggageProcessorCustomizer.SPAN_PREFIX, ""))); + return BaggageProcessorCustomizer.createBaggageSpanProcessor( + ConfigPropertiesUtil.resolveConfig( + config, Collections.singletonMap(BaggageProcessorCustomizer.SPAN_PREFIX, ""))); } @Override From 1e77d6f8c4ad3a745f0231434b8310639dec1c4a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 10:55:17 +0200 Subject: [PATCH 18/44] format --- .../inferredspans/InferredSpansCustomizerProviderTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java index cca693e42..20685cbeb 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java @@ -5,14 +5,13 @@ package io.opentelemetry.contrib.inferredspans; +import static org.assertj.core.api.Assertions.assertThat; + import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; -import org.junit.jupiter.api.Test; - import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; - -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; class InferredSpansCustomizerProviderTest { From 548c0c4c35f90ab7b67a88a60bc6dde7092b357f Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 11:09:19 +0200 Subject: [PATCH 19/44] stack trace span processor --- .../processor/BaggageLogRecordProcessor.java | 12 +------ .../processor/BaggageProcessorCustomizer.java | 29 ++++++++++------ .../processor/BaggageSpanProcessor.java | 12 +------ span-stacktrace/build.gradle.kts | 4 +++ .../stacktrace/StackTraceAutoConfig.java | 17 +++++----- .../StackTraceComponentProvider.java | 34 +++++++++++++++++++ 6 files changed, 67 insertions(+), 41 deletions(-) create mode 100644 span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java index 79fcbc313..4e8c91505 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java @@ -23,23 +23,17 @@ public class BaggageLogRecordProcessor implements LogRecordProcessor { * created log record. */ public static BaggageLogRecordProcessor allowAllBaggageKeys() { - return new BaggageLogRecordProcessor(baggageKey -> true, false); + return new BaggageLogRecordProcessor(baggageKey -> true); } private final Predicate baggageKeyPredicate; - private boolean empty; /** * Creates a new {@link BaggageLogRecordProcessor} that copies only baggage entries with keys that * pass the provided filter into the newly created log record. */ public BaggageLogRecordProcessor(Predicate baggageKeyPredicate) { - this(baggageKeyPredicate, false); // we don't know if the predicate matches any keys - } - - BaggageLogRecordProcessor(Predicate baggageKeyPredicate, boolean empty) { this.baggageKeyPredicate = baggageKeyPredicate; - this.empty = empty; } @Override @@ -52,8 +46,4 @@ public void onEmit(Context context, ReadWriteLogRecord logRecord) { } }); } - - boolean isEmpty() { - return empty; - } } diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index effcab6e2..b3ae3ee32 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -35,43 +35,50 @@ public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { private static void addSpanProcessor( SdkTracerProviderBuilder sdkTracerProviderBuilder, ConfigProperties config) { - BaggageSpanProcessor processor = createBaggageSpanProcessor(config); - if (processor.isEmpty()) { + if (spanKeys(config).isEmpty()) { return; } - sdkTracerProviderBuilder.addSpanProcessor(processor); + + sdkTracerProviderBuilder.addSpanProcessor(createBaggageSpanProcessor(config)); } static BaggageSpanProcessor createBaggageSpanProcessor(ConfigProperties config) { - return createBaggageSpanProcessor(config.getList(SPAN_PREFIX + "copy-from-baggage.include")); + return createBaggageSpanProcessor(spanKeys(config)); + } + + static List spanKeys(ConfigProperties config) { + return config.getList(SPAN_PREFIX + "copy-from-baggage.include"); } static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { if (matchAll(keys)) { return BaggageSpanProcessor.allowAllBaggageKeys(); } - return new BaggageSpanProcessor(keys::contains, keys.isEmpty()); + return new BaggageSpanProcessor(keys::contains); } private static void addLogRecordProcessor( SdkLoggerProviderBuilder sdkLoggerProviderBuilder, ConfigProperties config) { - BaggageLogRecordProcessor processor = createBaggageLogRecordProcessor(config); - if (processor.isEmpty()) { + if (logKeys(config).isEmpty()) { return; } - sdkLoggerProviderBuilder.addLogRecordProcessor(processor); + + sdkLoggerProviderBuilder.addLogRecordProcessor(createBaggageLogRecordProcessor(config)); } static BaggageLogRecordProcessor createBaggageLogRecordProcessor(ConfigProperties config) { - return createBaggageLogRecordProcessor( - config.getList(LOG_PREFIX + "copy-from-baggage.include")); + return createBaggageLogRecordProcessor(logKeys(config)); + } + + static List logKeys(ConfigProperties config) { + return config.getList(LOG_PREFIX + "copy-from-baggage.include"); } static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List keys) { if (matchAll(keys)) { return BaggageLogRecordProcessor.allowAllBaggageKeys(); } - return new BaggageLogRecordProcessor(keys::contains, keys.isEmpty()); + return new BaggageLogRecordProcessor(keys::contains); } private static boolean matchAll(List keys) { diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java index e9c4798fc..5f0f53d03 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java @@ -18,19 +18,13 @@ */ public class BaggageSpanProcessor implements SpanProcessor { private final Predicate baggageKeyPredicate; - private boolean empty; /** * Creates a new {@link BaggageSpanProcessor} that copies only baggage entries with keys that pass * the provided filter into the newly created {@link io.opentelemetry.api.trace.Span}. */ public BaggageSpanProcessor(Predicate baggageKeyPredicate) { - this(baggageKeyPredicate, false); // we don't know if the predicate matches any keys - } - - BaggageSpanProcessor(Predicate baggageKeyPredicate, boolean empty) { this.baggageKeyPredicate = baggageKeyPredicate; - this.empty = empty; } /** @@ -38,7 +32,7 @@ public BaggageSpanProcessor(Predicate baggageKeyPredicate) { * created {@link io.opentelemetry.api.trace.Span}. */ public static BaggageSpanProcessor allowAllBaggageKeys() { - return new BaggageSpanProcessor(baggageKey -> true, false); + return new BaggageSpanProcessor(baggageKey -> true); } @Override @@ -64,8 +58,4 @@ public void onEnd(ReadableSpan span) {} public boolean isEndRequired() { return false; } - - boolean isEmpty() { - return empty; - } } diff --git a/span-stacktrace/build.gradle.kts b/span-stacktrace/build.gradle.kts index 4033b0177..a9fa79e77 100644 --- a/span-stacktrace/build.gradle.kts +++ b/span-stacktrace/build.gradle.kts @@ -7,6 +7,8 @@ description = "OpenTelemetry Java span stacktrace capture module" otelJava.moduleName.set("io.opentelemetry.contrib.stacktrace") dependencies { + implementation(project(":declarative-config-bridge")) + annotationProcessor("com.google.auto.service:auto-service") compileOnly("com.google.auto.service:auto-service-annotations") @@ -15,8 +17,10 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") compileOnly("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("io.opentelemetry.semconv:opentelemetry-semconv") diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java index 2315d2a10..189934689 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java @@ -23,25 +23,26 @@ public class StackTraceAutoConfig implements AutoConfigurationCustomizerProvider private static final Logger log = Logger.getLogger(StackTraceAutoConfig.class.getName()); - private static final String CONFIG_MIN_DURATION = - "otel.java.experimental.span-stacktrace.min.duration"; + static final String PREFIX = "otel.java.experimental.span-stacktrace."; + private static final String CONFIG_MIN_DURATION = PREFIX + "min.duration"; private static final Duration CONFIG_MIN_DURATION_DEFAULT = Duration.ofMillis(5); - - private static final String CONFIG_FILTER = "otel.java.experimental.span-stacktrace.filter"; + private static final String CONFIG_FILTER = PREFIX + "filter"; @Override public void customize(AutoConfigurationCustomizer config) { config.addTracerProviderCustomizer( (providerBuilder, properties) -> { - long minDuration = getMinDuration(properties); - if (minDuration >= 0) { - Predicate filter = getFilterPredicate(properties); - providerBuilder.addSpanProcessor(new StackTraceSpanProcessor(minDuration, filter)); + if (getMinDuration(properties) >= 0) { + providerBuilder.addSpanProcessor(create(properties)); } return providerBuilder; }); } + static StackTraceSpanProcessor create(ConfigProperties properties) { + return new StackTraceSpanProcessor(getMinDuration(properties), getFilterPredicate(properties)); + } + // package-private for testing static long getMinDuration(ConfigProperties properties) { long minDuration = diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java new file mode 100644 index 000000000..5606a53a3 --- /dev/null +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.stacktrace; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; +import java.util.Collections; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class StackTraceComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "stacktrace"; + } + + @Override + public SpanProcessor create(DeclarativeConfigProperties config) { + return StackTraceAutoConfig.create( + ConfigPropertiesUtil.resolveConfig( + config, Collections.singletonMap(StackTraceAutoConfig.PREFIX, ""))); + } + + @Override + public Class getType() { + return SpanProcessor.class; + } +} From 092fce32a2279226760b95ddbf3fb2fbf4cc7a8a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 11:12:57 +0200 Subject: [PATCH 20/44] stack trace span processor --- .../processor/BaggageProcessorCustomizer.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index b3ae3ee32..3dbf017b4 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -46,10 +46,6 @@ static BaggageSpanProcessor createBaggageSpanProcessor(ConfigProperties config) return createBaggageSpanProcessor(spanKeys(config)); } - static List spanKeys(ConfigProperties config) { - return config.getList(SPAN_PREFIX + "copy-from-baggage.include"); - } - static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { if (matchAll(keys)) { return BaggageSpanProcessor.allowAllBaggageKeys(); @@ -57,6 +53,10 @@ static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { return new BaggageSpanProcessor(keys::contains); } + static List spanKeys(ConfigProperties config) { + return config.getList(SPAN_PREFIX + "copy-from-baggage.include"); + } + private static void addLogRecordProcessor( SdkLoggerProviderBuilder sdkLoggerProviderBuilder, ConfigProperties config) { if (logKeys(config).isEmpty()) { @@ -70,10 +70,6 @@ static BaggageLogRecordProcessor createBaggageLogRecordProcessor(ConfigPropertie return createBaggageLogRecordProcessor(logKeys(config)); } - static List logKeys(ConfigProperties config) { - return config.getList(LOG_PREFIX + "copy-from-baggage.include"); - } - static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List keys) { if (matchAll(keys)) { return BaggageLogRecordProcessor.allowAllBaggageKeys(); @@ -81,6 +77,10 @@ static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List ke return new BaggageLogRecordProcessor(keys::contains); } + static List logKeys(ConfigProperties config) { + return config.getList(LOG_PREFIX + "copy-from-baggage.include"); + } + private static boolean matchAll(List keys) { return keys.size() == 1 && keys.get(0).equals("*"); } From dd100551ec6aaa081b278c5181db69ab0a801dae Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 11:16:37 +0200 Subject: [PATCH 21/44] fix --- baggage-processor/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/baggage-processor/build.gradle.kts b/baggage-processor/build.gradle.kts index dac7f8cd0..af21261aa 100644 --- a/baggage-processor/build.gradle.kts +++ b/baggage-processor/build.gradle.kts @@ -17,6 +17,8 @@ dependencies { implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + testAnnotationProcessor("com.google.auto.service:auto-service") + testCompileOnly("com.google.auto.service:auto-service-annotations") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") From 444833f13d4ffefdae2efa1a81703ae5d71b53df Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 12:38:52 +0200 Subject: [PATCH 22/44] fix --- .../processor/BaggageLogRecordComponentProvider.java | 2 +- .../baggage/processor/BaggageProcessorCustomizer.java | 6 ++---- .../baggage/processor/BaggageSpanComponentProvider.java | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java index b50b51572..db309e726 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java @@ -24,7 +24,7 @@ public String getName() { public LogRecordProcessor create(DeclarativeConfigProperties config) { return BaggageProcessorCustomizer.createBaggageLogRecordProcessor( ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap(BaggageProcessorCustomizer.LOG_PREFIX, ""))); + config, Collections.singletonMap("otel.java.experimental.log-attributes.", ""))); } @Override diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index 3dbf017b4..08a7fcf61 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -15,8 +15,6 @@ @AutoService(AutoConfigurationCustomizerProvider.class) public class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider { - static final String SPAN_PREFIX = "otel.java.experimental.span-attributes."; - static final String LOG_PREFIX = "otel.java.experimental.log-attributes."; @Override public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { @@ -54,7 +52,7 @@ static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { } static List spanKeys(ConfigProperties config) { - return config.getList(SPAN_PREFIX + "copy-from-baggage.include"); + return config.getList("otel.java.experimental.span-attributes.copy-from-baggage.include"); } private static void addLogRecordProcessor( @@ -78,7 +76,7 @@ static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List ke } static List logKeys(ConfigProperties config) { - return config.getList(LOG_PREFIX + "copy-from-baggage.include"); + return config.getList("otel.java.experimental.log-attributes.copy-from-baggage.include"); } private static boolean matchAll(List keys) { diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java index e37251bb9..69227802f 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java @@ -24,7 +24,7 @@ public String getName() { public SpanProcessor create(DeclarativeConfigProperties config) { return BaggageProcessorCustomizer.createBaggageSpanProcessor( ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap(BaggageProcessorCustomizer.SPAN_PREFIX, ""))); + config, Collections.singletonMap("otel.java.experimental.span-attributes.", ""))); } @Override From 4211e85e814f2b7612171efcf61abedcf1d58155 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 13:36:43 +0200 Subject: [PATCH 23/44] fix --- .../processor/BaggageProcessorCustomizerTest.java | 4 ++-- .../InferredSpansCustomizerProviderTest.java | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java index bfa8835ae..f30371ff5 100644 --- a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java @@ -103,9 +103,9 @@ private static OpenTelemetrySdk getOpenTelemetrySdk( // We set the export interval of the spans to 10 ms. The default value is 5 // seconds. "otel.bsp.schedule.delay", // span exporter - "10", + "100", "otel.blrp.schedule.delay", // log exporter - "10", + "100", "otel.traces.exporter", MEMORY_EXPORTER, "otel.metrics.exporter", diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java index 20685cbeb..ea1665d70 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java @@ -7,14 +7,25 @@ import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.contrib.inferredspans.internal.ProfilingActivationListener; +import io.opentelemetry.contrib.inferredspans.internal.util.OtelReflectionUtils; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class InferredSpansCustomizerProviderTest { + @BeforeEach + @AfterEach + public void resetGlobalOtel() { + ProfilingActivationListener.ensureInitialized(); + OtelReflectionUtils.shutdownAndResetGlobalOtel(); + } + @Test void declarativeConfig() { String yaml = @@ -39,8 +50,5 @@ void declarativeConfig() { .extracting("config") .extracting("backupDiagnosticFiles") .isEqualTo(true); - - assertThat(sdk.toString()) - .contains("spanProcessor=io.opentelemetry.contrib.inferredspans.InferredSpansProcessor"); } } From e4de567d4b5398baceb28439b48484b95e88f862 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 14:00:40 +0200 Subject: [PATCH 24/44] make temp dir more reliable --- .../inferredspans/InferredSpansProcessor.java | 3 +- .../internal/SamplingProfiler.java | 10 ++++-- .../internal/SamplingProfilerTest.java | 32 ++++--------------- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java index 22f59ba53..b96163b48 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java @@ -49,7 +49,8 @@ public class InferredSpansProcessor implements SpanProcessor { boolean startScheduledProfiling, @Nullable File activationEventsFile, @Nullable File jfrFile) { - profiler = new SamplingProfiler(config, clock, this::getTracer, activationEventsFile, jfrFile); + profiler = + new SamplingProfiler(config, clock, this::getTracer, activationEventsFile, jfrFile, null); if (startScheduledProfiling) { profiler.start(); } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java index 61e5f75a7..4bd392210 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java @@ -149,6 +149,7 @@ public class SamplingProfiler implements Runnable { private final ProfilingActivationListener activationListener; private final Supplier tracerProvider; + @Nullable private final File tempDir; private final AsyncProfiler profiler; @@ -168,9 +169,11 @@ public SamplingProfiler( SpanAnchoredClock nanoClock, Supplier tracerProvider, @Nullable File activationEventsFile, - @Nullable File jfrFile) { + @Nullable File jfrFile, + @Nullable File tempDir) { this.config = config; this.tracerProvider = tracerProvider; + this.tempDir = tempDir; this.scheduler = Executors.newSingleThreadScheduledExecutor( r -> { @@ -250,12 +253,13 @@ boolean isProfilingActiveOnThread(Thread thread) { private synchronized void createFilesIfRequired() throws IOException { if (jfrFile == null || !jfrFile.exists()) { - jfrFile = File.createTempFile("otel-inferred-traces-", ".jfr"); + jfrFile = File.createTempFile("otel-inferred-traces-", ".jfr", tempDir); jfrFile.deleteOnExit(); canDeleteJfrFile = true; } if (activationEventsFile == null || !activationEventsFile.exists()) { - activationEventsFile = File.createTempFile("otel-inferred-activation-events-", ".bin"); + activationEventsFile = + File.createTempFile("otel-inferred-activation-events-", ".bin", tempDir); activationEventsFile.deleteOnExit(); canDeleteActivationEventsFile = true; } diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java index b97ce8729..ff4a8def5 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java @@ -32,12 +32,12 @@ import java.util.stream.Stream; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.condition.OS; +import org.junit.jupiter.api.io.TempDir; // async-profiler doesn't work on Windows @DisabledOnOs(OS.WINDOWS) @@ -46,11 +46,7 @@ class SamplingProfilerTest { private ProfilerTestSetup setup; - @BeforeEach - void setup() { - // avoids any test failure to make other tests to fail - getProfilerTempFiles().forEach(SamplingProfilerTest::silentDeleteFile); - } + @TempDir private Path tempDir; @AfterEach void tearDown() { @@ -58,7 +54,6 @@ void tearDown() { setup.close(); setup = null; } - getProfilerTempFiles().forEach(SamplingProfilerTest::silentDeleteFile); } @Test @@ -117,8 +112,8 @@ void shouldNotDeleteProvidedFiles() throws Exception { defaultConfig = ProfilerTestSetup.extractProfilerImpl(profiler1).getConfig(); } - Path tempFile1 = Files.createTempFile("otel-inferred-provided", "test.bin"); - Path tempFile2 = Files.createTempFile("otel-inferred-provided", "test.jfr"); + Path tempFile1 = Files.createTempFile(tempDir, "otel-inferred-provided", "test.bin"); + Path tempFile2 = Files.createTempFile(tempDir, "otel-inferred-provided", "test.jfr"); try (OpenTelemetrySdk sdk = OpenTelemetrySdk.builder().build()) { @@ -128,7 +123,8 @@ void shouldNotDeleteProvidedFiles() throws Exception { new FixedClock(), () -> sdk.getTracer("my-tracer"), tempFile1.toFile(), - tempFile2.toFile()); + tempFile2.toFile(), + tempDir.toFile()); otherProfiler.start(); awaitProfilerStarted(otherProfiler); @@ -333,20 +329,4 @@ private void setupProfiler(Consumer configCustomi configCustomizer.accept(config); }); } - - private static void awaitProfilerStarted(SamplingProfiler profiler) { - // ensure profiler is initialized - await() - .pollDelay(Duration.ofMillis(10)) - .timeout(Duration.ofSeconds(6)) - .until(() -> profiler.getProfilingSessions() > 1); - } - - private static void silentDeleteFile(Path f) { - try { - Files.delete(f); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } } From 19d017d770590e5cf2c6ee564935f6ae3e02c34b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 14:05:17 +0200 Subject: [PATCH 25/44] make temp dir more reliable --- .../inferredspans/internal/SamplingProfilerTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java index ff4a8def5..1e9d97807 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java @@ -329,4 +329,12 @@ private void setupProfiler(Consumer configCustomi configCustomizer.accept(config); }); } + + private static void awaitProfilerStarted(SamplingProfiler profiler) { + // ensure profiler is initialized + await() + .pollDelay(Duration.ofMillis(10)) + .timeout(Duration.ofSeconds(6)) + .until(() -> profiler.getProfilingSessions() > 1); + } } From fb4a7ef617b7e0956f14310cd04b46ada4f6fc00 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 15 Jul 2025 14:10:12 +0200 Subject: [PATCH 26/44] revert inferred spans (flaky) --- inferred-spans/build.gradle.kts | 4 -- .../InferredSpansAutoConfig.java | 50 ++++++++--------- .../InferredSpansComponentProvider.java | 35 ------------ .../inferredspans/InferredSpansProcessor.java | 3 +- .../internal/SamplingProfiler.java | 10 ++-- .../InferredSpansCustomizerProviderTest.java | 54 ------------------- .../internal/SamplingProfilerTest.java | 24 ++++++--- 7 files changed, 45 insertions(+), 135 deletions(-) delete mode 100644 inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java delete mode 100644 inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java diff --git a/inferred-spans/build.gradle.kts b/inferred-spans/build.gradle.kts index bc89d6da9..98d5e33a3 100644 --- a/inferred-spans/build.gradle.kts +++ b/inferred-spans/build.gradle.kts @@ -9,13 +9,10 @@ description = "OpenTelemetry Java profiling based inferred spans module" otelJava.moduleName.set("io.opentelemetry.contrib.inferredspans") dependencies { - implementation(project(":declarative-config-bridge")) - annotationProcessor("com.google.auto.service:auto-service") compileOnly("com.google.auto.service:auto-service-annotations") compileOnly("io.opentelemetry:opentelemetry-sdk") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") compileOnly("io.opentelemetry.semconv:opentelemetry-semconv") implementation("com.lmax:disruptor") implementation("org.jctools:jctools-core") @@ -28,7 +25,6 @@ dependencies { testImplementation("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("io.opentelemetry:opentelemetry-sdk") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("io.opentelemetry:opentelemetry-api-incubator") testImplementation("io.opentelemetry:opentelemetry-exporter-logging") diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java index f944841d7..9c8118ec5 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java @@ -11,7 +11,6 @@ import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.trace.SpanProcessor; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -46,7 +45,29 @@ public void customize(AutoConfigurationCustomizer config) { config.addTracerProviderCustomizer( (providerBuilder, properties) -> { if (properties.getBoolean(ENABLED_OPTION, false)) { - providerBuilder.addSpanProcessor(create(properties)); + InferredSpansProcessorBuilder builder = InferredSpansProcessor.builder(); + + PropertiesApplier applier = new PropertiesApplier(properties); + + applier.applyBool(LOGGING_OPTION, builder::profilerLoggingEnabled); + applier.applyBool(DIAGNOSTIC_FILES_OPTION, builder::backupDiagnosticFiles); + applier.applyInt(SAFEMODE_OPTION, builder::asyncProfilerSafeMode); + applier.applyBool(POSTPROCESSING_OPTION, builder::postProcessingEnabled); + applier.applyDuration(SAMPLING_INTERVAL_OPTION, builder::samplingInterval); + applier.applyDuration(MIN_DURATION_OPTION, builder::inferredSpansMinDuration); + applier.applyWildcards(INCLUDED_CLASSES_OPTION, builder::includedClasses); + applier.applyWildcards(EXCLUDED_CLASSES_OPTION, builder::excludedClasses); + applier.applyDuration(INTERVAL_OPTION, builder::profilerInterval); + applier.applyDuration(DURATION_OPTION, builder::profilingDuration); + applier.applyString(LIB_DIRECTORY_OPTION, builder::profilerLibDirectory); + + String parentOverrideHandlerName = properties.getString(PARENT_OVERRIDE_HANDLER_OPTION); + if (parentOverrideHandlerName != null && !parentOverrideHandlerName.isEmpty()) { + builder.parentOverrideHandler( + constructParentOverrideHandler(parentOverrideHandlerName)); + } + + providerBuilder.addSpanProcessor(builder.build()); } else { log.finest( "Not enabling inferred spans processor because " + ENABLED_OPTION + " is not set"); @@ -55,31 +76,6 @@ public void customize(AutoConfigurationCustomizer config) { }); } - static SpanProcessor create(ConfigProperties properties) { - InferredSpansProcessorBuilder builder = InferredSpansProcessor.builder(); - - PropertiesApplier applier = new PropertiesApplier(properties); - - applier.applyBool(LOGGING_OPTION, builder::profilerLoggingEnabled); - applier.applyBool(DIAGNOSTIC_FILES_OPTION, builder::backupDiagnosticFiles); - applier.applyInt(SAFEMODE_OPTION, builder::asyncProfilerSafeMode); - applier.applyBool(POSTPROCESSING_OPTION, builder::postProcessingEnabled); - applier.applyDuration(SAMPLING_INTERVAL_OPTION, builder::samplingInterval); - applier.applyDuration(MIN_DURATION_OPTION, builder::inferredSpansMinDuration); - applier.applyWildcards(INCLUDED_CLASSES_OPTION, builder::includedClasses); - applier.applyWildcards(EXCLUDED_CLASSES_OPTION, builder::excludedClasses); - applier.applyDuration(INTERVAL_OPTION, builder::profilerInterval); - applier.applyDuration(DURATION_OPTION, builder::profilingDuration); - applier.applyString(LIB_DIRECTORY_OPTION, builder::profilerLibDirectory); - - String parentOverrideHandlerName = properties.getString(PARENT_OVERRIDE_HANDLER_OPTION); - if (parentOverrideHandlerName != null && !parentOverrideHandlerName.isEmpty()) { - builder.parentOverrideHandler(constructParentOverrideHandler(parentOverrideHandlerName)); - } - - return builder.build(); - } - @SuppressWarnings("unchecked") private static BiConsumer constructParentOverrideHandler(String name) { try { diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java deleted file mode 100644 index 21101d639..000000000 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansComponentProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.inferredspans; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; -import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; -import io.opentelemetry.sdk.trace.SpanProcessor; -import java.util.Collections; - -@SuppressWarnings("rawtypes") -@AutoService(ComponentProvider.class) -public class InferredSpansComponentProvider implements ComponentProvider { - - @Override - public String getName() { - return "inferred_spans"; - } - - @Override - public SpanProcessor create(DeclarativeConfigProperties config) { - return InferredSpansAutoConfig.create( - ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap("otel.inferred.spans.", ""))); - } - - @Override - public Class getType() { - return SpanProcessor.class; - } -} diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java index b96163b48..22f59ba53 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java @@ -49,8 +49,7 @@ public class InferredSpansProcessor implements SpanProcessor { boolean startScheduledProfiling, @Nullable File activationEventsFile, @Nullable File jfrFile) { - profiler = - new SamplingProfiler(config, clock, this::getTracer, activationEventsFile, jfrFile, null); + profiler = new SamplingProfiler(config, clock, this::getTracer, activationEventsFile, jfrFile); if (startScheduledProfiling) { profiler.start(); } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java index 4bd392210..61e5f75a7 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java @@ -149,7 +149,6 @@ public class SamplingProfiler implements Runnable { private final ProfilingActivationListener activationListener; private final Supplier tracerProvider; - @Nullable private final File tempDir; private final AsyncProfiler profiler; @@ -169,11 +168,9 @@ public SamplingProfiler( SpanAnchoredClock nanoClock, Supplier tracerProvider, @Nullable File activationEventsFile, - @Nullable File jfrFile, - @Nullable File tempDir) { + @Nullable File jfrFile) { this.config = config; this.tracerProvider = tracerProvider; - this.tempDir = tempDir; this.scheduler = Executors.newSingleThreadScheduledExecutor( r -> { @@ -253,13 +250,12 @@ boolean isProfilingActiveOnThread(Thread thread) { private synchronized void createFilesIfRequired() throws IOException { if (jfrFile == null || !jfrFile.exists()) { - jfrFile = File.createTempFile("otel-inferred-traces-", ".jfr", tempDir); + jfrFile = File.createTempFile("otel-inferred-traces-", ".jfr"); jfrFile.deleteOnExit(); canDeleteJfrFile = true; } if (activationEventsFile == null || !activationEventsFile.exists()) { - activationEventsFile = - File.createTempFile("otel-inferred-activation-events-", ".bin", tempDir); + activationEventsFile = File.createTempFile("otel-inferred-activation-events-", ".bin"); activationEventsFile.deleteOnExit(); canDeleteActivationEventsFile = true; } diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java deleted file mode 100644 index ea1665d70..000000000 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansCustomizerProviderTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.inferredspans; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.contrib.inferredspans.internal.ProfilingActivationListener; -import io.opentelemetry.contrib.inferredspans.internal.util.OtelReflectionUtils; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class InferredSpansCustomizerProviderTest { - - @BeforeEach - @AfterEach - public void resetGlobalOtel() { - ProfilingActivationListener.ensureInitialized(); - OtelReflectionUtils.shutdownAndResetGlobalOtel(); - } - - @Test - void declarativeConfig() { - String yaml = - "file_format: 0.4\n" - + "tracer_provider:\n" - + " processors:\n" - + " - inferred_spans:\n" - + " backup:\n" - + " diagnostic:\n" - + " files: true\n"; - - OpenTelemetrySdk sdk = - DeclarativeConfiguration.parseAndCreate( - new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); - - assertThat(sdk) - .extracting("tracerProvider") - .extracting("delegate") - .extracting("sharedState") - .extracting("activeSpanProcessor") - .extracting("profiler") - .extracting("config") - .extracting("backupDiagnosticFiles") - .isEqualTo(true); - } -} diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java index 1e9d97807..b97ce8729 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerTest.java @@ -32,12 +32,12 @@ import java.util.stream.Stream; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledForJreRange; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.JRE; import org.junit.jupiter.api.condition.OS; -import org.junit.jupiter.api.io.TempDir; // async-profiler doesn't work on Windows @DisabledOnOs(OS.WINDOWS) @@ -46,7 +46,11 @@ class SamplingProfilerTest { private ProfilerTestSetup setup; - @TempDir private Path tempDir; + @BeforeEach + void setup() { + // avoids any test failure to make other tests to fail + getProfilerTempFiles().forEach(SamplingProfilerTest::silentDeleteFile); + } @AfterEach void tearDown() { @@ -54,6 +58,7 @@ void tearDown() { setup.close(); setup = null; } + getProfilerTempFiles().forEach(SamplingProfilerTest::silentDeleteFile); } @Test @@ -112,8 +117,8 @@ void shouldNotDeleteProvidedFiles() throws Exception { defaultConfig = ProfilerTestSetup.extractProfilerImpl(profiler1).getConfig(); } - Path tempFile1 = Files.createTempFile(tempDir, "otel-inferred-provided", "test.bin"); - Path tempFile2 = Files.createTempFile(tempDir, "otel-inferred-provided", "test.jfr"); + Path tempFile1 = Files.createTempFile("otel-inferred-provided", "test.bin"); + Path tempFile2 = Files.createTempFile("otel-inferred-provided", "test.jfr"); try (OpenTelemetrySdk sdk = OpenTelemetrySdk.builder().build()) { @@ -123,8 +128,7 @@ void shouldNotDeleteProvidedFiles() throws Exception { new FixedClock(), () -> sdk.getTracer("my-tracer"), tempFile1.toFile(), - tempFile2.toFile(), - tempDir.toFile()); + tempFile2.toFile()); otherProfiler.start(); awaitProfilerStarted(otherProfiler); @@ -337,4 +341,12 @@ private static void awaitProfilerStarted(SamplingProfiler profiler) { .timeout(Duration.ofSeconds(6)) .until(() -> profiler.getProfilingSessions() > 1); } + + private static void silentDeleteFile(Path f) { + try { + Files.delete(f); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } } From a9d9c050d6776c14fe4893b458ce6d2728ecdd59 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 16 Jul 2025 09:13:18 +0200 Subject: [PATCH 27/44] baggage is in a separate PR --- baggage-processor/build.gradle.kts | 8 ---- .../BaggageLogRecordComponentProvider.java | 34 --------------- .../processor/BaggageProcessorCustomizer.java | 41 ++++++------------- .../BaggageSpanComponentProvider.java | 34 --------------- ...re.spi.AutoConfigurationCustomizerProvider | 1 + .../BaggageProcessorCustomizerTest.java | 4 +- 6 files changed, 15 insertions(+), 107 deletions(-) delete mode 100644 baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java delete mode 100644 baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java create mode 100644 baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider diff --git a/baggage-processor/build.gradle.kts b/baggage-processor/build.gradle.kts index af21261aa..017158399 100644 --- a/baggage-processor/build.gradle.kts +++ b/baggage-processor/build.gradle.kts @@ -8,19 +8,11 @@ description = "OpenTelemetry Baggage Span Processor" otelJava.moduleName.set("io.opentelemetry.contrib.baggage.processor") dependencies { - implementation(project(":declarative-config-bridge")) - - annotationProcessor("com.google.auto.service:auto-service") - compileOnly("com.google.auto.service:auto-service-annotations") api("io.opentelemetry:opentelemetry-api") api("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") - testAnnotationProcessor("com.google.auto.service:auto-service") - testCompileOnly("com.google.auto.service:auto-service-annotations") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("org.mockito:mockito-inline") testImplementation("com.google.guava:guava") diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java deleted file mode 100644 index db309e726..000000000 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.baggage.processor; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; -import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; -import io.opentelemetry.sdk.logs.LogRecordProcessor; -import java.util.Collections; - -@SuppressWarnings("rawtypes") -@AutoService(ComponentProvider.class) -public class BaggageLogRecordComponentProvider implements ComponentProvider { - @Override - public String getName() { - return "baggage"; - } - - @Override - public LogRecordProcessor create(DeclarativeConfigProperties config) { - return BaggageProcessorCustomizer.createBaggageLogRecordProcessor( - ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap("otel.java.experimental.log-attributes.", ""))); - } - - @Override - public Class getType() { - return LogRecordProcessor.class; - } -} diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index 08a7fcf61..da35512a3 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -5,7 +5,6 @@ package io.opentelemetry.contrib.baggage.processor; -import com.google.auto.service.AutoService; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -13,9 +12,7 @@ import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import java.util.List; -@AutoService(AutoConfigurationCustomizerProvider.class) public class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider { - @Override public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { autoConfigurationCustomizer @@ -33,53 +30,39 @@ public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { private static void addSpanProcessor( SdkTracerProviderBuilder sdkTracerProviderBuilder, ConfigProperties config) { - if (spanKeys(config).isEmpty()) { + List keys = + config.getList("otel.java.experimental.span-attributes.copy-from-baggage.include"); + + if (keys.isEmpty()) { return; } - sdkTracerProviderBuilder.addSpanProcessor(createBaggageSpanProcessor(config)); - } - - static BaggageSpanProcessor createBaggageSpanProcessor(ConfigProperties config) { - return createBaggageSpanProcessor(spanKeys(config)); + sdkTracerProviderBuilder.addSpanProcessor(createBaggageSpanProcessor(keys)); } static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { - if (matchAll(keys)) { + if (keys.size() == 1 && keys.get(0).equals("*")) { return BaggageSpanProcessor.allowAllBaggageKeys(); } return new BaggageSpanProcessor(keys::contains); } - static List spanKeys(ConfigProperties config) { - return config.getList("otel.java.experimental.span-attributes.copy-from-baggage.include"); - } - private static void addLogRecordProcessor( SdkLoggerProviderBuilder sdkLoggerProviderBuilder, ConfigProperties config) { - if (logKeys(config).isEmpty()) { + List keys = + config.getList("otel.java.experimental.log-attributes.copy-from-baggage.include"); + + if (keys.isEmpty()) { return; } - sdkLoggerProviderBuilder.addLogRecordProcessor(createBaggageLogRecordProcessor(config)); - } - - static BaggageLogRecordProcessor createBaggageLogRecordProcessor(ConfigProperties config) { - return createBaggageLogRecordProcessor(logKeys(config)); + sdkLoggerProviderBuilder.addLogRecordProcessor(createBaggageLogRecordProcessor(keys)); } static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List keys) { - if (matchAll(keys)) { + if (keys.size() == 1 && keys.get(0).equals("*")) { return BaggageLogRecordProcessor.allowAllBaggageKeys(); } return new BaggageLogRecordProcessor(keys::contains); } - - static List logKeys(ConfigProperties config) { - return config.getList("otel.java.experimental.log-attributes.copy-from-baggage.include"); - } - - private static boolean matchAll(List keys) { - return keys.size() == 1 && keys.get(0).equals("*"); - } } diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java deleted file mode 100644 index 69227802f..000000000 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.baggage.processor; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; -import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; -import io.opentelemetry.sdk.trace.SpanProcessor; -import java.util.Collections; - -@SuppressWarnings("rawtypes") -@AutoService(ComponentProvider.class) -public class BaggageSpanComponentProvider implements ComponentProvider { - @Override - public String getName() { - return "baggage"; - } - - @Override - public SpanProcessor create(DeclarativeConfigProperties config) { - return BaggageProcessorCustomizer.createBaggageSpanProcessor( - ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap("otel.java.experimental.span-attributes.", ""))); - } - - @Override - public Class getType() { - return SpanProcessor.class; - } -} diff --git a/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider b/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider new file mode 100644 index 000000000..8eb4afb06 --- /dev/null +++ b/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider @@ -0,0 +1 @@ +io.opentelemetry.contrib.baggage.processor.BaggageProcessorCustomizer diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java index f30371ff5..bfa8835ae 100644 --- a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java @@ -103,9 +103,9 @@ private static OpenTelemetrySdk getOpenTelemetrySdk( // We set the export interval of the spans to 10 ms. The default value is 5 // seconds. "otel.bsp.schedule.delay", // span exporter - "100", + "10", "otel.blrp.schedule.delay", // log exporter - "100", + "10", "otel.traces.exporter", MEMORY_EXPORTER, "otel.metrics.exporter", From 4a119c9908a687833db308fd67bf066005d312a0 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 18 Jul 2025 17:06:44 +0200 Subject: [PATCH 28/44] use unified bridge --- .../autoconfigure/ConfigPropertiesUtil.java | 32 +++---- .../DeclarativeConfigPropertiesBridge.java | 62 +++++++++---- .../sdk/autoconfigure/PropertyTranslator.java | 37 ++++++++ .../PropertyTranslatorBuilder.java | 33 +++++++ ...DeclarativeConfigPropertiesBridgeTest.java | 88 +++++++++---------- .../src/test/resources/config.yaml | 27 ++++++ .../gcp/auth/GcpAuthCustomizerProvider.java | 8 +- .../auth/GcpAuthCustomizerProviderTest.java | 3 +- .../StackTraceComponentProvider.java | 5 +- 9 files changed, 204 insertions(+), 91 deletions(-) create mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslator.java create mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java create mode 100644 declarative-config-bridge/src/test/resources/config.yaml diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index 457e49b90..eaf18d584 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -10,13 +10,9 @@ import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; -import java.util.Collections; -import java.util.Map; import javax.annotation.Nullable; -public class ConfigPropertiesUtil { +public final class ConfigPropertiesUtil { private ConfigPropertiesUtil() {} /** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */ @@ -31,41 +27,35 @@ public static ConfigProperties resolveConfigProperties( AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); if (configProvider != null) { return resolveInstrumentationConfig( - configProvider.getInstrumentationConfig(), Collections.emptyMap()); + configProvider.getInstrumentationConfig(), propertyTranslatorBuilder()); } // Should never happen throw new IllegalStateException( "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); } - public static ConfigProperties resolveModel(OpenTelemetryConfigurationModel model) { - return resolveModel(model, Collections.emptyMap()); - } - - public static ConfigProperties resolveModel( - OpenTelemetryConfigurationModel model, Map translationMap) { - return resolveInstrumentationConfig( - SdkConfigProvider.create(model).getInstrumentationConfig(), translationMap); - } - public static ConfigProperties resolveInstrumentationConfig( @Nullable DeclarativeConfigProperties instrumentationConfig) { - return resolveInstrumentationConfig(instrumentationConfig, Collections.emptyMap()); + return resolveInstrumentationConfig(instrumentationConfig, propertyTranslatorBuilder()); } public static ConfigProperties resolveInstrumentationConfig( @Nullable DeclarativeConfigProperties instrumentationConfig, - Map translationMap) { + PropertyTranslatorBuilder builder) { return DeclarativeConfigPropertiesBridge.fromInstrumentationConfig( - instrumentationConfig, translationMap); + instrumentationConfig, builder.build()); } public static ConfigProperties resolveConfig( - @Nullable DeclarativeConfigProperties config, Map translationMap) { - return DeclarativeConfigPropertiesBridge.create(config, translationMap); + @Nullable DeclarativeConfigProperties config, PropertyTranslatorBuilder builder) { + return DeclarativeConfigPropertiesBridge.create(config, builder.build()); } public static String propertyYamlPath(String propertyName) { return DeclarativeConfigPropertiesBridge.yamlPath(propertyName); } + + public static PropertyTranslatorBuilder propertyTranslatorBuilder() { + return new PropertyTranslatorBuilder(); + } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 8acdc32a1..188c4e899 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -50,63 +50,86 @@ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; + private final PropertyTranslator translator; @Nullable private final DeclarativeConfigProperties baseNode; - private final Map translationMap; static DeclarativeConfigPropertiesBridge fromInstrumentationConfig( - @Nullable DeclarativeConfigProperties instrumentationConfig, - Map translationMap) { + @Nullable DeclarativeConfigProperties instrumentationConfig, PropertyTranslator translator) { if (instrumentationConfig == null) { instrumentationConfig = DeclarativeConfigProperties.empty(); } return new DeclarativeConfigPropertiesBridge( - instrumentationConfig.getStructured("java", empty()), translationMap); + instrumentationConfig.getStructured("java", empty()), translator); } static DeclarativeConfigPropertiesBridge create( - @Nullable DeclarativeConfigProperties node, Map translationMap) { - return new DeclarativeConfigPropertiesBridge(node, translationMap); + @Nullable DeclarativeConfigProperties node, PropertyTranslator translator) { + return new DeclarativeConfigPropertiesBridge(node, translator); } private DeclarativeConfigPropertiesBridge( - @Nullable DeclarativeConfigProperties baseNode, Map translationMap) { + @Nullable DeclarativeConfigProperties baseNode, PropertyTranslator translator) { this.baseNode = baseNode; - this.translationMap = translationMap; + this.translator = translator; } @Nullable @Override public String getString(String propertyName) { + Object value = translator.get(propertyName); + if (value != null) { + return value.toString(); + } return getPropertyValue(propertyName, DeclarativeConfigProperties::getString); } @Nullable @Override public Boolean getBoolean(String propertyName) { + Object value = translator.get(propertyName); + if (value != null) { + return (Boolean) value; + } return getPropertyValue(propertyName, DeclarativeConfigProperties::getBoolean); } @Nullable @Override public Integer getInt(String propertyName) { + Object value = translator.get(propertyName); + if (value != null) { + return (Integer) value; + } return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt); } @Nullable @Override public Long getLong(String propertyName) { + Object value = translator.get(propertyName); + if (value != null) { + return (Long) value; + } return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); } @Nullable @Override public Double getDouble(String propertyName) { + Object value = translator.get(propertyName); + if (value != null) { + return (Double) value; + } return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble); } @Nullable @Override public Duration getDuration(String propertyName) { + Object value = translator.get(propertyName); + if (value != null) { + return (Duration) value; + } Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); if (millis == null) { return null; @@ -114,8 +137,13 @@ public Duration getDuration(String propertyName) { return Duration.ofMillis(millis); } + @SuppressWarnings("unchecked") @Override public List getList(String propertyName) { + Object value = translator.get(propertyName); + if (value != null) { + return (List) value; + } List propertyValue = getPropertyValue( propertyName, @@ -123,8 +151,13 @@ public List getList(String propertyName) { return propertyValue == null ? Collections.emptyList() : propertyValue; } + @SuppressWarnings("unchecked") @Override public Map getMap(String propertyName) { + Object fixed = translator.get(propertyName); + if (fixed != null) { + return (Map) fixed; + } DeclarativeConfigProperties propertyValue = getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); if (propertyValue == null) { @@ -151,7 +184,7 @@ private T getPropertyValue( return null; } - String[] segments = getSegments(translate(property)); + String[] segments = getSegments(translator.translateProperty(property)); if (segments.length == 0) { return null; } @@ -168,21 +201,12 @@ private T getPropertyValue( return extractor.apply(target, lastPart); } - private String translate(String property) { - for (Map.Entry entry : translationMap.entrySet()) { - if (property.startsWith(entry.getKey())) { - return entry.getValue() + property.substring(entry.getKey().length()); - } - } - return property; - } - private static String[] getSegments(String property) { if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); } // Split the remainder of the property on "." - return property.split("\\."); + return property.replace('-', '_').split("\\."); } static String yamlPath(String property) { diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslator.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslator.java new file mode 100644 index 000000000..8edfd8673 --- /dev/null +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslator.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sdk.autoconfigure; + +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Nullable; + +@SuppressWarnings("NonApiType") +class PropertyTranslator { + // lookup order matters - we choose the first match + private final LinkedHashMap translationMap; + private final Map fixedValues; + + PropertyTranslator( + LinkedHashMap translationMap, Map fixedValues) { + this.translationMap = translationMap; + this.fixedValues = fixedValues; + } + + String translateProperty(String property) { + for (Map.Entry entry : translationMap.entrySet()) { + if (property.startsWith(entry.getKey())) { + return entry.getValue() + property.substring(entry.getKey().length()); + } + } + return property; + } + + @Nullable + public Object get(String propertyName) { + return fixedValues.get(propertyName); + } +} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java new file mode 100644 index 000000000..1b06c40a4 --- /dev/null +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sdk.autoconfigure; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import java.util.LinkedHashMap; +import java.util.Map; + +public class PropertyTranslatorBuilder { + private final LinkedHashMap translationMap = new LinkedHashMap<>(); + private final Map fixedValues = new LinkedHashMap<>(); + + PropertyTranslatorBuilder() {} + + @CanIgnoreReturnValue + public PropertyTranslatorBuilder addTranslation(String propertyName, String yamlPath) { + translationMap.put(propertyName, yamlPath); + return this; + } + + @CanIgnoreReturnValue + public PropertyTranslatorBuilder addFixedValue(String propertyName, Object value) { + fixedValues.put(propertyName, value); + return this; + } + + PropertyTranslator build() { + return new PropertyTranslator(translationMap, fixedValues); + } +} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index e02940d1c..c8b223423 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -3,10 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.contrib.sdk.autoconfigure; /* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ +package io.opentelemetry.contrib.sdk.autoconfigure; import static org.assertj.core.api.Assertions.assertThat; @@ -15,11 +12,8 @@ import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.InstrumentationModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -28,56 +22,31 @@ class DeclarativeConfigPropertiesBridgeTest { - private static final String YAML = - "file_format: 0.4\n" - + "instrumentation/development:\n" - + " java:\n" - + " common:\n" - + " default-enabled: true\n" - + " runtime-telemetry:\n" - + " enabled: false\n" - + " example-instrumentation:\n" - + " string_key: value\n" - + " bool_key: true\n" - + " int_key: 1\n" - + " double_key: 1.1\n" - + " list_key:\n" - + " - value1\n" - + " - value2\n" - + " - true\n" - + " map_key:\n" - + " string_key1: value1\n" - + " string_key2: value2\n" - + " bool_key: true\n" - + " acme:\n" - + " full_name:\n" - + " preserved: true"; - private ConfigProperties bridge; private ConfigProperties emptyBridge; @BeforeEach void setup() { - bridge = createBridge(Collections.emptyMap()); + bridge = create(ConfigPropertiesUtil.propertyTranslatorBuilder()); OpenTelemetryConfigurationModel emptyModel = new OpenTelemetryConfigurationModel() .withAdditionalProperty("instrumentation/development", new InstrumentationModel()); SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); emptyBridge = - DeclarativeConfigPropertiesBridge.fromInstrumentationConfig( - Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig()), - Collections.emptyMap()); + ConfigPropertiesUtil.resolveInstrumentationConfig( + Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); } - private static DeclarativeConfigPropertiesBridge createBridge( - Map translationMap) { + private static ConfigProperties create(PropertyTranslatorBuilder builder) { OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( - new ByteArrayInputStream(YAML.getBytes(StandardCharsets.UTF_8))); - return DeclarativeConfigPropertiesBridge.fromInstrumentationConfig( - Objects.requireNonNull(SdkConfigProvider.create(model).getInstrumentationConfig()), - translationMap); + DeclarativeConfigPropertiesBridgeTest.class + .getClassLoader() + .getResourceAsStream("config.yaml")); + SdkConfigProvider configProvider = SdkConfigProvider.create(model); + return ConfigPropertiesUtil.resolveInstrumentationConfig( + configProvider.getInstrumentationConfig(), builder); } @Test @@ -91,7 +60,6 @@ void getProperties() { .isTrue(); // common cases - assertThat(bridge.getBoolean("otel.instrumentation.common.default-enabled")).isTrue(); assertThat(bridge.getBoolean("otel.instrumentation.runtime-telemetry.enabled")).isFalse(); // check all the types @@ -154,9 +122,37 @@ void vendor() { } @Test - void translation() { - DeclarativeConfigPropertiesBridge propertiesBridge = - createBridge(Collections.singletonMap("acme", "acme.full_name")); + void vendorTranslation() { + ConfigProperties propertiesBridge = + create( + ConfigPropertiesUtil.propertyTranslatorBuilder() + .addTranslation("acme", "acme.full_name")); assertThat(propertiesBridge.getBoolean("acme.preserved")).isTrue(); } + + @Test + void agentCommonTranslation() { + assertThat( + create( + ConfigPropertiesUtil.propertyTranslatorBuilder() + .addTranslation( + "otel.instrumentation.common.default-enabled", + "common.default.enabled")) + .getBoolean("otel.instrumentation.common.default-enabled")) + .isFalse(); + } + + @Test + void agentTranslation() { + ConfigProperties bridge = + create( + ConfigPropertiesUtil.propertyTranslatorBuilder() + .addTranslation("otel.javaagent", "agent") + .addFixedValue("otel.javaagent.debug", true) + .addFixedValue("otel.javaagent.logging", "application")); + + assertThat(bridge.getBoolean("otel.javaagent.debug")).isTrue(); + assertThat(bridge.getBoolean("otel.javaagent.experimental.indy")).isTrue(); + assertThat(bridge.getString("otel.javaagent.logging")).isEqualTo("application"); + } } diff --git a/declarative-config-bridge/src/test/resources/config.yaml b/declarative-config-bridge/src/test/resources/config.yaml new file mode 100644 index 000000000..ef0ce9a8c --- /dev/null +++ b/declarative-config-bridge/src/test/resources/config.yaml @@ -0,0 +1,27 @@ +file_format: 0.4 +instrumentation/development: + java: + acme: + full_name: + preserved: true + agent: + experimental: + indy: true + common: + default: + enabled: false + runtime_telemetry: + enabled: false + example_instrumentation: + string_key: value + bool_key: true + int_key: 1 + double_key: 1.1 + list_key: + - value1 + - value2 + - true + map_key: + string_key1: value1 + string_key2: value2 + bool_key: true diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index 297a47596..42b0f68be 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -15,6 +15,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessorModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MeterProviderModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReaderModel; @@ -51,7 +52,7 @@ public void customize(DeclarativeConfigurationCustomizer customizer) { customize( model, GcpAuthAutoConfigurationCustomizerProvider.getCredentials(), - ConfigPropertiesUtil.resolveModel(model)); + getConfigProperties(model)); return model; }); @@ -68,6 +69,11 @@ static void customize( customizeTracer(model, headerMap, configProperties); } + static ConfigProperties getConfigProperties(OpenTelemetryConfigurationModel model) { + return ConfigPropertiesUtil.resolveInstrumentationConfig( + SdkConfigProvider.create(model).getInstrumentationConfig()); + } + private static void customizeMeter( OpenTelemetryConfigurationModel model, Map headerMap, diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java index fd469eae0..8252f50c6 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java @@ -11,7 +11,6 @@ import static org.mockito.Mockito.when; import com.google.auth.oauth2.GoogleCredentials; -import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; @@ -52,7 +51,7 @@ void declarativeConfig() throws IOException { OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); - ConfigProperties properties = ConfigPropertiesUtil.resolveModel(model); + ConfigProperties properties = GcpAuthCustomizerProvider.getConfigProperties(model); assertThat(GcpAuthAutoConfigurationCustomizerProvider.targetSignals(properties)) .containsExactly("metrics", "traces"); diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java index 5606a53a3..b6f07a4fe 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java @@ -10,7 +10,6 @@ import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.trace.SpanProcessor; -import java.util.Collections; @SuppressWarnings("rawtypes") @AutoService(ComponentProvider.class) @@ -24,7 +23,9 @@ public String getName() { public SpanProcessor create(DeclarativeConfigProperties config) { return StackTraceAutoConfig.create( ConfigPropertiesUtil.resolveConfig( - config, Collections.singletonMap(StackTraceAutoConfig.PREFIX, ""))); + config, + ConfigPropertiesUtil.propertyTranslatorBuilder() + .addTranslation(StackTraceAutoConfig.PREFIX, ""))); } @Override From 4f7014a9ca5ff4444960db1196cf1e71cf06362f Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 22 Jul 2025 18:36:13 +0200 Subject: [PATCH 29/44] add experimental- suffix, add test --- .../StackTraceComponentProvider.java | 2 +- .../StackTraceComponentProviderTest.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java index b6f07a4fe..5c37441f5 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java @@ -16,7 +16,7 @@ public class StackTraceComponentProvider implements ComponentProvider { @Override public String getName() { - return "stacktrace"; + return "experimental-stacktrace"; } @Override diff --git a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java new file mode 100644 index 000000000..edc2a8d8c --- /dev/null +++ b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java @@ -0,0 +1,27 @@ +package io.opentelemetry.contrib.stacktrace; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; + +class StackTraceComponentProviderTest { + @Test + void endToEnd() { + String yaml = + "file_format: 0.4\n" + + "tracer_provider:\n" + + " processors:\n" + + " - experimental-stacktrace:\n"; + + OpenTelemetrySdk openTelemetrySdk = + DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + + assertThat(openTelemetrySdk.getSdkTracerProvider().toString()) + .contains("StackTraceSpanProcessor"); + } +} From 6587b31158c15be12bc2903ac1cf884ecdc3860c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 22 Jul 2025 18:37:25 +0200 Subject: [PATCH 30/44] add experimental- suffix, add test --- .../StackTraceComponentProviderTest.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java index edc2a8d8c..a2b4c4212 100644 --- a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java +++ b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.contrib.stacktrace; import static org.assertj.core.api.Assertions.assertThat; @@ -10,18 +15,18 @@ class StackTraceComponentProviderTest { @Test - void endToEnd() { - String yaml = - "file_format: 0.4\n" - + "tracer_provider:\n" - + " processors:\n" - + " - experimental-stacktrace:\n"; + void endToEnd() { + String yaml = + "file_format: 0.4\n" + + "tracer_provider:\n" + + " processors:\n" + + " - experimental-stacktrace:\n"; - OpenTelemetrySdk openTelemetrySdk = - DeclarativeConfiguration.parseAndCreate( - new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + OpenTelemetrySdk openTelemetrySdk = + DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); assertThat(openTelemetrySdk.getSdkTracerProvider().toString()) .contains("StackTraceSpanProcessor"); - } + } } From d0718e654bcf5cb75adf13091e954b0e9ba32b2a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 24 Jul 2025 20:42:51 +0200 Subject: [PATCH 31/44] update bridge to match agent --- ...r.java => ConfigPropertiesTranslator.java} | 4 +- .../autoconfigure/ConfigPropertiesUtil.java | 51 +---------- .../DeclarativeConfigPropertiesBridge.java | 23 ++--- ...larativeConfigPropertiesBridgeBuilder.java | 76 ++++++++++++++++ .../PropertyTranslatorBuilder.java | 33 ------- .../ConfigPropertiesUtilTest.java | 75 ---------------- ...tiveConfigPropertiesBridgeBuilderTest.java | 89 +++++++++++++++++++ ...DeclarativeConfigPropertiesBridgeTest.java | 20 ++--- .../gcp/auth/GcpAuthCustomizerProvider.java | 5 +- .../StackTraceComponentProvider.java | 9 +- 10 files changed, 194 insertions(+), 191 deletions(-) rename declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/{PropertyTranslator.java => ConfigPropertiesTranslator.java} (93%) create mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java delete mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java create mode 100644 declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslator.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java similarity index 93% rename from declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslator.java rename to declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java index 8edfd8673..5c54b04c7 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslator.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java @@ -10,12 +10,12 @@ import javax.annotation.Nullable; @SuppressWarnings("NonApiType") -class PropertyTranslator { +class ConfigPropertiesTranslator { // lookup order matters - we choose the first match private final LinkedHashMap translationMap; private final Map fixedValues; - PropertyTranslator( + ConfigPropertiesTranslator( LinkedHashMap translationMap, Map fixedValues) { this.translationMap = translationMap; this.fixedValues = fixedValues; diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index eaf18d584..1deb62b30 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -5,57 +5,14 @@ package io.opentelemetry.contrib.sdk.autoconfigure; -import io.opentelemetry.api.incubator.config.ConfigProvider; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import javax.annotation.Nullable; - +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ public final class ConfigPropertiesUtil { private ConfigPropertiesUtil() {} - /** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */ - public static ConfigProperties resolveConfigProperties( - AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - ConfigProperties sdkConfigProperties = - AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); - if (sdkConfigProperties != null) { - return sdkConfigProperties; - } - ConfigProvider configProvider = - AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); - if (configProvider != null) { - return resolveInstrumentationConfig( - configProvider.getInstrumentationConfig(), propertyTranslatorBuilder()); - } - // Should never happen - throw new IllegalStateException( - "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); - } - - public static ConfigProperties resolveInstrumentationConfig( - @Nullable DeclarativeConfigProperties instrumentationConfig) { - return resolveInstrumentationConfig(instrumentationConfig, propertyTranslatorBuilder()); - } - - public static ConfigProperties resolveInstrumentationConfig( - @Nullable DeclarativeConfigProperties instrumentationConfig, - PropertyTranslatorBuilder builder) { - return DeclarativeConfigPropertiesBridge.fromInstrumentationConfig( - instrumentationConfig, builder.build()); - } - - public static ConfigProperties resolveConfig( - @Nullable DeclarativeConfigProperties config, PropertyTranslatorBuilder builder) { - return DeclarativeConfigPropertiesBridge.create(config, builder.build()); - } - public static String propertyYamlPath(String propertyName) { return DeclarativeConfigPropertiesBridge.yamlPath(propertyName); } - - public static PropertyTranslatorBuilder propertyTranslatorBuilder() { - return new PropertyTranslatorBuilder(); - } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 188c4e899..2b8983bd2 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -45,30 +45,19 @@ * common: * string_key: value * + * + *

    This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. */ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; - private final PropertyTranslator translator; + private final ConfigPropertiesTranslator translator; @Nullable private final DeclarativeConfigProperties baseNode; - static DeclarativeConfigPropertiesBridge fromInstrumentationConfig( - @Nullable DeclarativeConfigProperties instrumentationConfig, PropertyTranslator translator) { - if (instrumentationConfig == null) { - instrumentationConfig = DeclarativeConfigProperties.empty(); - } - return new DeclarativeConfigPropertiesBridge( - instrumentationConfig.getStructured("java", empty()), translator); - } - - static DeclarativeConfigPropertiesBridge create( - @Nullable DeclarativeConfigProperties node, PropertyTranslator translator) { - return new DeclarativeConfigPropertiesBridge(node, translator); - } - - private DeclarativeConfigPropertiesBridge( - @Nullable DeclarativeConfigProperties baseNode, PropertyTranslator translator) { + DeclarativeConfigPropertiesBridge( + @Nullable DeclarativeConfigProperties baseNode, ConfigPropertiesTranslator translator) { this.baseNode = baseNode; this.translator = translator; } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java new file mode 100644 index 000000000..12caeb143 --- /dev/null +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java @@ -0,0 +1,76 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sdk.autoconfigure; + +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.incubator.config.ConfigProvider; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * A builder for {@link DeclarativeConfigPropertiesBridge} that allows adding translations and fixed + * values for properties. + * + *

    This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class DeclarativeConfigPropertiesBridgeBuilder { + private final LinkedHashMap translationMap = new LinkedHashMap<>(); + private final Map fixedValues = new LinkedHashMap<>(); + + public DeclarativeConfigPropertiesBridgeBuilder() {} + + @CanIgnoreReturnValue + public DeclarativeConfigPropertiesBridgeBuilder addTranslation( + String propertyName, String yamlPath) { + translationMap.put(propertyName, yamlPath); + return this; + } + + @CanIgnoreReturnValue + public DeclarativeConfigPropertiesBridgeBuilder addFixedValue(String propertyName, Object value) { + fixedValues.put(propertyName, value); + return this; + } + + /** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */ + public ConfigProperties resolveConfigProperties( + AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { + ConfigProperties sdkConfigProperties = + AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); + if (sdkConfigProperties != null) { + return sdkConfigProperties; + } + ConfigProvider configProvider = + AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); + if (configProvider != null) { + return resolveInstrumentationConfig(configProvider.getInstrumentationConfig()); + } + // Should never happen + throw new IllegalStateException( + "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); + } + + public ConfigProperties resolveInstrumentationConfig( + @Nullable DeclarativeConfigProperties instrumentationConfig) { + if (instrumentationConfig == null) { + instrumentationConfig = DeclarativeConfigProperties.empty(); + } + return resolveConfig(instrumentationConfig.getStructured("java", empty())); + } + + public ConfigProperties resolveConfig(@Nullable DeclarativeConfigProperties config) { + return new DeclarativeConfigPropertiesBridge( + config, new ConfigPropertiesTranslator(translationMap, fixedValues)); + } +} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java deleted file mode 100644 index 1b06c40a4..000000000 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/PropertyTranslatorBuilder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -import com.google.errorprone.annotations.CanIgnoreReturnValue; -import java.util.LinkedHashMap; -import java.util.Map; - -public class PropertyTranslatorBuilder { - private final LinkedHashMap translationMap = new LinkedHashMap<>(); - private final Map fixedValues = new LinkedHashMap<>(); - - PropertyTranslatorBuilder() {} - - @CanIgnoreReturnValue - public PropertyTranslatorBuilder addTranslation(String propertyName, String yamlPath) { - translationMap.put(propertyName, yamlPath); - return this; - } - - @CanIgnoreReturnValue - public PropertyTranslatorBuilder addFixedValue(String propertyName, Object value) { - fixedValues.put(propertyName, value); - return this; - } - - PropertyTranslator build() { - return new PropertyTranslator(translationMap, fixedValues); - } -} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java index 9981ffdb2..f28f943d4 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java @@ -6,85 +6,10 @@ package io.opentelemetry.contrib.sdk.autoconfigure; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import io.opentelemetry.api.incubator.config.ConfigProvider; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -@SuppressWarnings("DoNotMockAutoValue") class ConfigPropertiesUtilTest { - @Test - void shouldUseConfigPropertiesForAutoConfiguration() { - ConfigProperties configPropertiesMock = mock(ConfigProperties.class); - AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); - try (MockedStatic autoConfigureUtilMock = - Mockito.mockStatic(AutoConfigureUtil.class)) { - autoConfigureUtilMock - .when(() -> AutoConfigureUtil.getConfig(sdkMock)) - .thenReturn(configPropertiesMock); - - ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock); - - assertThat(configProperties).isSameAs(configPropertiesMock); - } - } - - @Test - void shouldUseConfigProviderForDeclarativeConfiguration() { - String propertyName = "testProperty"; - String expectedValue = "the value"; - DeclarativeConfigProperties javaNodeMock = mock(DeclarativeConfigProperties.class); - when(javaNodeMock.getString(propertyName)).thenReturn(expectedValue); - - DeclarativeConfigProperties instrumentationConfigMock = mock(DeclarativeConfigProperties.class); - when(instrumentationConfigMock.getStructured(eq("java"), any())).thenReturn(javaNodeMock); - - ConfigProvider configProviderMock = mock(ConfigProvider.class); - when(configProviderMock.getInstrumentationConfig()).thenReturn(instrumentationConfigMock); - - AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); - - try (MockedStatic autoConfigureUtilMock = - Mockito.mockStatic(AutoConfigureUtil.class)) { - autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); - autoConfigureUtilMock - .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) - .thenReturn(configProviderMock); - - ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock); - - assertThat(configProperties.getString(propertyName)).isEqualTo(expectedValue); - } - } - - @Test - void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig() { - AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); - ConfigProvider configProviderMock = mock(ConfigProvider.class); - when(configProviderMock.getInstrumentationConfig()).thenReturn(null); - - try (MockedStatic autoConfigureUtilMock = - Mockito.mockStatic(AutoConfigureUtil.class)) { - autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); - autoConfigureUtilMock - .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) - .thenReturn(configProviderMock); - - ConfigProperties configProperties = ConfigPropertiesUtil.resolveConfigProperties(sdkMock); - - assertThat(configProperties.getString("testProperty")).isEqualTo(null); - } - } - @Test void propertyYamlPath() { assertThat(ConfigPropertiesUtil.propertyYamlPath("google.otel.auth.target.signals")) diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java new file mode 100644 index 000000000..504edb196 --- /dev/null +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java @@ -0,0 +1,89 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.sdk.autoconfigure; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import io.opentelemetry.api.incubator.config.ConfigProvider; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +class DeclarativeConfigPropertiesBridgeBuilderTest { + @Test + void shouldUseConfigPropertiesForAutoConfiguration() { + ConfigProperties configPropertiesMock = mock(ConfigProperties.class); + AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); + try (MockedStatic autoConfigureUtilMock = + Mockito.mockStatic(AutoConfigureUtil.class)) { + autoConfigureUtilMock + .when(() -> AutoConfigureUtil.getConfig(sdkMock)) + .thenReturn(configPropertiesMock); + + ConfigProperties configProperties = + new DeclarativeConfigPropertiesBridgeBuilder().resolveConfigProperties(sdkMock); + + assertThat(configProperties).isSameAs(configPropertiesMock); + } + } + + @Test + void shouldUseConfigProviderForDeclarativeConfiguration() { + String propertyName = "testProperty"; + String expectedValue = "the value"; + DeclarativeConfigProperties javaNodeMock = mock(DeclarativeConfigProperties.class); + when(javaNodeMock.getString(propertyName)).thenReturn(expectedValue); + + DeclarativeConfigProperties instrumentationConfigMock = mock(DeclarativeConfigProperties.class); + when(instrumentationConfigMock.getStructured(eq("java"), any())).thenReturn(javaNodeMock); + + ConfigProvider configProviderMock = mock(ConfigProvider.class); + when(configProviderMock.getInstrumentationConfig()).thenReturn(instrumentationConfigMock); + + AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); + + try (MockedStatic autoConfigureUtilMock = + Mockito.mockStatic(AutoConfigureUtil.class)) { + autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); + autoConfigureUtilMock + .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) + .thenReturn(configProviderMock); + + ConfigProperties configProperties = + new DeclarativeConfigPropertiesBridgeBuilder().resolveConfigProperties(sdkMock); + + assertThat(configProperties.getString(propertyName)).isEqualTo(expectedValue); + } + } + + @Test + void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig() { + AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); + ConfigProvider configProviderMock = mock(ConfigProvider.class); + when(configProviderMock.getInstrumentationConfig()).thenReturn(null); + + try (MockedStatic autoConfigureUtilMock = + Mockito.mockStatic(AutoConfigureUtil.class)) { + autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); + autoConfigureUtilMock + .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) + .thenReturn(configProviderMock); + + ConfigProperties configProperties = + new DeclarativeConfigPropertiesBridgeBuilder().resolveConfigProperties(sdkMock); + + assertThat(configProperties.getString("testProperty")).isEqualTo(null); + } + } +} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index c8b223423..746eed875 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -27,26 +27,26 @@ class DeclarativeConfigPropertiesBridgeTest { @BeforeEach void setup() { - bridge = create(ConfigPropertiesUtil.propertyTranslatorBuilder()); + bridge = create(new DeclarativeConfigPropertiesBridgeBuilder()); OpenTelemetryConfigurationModel emptyModel = new OpenTelemetryConfigurationModel() .withAdditionalProperty("instrumentation/development", new InstrumentationModel()); SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); emptyBridge = - ConfigPropertiesUtil.resolveInstrumentationConfig( - Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); + new DeclarativeConfigPropertiesBridgeBuilder() + .resolveInstrumentationConfig( + Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); } - private static ConfigProperties create(PropertyTranslatorBuilder builder) { + private static ConfigProperties create(DeclarativeConfigPropertiesBridgeBuilder builder) { OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( DeclarativeConfigPropertiesBridgeTest.class .getClassLoader() .getResourceAsStream("config.yaml")); - SdkConfigProvider configProvider = SdkConfigProvider.create(model); - return ConfigPropertiesUtil.resolveInstrumentationConfig( - configProvider.getInstrumentationConfig(), builder); + return builder.resolveInstrumentationConfig( + SdkConfigProvider.create(model).getInstrumentationConfig()); } @Test @@ -125,7 +125,7 @@ void vendor() { void vendorTranslation() { ConfigProperties propertiesBridge = create( - ConfigPropertiesUtil.propertyTranslatorBuilder() + new DeclarativeConfigPropertiesBridgeBuilder() .addTranslation("acme", "acme.full_name")); assertThat(propertiesBridge.getBoolean("acme.preserved")).isTrue(); } @@ -134,7 +134,7 @@ void vendorTranslation() { void agentCommonTranslation() { assertThat( create( - ConfigPropertiesUtil.propertyTranslatorBuilder() + new DeclarativeConfigPropertiesBridgeBuilder() .addTranslation( "otel.instrumentation.common.default-enabled", "common.default.enabled")) @@ -146,7 +146,7 @@ void agentCommonTranslation() { void agentTranslation() { ConfigProperties bridge = create( - ConfigPropertiesUtil.propertyTranslatorBuilder() + new DeclarativeConfigPropertiesBridgeBuilder() .addTranslation("otel.javaagent", "agent") .addFixedValue("otel.javaagent.debug", true) .addFixedValue("otel.javaagent.logging", "application")); diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index 42b0f68be..51385b534 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -12,6 +12,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.contrib.sdk.autoconfigure.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; @@ -70,8 +71,8 @@ static void customize( } static ConfigProperties getConfigProperties(OpenTelemetryConfigurationModel model) { - return ConfigPropertiesUtil.resolveInstrumentationConfig( - SdkConfigProvider.create(model).getInstrumentationConfig()); + return new DeclarativeConfigPropertiesBridgeBuilder() + .resolveInstrumentationConfig(SdkConfigProvider.create(model).getInstrumentationConfig()); } private static void customizeMeter( diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java index 5c37441f5..cfa36ae6d 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java @@ -7,7 +7,7 @@ import com.google.auto.service.AutoService; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; +import io.opentelemetry.contrib.sdk.autoconfigure.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.trace.SpanProcessor; @@ -22,10 +22,9 @@ public String getName() { @Override public SpanProcessor create(DeclarativeConfigProperties config) { return StackTraceAutoConfig.create( - ConfigPropertiesUtil.resolveConfig( - config, - ConfigPropertiesUtil.propertyTranslatorBuilder() - .addTranslation(StackTraceAutoConfig.PREFIX, ""))); + new DeclarativeConfigPropertiesBridgeBuilder() + .addTranslation(StackTraceAutoConfig.PREFIX, "") + .resolveConfig(config)); } @Override From e042b15f0bef19c323b2ba4091160141e1f3d6cf Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 24 Jul 2025 20:49:14 +0200 Subject: [PATCH 32/44] update bridge to match agent --- .../sdk/autoconfigure/ConfigPropertiesTranslator.java | 5 +++-- .../DeclarativeConfigPropertiesBridge.java | 10 ++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java index 5c54b04c7..9ce1ebf20 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java @@ -30,8 +30,9 @@ String translateProperty(String property) { return property; } + @SuppressWarnings("unchecked") @Nullable - public Object get(String propertyName) { - return fixedValues.get(propertyName); + public T get(String propertyName) { + return (T) fixedValues.get(propertyName); } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 2b8983bd2..f38411490 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -126,12 +126,11 @@ public Duration getDuration(String propertyName) { return Duration.ofMillis(millis); } - @SuppressWarnings("unchecked") @Override public List getList(String propertyName) { - Object value = translator.get(propertyName); + List value = translator.get(propertyName); if (value != null) { - return (List) value; + return value; } List propertyValue = getPropertyValue( @@ -140,12 +139,11 @@ public List getList(String propertyName) { return propertyValue == null ? Collections.emptyList() : propertyValue; } - @SuppressWarnings("unchecked") @Override public Map getMap(String propertyName) { - Object fixed = translator.get(propertyName); + Map fixed = translator.get(propertyName); if (fixed != null) { - return (Map) fixed; + return fixed; } DeclarativeConfigProperties propertyValue = getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); From 5bf5e78d1ac52e4372a6602b05b2562685750d98 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 24 Jul 2025 20:55:27 +0200 Subject: [PATCH 33/44] Revert "update bridge to match agent" This reverts commit 2e2bb79add74c6790e87d4fc0b24b80edff848e5. --- .../sdk/autoconfigure/ConfigPropertiesTranslator.java | 5 ++--- .../DeclarativeConfigPropertiesBridge.java | 10 ++++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java index 9ce1ebf20..5c54b04c7 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java @@ -30,9 +30,8 @@ String translateProperty(String property) { return property; } - @SuppressWarnings("unchecked") @Nullable - public T get(String propertyName) { - return (T) fixedValues.get(propertyName); + public Object get(String propertyName) { + return fixedValues.get(propertyName); } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index f38411490..2b8983bd2 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -126,11 +126,12 @@ public Duration getDuration(String propertyName) { return Duration.ofMillis(millis); } + @SuppressWarnings("unchecked") @Override public List getList(String propertyName) { - List value = translator.get(propertyName); + Object value = translator.get(propertyName); if (value != null) { - return value; + return (List) value; } List propertyValue = getPropertyValue( @@ -139,11 +140,12 @@ public List getList(String propertyName) { return propertyValue == null ? Collections.emptyList() : propertyValue; } + @SuppressWarnings("unchecked") @Override public Map getMap(String propertyName) { - Map fixed = translator.get(propertyName); + Object fixed = translator.get(propertyName); if (fixed != null) { - return fixed; + return (Map) fixed; } DeclarativeConfigProperties propertyValue = getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); From b3bfd037758dbd3f91c5ae30c5d66103170386e6 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 24 Jul 2025 21:21:56 +0200 Subject: [PATCH 34/44] update bridge to match agent --- .../DeclarativeConfigPropertiesBridgeBuilderTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java index 504edb196..1dc8ad9b3 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java @@ -20,6 +20,7 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; +@SuppressWarnings("DoNotMockAutoValue") class DeclarativeConfigPropertiesBridgeBuilderTest { @Test void shouldUseConfigPropertiesForAutoConfiguration() { From 712cf2735ba8a20cdcb5482eb1ace9cf28dbb4d2 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 4 Aug 2025 14:46:42 +0200 Subject: [PATCH 35/44] Update gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java Co-authored-by: Pranav Sharma --- .../gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index 8b241755f..148448afe 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -161,6 +161,7 @@ private static boolean isSignalTargeted(String checkSignal, ConfigProperties con targetedSignal.equals(checkSignal) || targetedSignal.equals(SIGNAL_TYPE_ALL)); } + @VisibleForTesting static List targetSignals(ConfigProperties configProperties) { return Objects.requireNonNull( ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValue( From d2e2ef42a13475e9252c4f6c1af1826561ec39f6 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 4 Aug 2025 14:46:56 +0200 Subject: [PATCH 36/44] Update gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java Co-authored-by: Pranav Sharma --- .../contrib/gcp/auth/GcpAuthCustomizerProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java index 51385b534..86518ae2d 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java @@ -59,6 +59,7 @@ public void customize(DeclarativeConfigurationCustomizer customizer) { }); } + @VisibleForTesting static void customize( OpenTelemetryConfigurationModel model, GoogleCredentials credentials, From 85fad27d65a539e59a8365acddc4dc7ccc72fef3 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 4 Aug 2025 14:48:29 +0200 Subject: [PATCH 37/44] pr review --- .../contrib/gcp/auth/ConfigurableOption.java | 8 +++----- ...cpAuthDeclarativeConfigurationCustomizerProvider.java} | 3 ++- ...thDeclarativeConfigurationCustomizerProviderTest.java} | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) rename gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/{GcpAuthCustomizerProvider.java => GcpAuthDeclarativeConfigurationCustomizerProvider.java} (98%) rename gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/{GcpAuthCustomizerProviderTest.java => GcpAuthDeclarativeConfigurationCustomizerProviderTest.java} (88%) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java index 54649c7a6..572baa8b8 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java @@ -92,8 +92,7 @@ String getUserReadableName() { } /** - * Retrieves the configured value for this option. This method checks the environment variable - * first and then the system property. + * Retrieves the configured value for this option. * * @return The configured value as a string, or throws an exception if not configured. * @throws ConfigurationException if neither the environment variable nor the system property is @@ -113,10 +112,9 @@ T getRequiredConfiguredValue( } /** - * Retrieves the configured value for this option. This method checks the environment variable - * first and then the system property. + * Retrieves the configured value for this option. * - * @return The configured value as a string, or throws an exception if not configured. + * @return The configured value as a string, or {@code null} if not configured. */ @Nullable T getConfiguredValue( diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java similarity index 98% rename from gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java rename to gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java index 86518ae2d..64ead75cd 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java @@ -11,6 +11,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; +import com.google.common.annotations.VisibleForTesting; import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; import io.opentelemetry.contrib.sdk.autoconfigure.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -37,7 +38,7 @@ import javax.annotation.Nullable; @AutoService(DeclarativeConfigurationCustomizerProvider.class) -public class GcpAuthCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { +public class GcpAuthDeclarativeConfigurationCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { static final String SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION = String.format( diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java similarity index 88% rename from gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java rename to gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java index 8252f50c6..f4b3a7f28 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.gcp.auth; -import static io.opentelemetry.contrib.gcp.auth.GcpAuthCustomizerProvider.SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthDeclarativeConfigurationCustomizerProvider.SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -20,7 +20,7 @@ import java.util.Collections; import org.junit.jupiter.api.Test; -class GcpAuthCustomizerProviderTest { +class GcpAuthDeclarativeConfigurationCustomizerProviderTest { @Test void declarativeConfig() throws IOException { @@ -51,7 +51,7 @@ void declarativeConfig() throws IOException { OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); - ConfigProperties properties = GcpAuthCustomizerProvider.getConfigProperties(model); + ConfigProperties properties = GcpAuthDeclarativeConfigurationCustomizerProvider.getConfigProperties(model); assertThat(GcpAuthAutoConfigurationCustomizerProvider.targetSignals(properties)) .containsExactly("metrics", "traces"); @@ -64,7 +64,7 @@ void declarativeConfig() throws IOException { .thenReturn( Collections.singletonMap("x-goog-user-project", Collections.singletonList("qp"))); - GcpAuthCustomizerProvider.customize(model, credentials, properties); + GcpAuthDeclarativeConfigurationCustomizerProvider.customize(model, credentials, properties); String header = "headers=\\[io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel@.*\\[name=x-goog-user-project,value=qp]"; From 65d2f8ee0d145057b2494093f7a6924b77fc68b8 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 4 Aug 2025 15:01:29 +0200 Subject: [PATCH 38/44] pr review --- ...uthAutoConfigurationCustomizerProvider.java | 18 +++++++++++++++--- ...arativeConfigurationCustomizerProvider.java | 6 +++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index 148448afe..5b3cc925d 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -7,6 +7,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; +import com.google.common.annotations.VisibleForTesting; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.contrib.gcp.auth.GoogleAuthException.Reason; @@ -124,7 +125,7 @@ public int order() { private static SpanExporter customizeSpanExporter( SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (shouldConfigureExporter( + if (shouldCustomizeExporter( SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); } @@ -133,14 +134,25 @@ private static SpanExporter customizeSpanExporter( private static MetricExporter customizeMetricExporter( MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (shouldConfigureExporter( + if (shouldCustomizeExporter( SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); } return exporter; } - static boolean shouldConfigureExporter( + /** + * Utility method to check whether OTLP exporters should be customized for the given target + * signal. + * + * @param signal The target signal to check against. Could be one of {@value SIGNAL_TYPE_TRACES}, + * {@value SIGNAL_TYPE_METRICS} or {@value SIGNAL_TYPE_ALL}. + * @param fixSuggestion A warning to alert the user that auth extension is not configured for the + * provided target signal. + * @param configProperties The {@link ConfigProperties} object used to configure the extension. + * @return A boolean indicating whether the OTLP exporters should be customized or not. + */ + static boolean shouldCustomizeExporter( String signal, String fixSuggestion, ConfigProperties configProperties) { if (isSignalTargeted(signal, configProperties)) { return true; diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java index 64ead75cd..c312f47fc 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java @@ -7,7 +7,7 @@ import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_METRICS; import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_TRACES; -import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.shouldConfigureExporter; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.shouldCustomizeExporter; import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; @@ -86,7 +86,7 @@ private static void customizeMeter( return; } - if (shouldConfigureExporter( + if (shouldCustomizeExporter( SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION, configProperties)) { for (MetricReaderModel reader : meterProvider.getReaders()) { if (reader.getPeriodic() != null) { @@ -122,7 +122,7 @@ private static void customizeTracer( return; } - if (shouldConfigureExporter( + if (shouldCustomizeExporter( SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION, configProperties)) { for (SpanProcessorModel processor : tracerProvider.getProcessors()) { BatchSpanProcessorModel batch = processor.getBatch(); From 91be48566e9f1065ccda808a3ab1e4175d3f9e76 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 4 Aug 2025 15:32:16 +0200 Subject: [PATCH 39/44] pr review --- .../GcpAuthDeclarativeConfigurationCustomizerProvider.java | 3 ++- .../GcpAuthDeclarativeConfigurationCustomizerProviderTest.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java index c312f47fc..1cefdc64c 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java @@ -38,7 +38,8 @@ import javax.annotation.Nullable; @AutoService(DeclarativeConfigurationCustomizerProvider.class) -public class GcpAuthDeclarativeConfigurationCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { +public class GcpAuthDeclarativeConfigurationCustomizerProvider + implements DeclarativeConfigurationCustomizerProvider { static final String SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION = String.format( diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java index f4b3a7f28..ca234a0e3 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java @@ -51,7 +51,8 @@ void declarativeConfig() throws IOException { OpenTelemetryConfigurationModel model = DeclarativeConfiguration.parse( new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); - ConfigProperties properties = GcpAuthDeclarativeConfigurationCustomizerProvider.getConfigProperties(model); + ConfigProperties properties = + GcpAuthDeclarativeConfigurationCustomizerProvider.getConfigProperties(model); assertThat(GcpAuthAutoConfigurationCustomizerProvider.targetSignals(properties)) .containsExactly("metrics", "traces"); From bfe1c5e5bee538ce06b00d035fef62cd9ea85887 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 15 Aug 2025 13:08:30 +0200 Subject: [PATCH 40/44] update config bridge from agent --- .../ConfigPropertiesTranslator.java | 37 -------- .../autoconfigure/ConfigPropertiesUtil.java | 15 ++- .../DeclarativeConfigPropertiesBridge.java | 95 ++++++++----------- ...larativeConfigPropertiesBridgeBuilder.java | 66 +++++++++---- ...tiveConfigPropertiesBridgeBuilderTest.java | 8 +- ...DeclarativeConfigPropertiesBridgeTest.java | 26 ++--- ...rativeConfigurationCustomizerProvider.java | 2 +- 7 files changed, 104 insertions(+), 145 deletions(-) delete mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java deleted file mode 100644 index 5c54b04c7..000000000 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesTranslator.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -import java.util.LinkedHashMap; -import java.util.Map; -import javax.annotation.Nullable; - -@SuppressWarnings("NonApiType") -class ConfigPropertiesTranslator { - // lookup order matters - we choose the first match - private final LinkedHashMap translationMap; - private final Map fixedValues; - - ConfigPropertiesTranslator( - LinkedHashMap translationMap, Map fixedValues) { - this.translationMap = translationMap; - this.fixedValues = fixedValues; - } - - String translateProperty(String property) { - for (Map.Entry entry : translationMap.entrySet()) { - if (property.startsWith(entry.getKey())) { - return entry.getValue() + property.substring(entry.getKey().length()); - } - } - return property; - } - - @Nullable - public Object get(String propertyName) { - return fixedValues.get(propertyName); - } -} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index 1deb62b30..eff0b7706 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -5,14 +5,19 @@ package io.opentelemetry.contrib.sdk.autoconfigure; -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ public final class ConfigPropertiesUtil { private ConfigPropertiesUtil() {} public static String propertyYamlPath(String propertyName) { - return DeclarativeConfigPropertiesBridge.yamlPath(propertyName); + return yamlPath(propertyName); } + + static String yamlPath(String property) { + String[] segments = DeclarativeConfigPropertiesBridge.getSegments(property); + if (segments.length == 0) { + throw new IllegalArgumentException("Invalid property: " + property); + } + + return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; + } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java index 2b8983bd2..bc7f4b117 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java @@ -14,6 +14,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.BiFunction; import javax.annotation.Nullable; @@ -45,81 +46,60 @@ * common: * string_key: value * - * - *

    This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. */ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; - private final ConfigPropertiesTranslator translator; - @Nullable private final DeclarativeConfigProperties baseNode; + private final DeclarativeConfigProperties baseNode; + + // lookup order matters - we choose the first match + private final Map mappings; + private final Map overrideValues; DeclarativeConfigPropertiesBridge( - @Nullable DeclarativeConfigProperties baseNode, ConfigPropertiesTranslator translator) { - this.baseNode = baseNode; - this.translator = translator; + DeclarativeConfigProperties baseNode, + Map mappings, + Map overrideValues) { + this.baseNode = Objects.requireNonNull(baseNode); + this.mappings = mappings; + this.overrideValues = overrideValues; } @Nullable @Override public String getString(String propertyName) { - Object value = translator.get(propertyName); - if (value != null) { - return value.toString(); - } - return getPropertyValue(propertyName, DeclarativeConfigProperties::getString); + return getPropertyValue(propertyName, String.class, DeclarativeConfigProperties::getString); } @Nullable @Override public Boolean getBoolean(String propertyName) { - Object value = translator.get(propertyName); - if (value != null) { - return (Boolean) value; - } - return getPropertyValue(propertyName, DeclarativeConfigProperties::getBoolean); + return getPropertyValue(propertyName, Boolean.class, DeclarativeConfigProperties::getBoolean); } @Nullable @Override public Integer getInt(String propertyName) { - Object value = translator.get(propertyName); - if (value != null) { - return (Integer) value; - } - return getPropertyValue(propertyName, DeclarativeConfigProperties::getInt); + return getPropertyValue(propertyName, Integer.class, DeclarativeConfigProperties::getInt); } @Nullable @Override public Long getLong(String propertyName) { - Object value = translator.get(propertyName); - if (value != null) { - return (Long) value; - } - return getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + return getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong); } @Nullable @Override public Double getDouble(String propertyName) { - Object value = translator.get(propertyName); - if (value != null) { - return (Double) value; - } - return getPropertyValue(propertyName, DeclarativeConfigProperties::getDouble); + return getPropertyValue(propertyName, Double.class, DeclarativeConfigProperties::getDouble); } @Nullable @Override public Duration getDuration(String propertyName) { - Object value = translator.get(propertyName); - if (value != null) { - return (Duration) value; - } - Long millis = getPropertyValue(propertyName, DeclarativeConfigProperties::getLong); + Long millis = getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong); if (millis == null) { return null; } @@ -129,13 +109,10 @@ public Duration getDuration(String propertyName) { @SuppressWarnings("unchecked") @Override public List getList(String propertyName) { - Object value = translator.get(propertyName); - if (value != null) { - return (List) value; - } List propertyValue = getPropertyValue( propertyName, + List.class, (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); return propertyValue == null ? Collections.emptyList() : propertyValue; } @@ -143,12 +120,11 @@ public List getList(String propertyName) { @SuppressWarnings("unchecked") @Override public Map getMap(String propertyName) { - Object fixed = translator.get(propertyName); - if (fixed != null) { - return (Map) fixed; - } DeclarativeConfigProperties propertyValue = - getPropertyValue(propertyName, DeclarativeConfigProperties::getStructured); + getPropertyValue( + propertyName, + DeclarativeConfigProperties.class, + DeclarativeConfigProperties::getStructured); if (propertyValue == null) { return Collections.emptyMap(); } @@ -168,12 +144,15 @@ public Map getMap(String propertyName) { @Nullable private T getPropertyValue( - String property, BiFunction extractor) { - if (baseNode == null) { - return null; + String property, + Class clazz, + BiFunction extractor) { + T override = clazz.cast(overrideValues.get(property)); + if (override != null) { + return override; } - String[] segments = getSegments(translator.translateProperty(property)); + String[] segments = getSegments(translateProperty(property)); if (segments.length == 0) { return null; } @@ -190,7 +169,7 @@ private T getPropertyValue( return extractor.apply(target, lastPart); } - private static String[] getSegments(String property) { + static String[] getSegments(String property) { if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); } @@ -198,12 +177,12 @@ private static String[] getSegments(String property) { return property.replace('-', '_').split("\\."); } - static String yamlPath(String property) { - String[] segments = getSegments(property); - if (segments.length == 0) { - throw new IllegalArgumentException("Invalid property: " + property); + private String translateProperty(String property) { + for (Map.Entry entry : mappings.entrySet()) { + if (property.startsWith(entry.getKey())) { + return entry.getValue() + property.substring(entry.getKey().length()); + } } - - return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; + return property; } } diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java index 12caeb143..7aafd4210 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java @@ -13,6 +13,7 @@ import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import javax.annotation.Nullable; @@ -20,32 +21,49 @@ /** * A builder for {@link DeclarativeConfigPropertiesBridge} that allows adding translations and fixed * values for properties. - * - *

    This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. */ public class DeclarativeConfigPropertiesBridgeBuilder { - private final LinkedHashMap translationMap = new LinkedHashMap<>(); - private final Map fixedValues = new LinkedHashMap<>(); + /** + * order is important here, so we use LinkedHashMap - see {@link #addMapping(String, String)} for + * more details + */ + private final Map mappings = new LinkedHashMap<>(); + + private final Map overrideValues = new HashMap<>(); public DeclarativeConfigPropertiesBridgeBuilder() {} + /** + * Adds a mapping from a property prefix to a YAML path. + * + *

    For example, if the property prefix is "otel.javaagent" and the YAML path is "agent", then + * any property starting with "otel.javaagent." will be resolved against the "agent" node in the + * instrumentation/java section of the YAML configuration. + * + * @param propertyPrefix the prefix of the property to translate + * @param yamlPath the YAML path to resolve the property against + */ @CanIgnoreReturnValue - public DeclarativeConfigPropertiesBridgeBuilder addTranslation( - String propertyName, String yamlPath) { - translationMap.put(propertyName, yamlPath); + public DeclarativeConfigPropertiesBridgeBuilder addMapping( + String propertyPrefix, String yamlPath) { + mappings.put(propertyPrefix, yamlPath); return this; } + /** + * Adds a fixed override value for a property. + * + * @param propertyName the name of the property to override + * @param value the value to return when the property is requested + */ @CanIgnoreReturnValue - public DeclarativeConfigPropertiesBridgeBuilder addFixedValue(String propertyName, Object value) { - fixedValues.put(propertyName, value); + public DeclarativeConfigPropertiesBridgeBuilder addOverride(String propertyName, Object value) { + overrideValues.put(propertyName, value); return this; } - /** Resolve {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */ - public ConfigProperties resolveConfigProperties( - AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { + /** Build {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */ + public ConfigProperties build(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { ConfigProperties sdkConfigProperties = AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); if (sdkConfigProperties != null) { @@ -54,23 +72,31 @@ public ConfigProperties resolveConfigProperties( ConfigProvider configProvider = AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); if (configProvider != null) { - return resolveInstrumentationConfig(configProvider.getInstrumentationConfig()); + return buildFromInstrumentationConfig(configProvider.getInstrumentationConfig()); } // Should never happen throw new IllegalStateException( "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); } - public ConfigProperties resolveInstrumentationConfig( + /** + * Build {@link ConfigProperties} from the {@link DeclarativeConfigProperties} provided by the + * instrumentation configuration. + * + *

    If the provided {@code instrumentationConfig} is null, an empty {@link + * DeclarativeConfigProperties} will be used. + * + * @param instrumentationConfig the instrumentation configuration to build from + * @return a new instance of {@link ConfigProperties} + */ + public ConfigProperties buildFromInstrumentationConfig( @Nullable DeclarativeConfigProperties instrumentationConfig) { + // leave the name "build" for a future method that builds from a DeclarativeConfigProperties + // instance that doesn't come from the top-level instrumentation config if (instrumentationConfig == null) { instrumentationConfig = DeclarativeConfigProperties.empty(); } - return resolveConfig(instrumentationConfig.getStructured("java", empty())); - } - - public ConfigProperties resolveConfig(@Nullable DeclarativeConfigProperties config) { return new DeclarativeConfigPropertiesBridge( - config, new ConfigPropertiesTranslator(translationMap, fixedValues)); + instrumentationConfig.getStructured("java", empty()), mappings, overrideValues); } } diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java index 1dc8ad9b3..e07a7fbf7 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java @@ -33,7 +33,7 @@ void shouldUseConfigPropertiesForAutoConfiguration() { .thenReturn(configPropertiesMock); ConfigProperties configProperties = - new DeclarativeConfigPropertiesBridgeBuilder().resolveConfigProperties(sdkMock); + new DeclarativeConfigPropertiesBridgeBuilder().build(sdkMock); assertThat(configProperties).isSameAs(configPropertiesMock); } @@ -62,7 +62,7 @@ void shouldUseConfigProviderForDeclarativeConfiguration() { .thenReturn(configProviderMock); ConfigProperties configProperties = - new DeclarativeConfigPropertiesBridgeBuilder().resolveConfigProperties(sdkMock); + new DeclarativeConfigPropertiesBridgeBuilder().build(sdkMock); assertThat(configProperties.getString(propertyName)).isEqualTo(expectedValue); } @@ -82,9 +82,9 @@ void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig( .thenReturn(configProviderMock); ConfigProperties configProperties = - new DeclarativeConfigPropertiesBridgeBuilder().resolveConfigProperties(sdkMock); + new DeclarativeConfigPropertiesBridgeBuilder().build(sdkMock); - assertThat(configProperties.getString("testProperty")).isEqualTo(null); + assertThat(configProperties.getString("testProperty")).isNull(); } } } diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java index 746eed875..405cecc1c 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java @@ -35,7 +35,7 @@ void setup() { SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); emptyBridge = new DeclarativeConfigPropertiesBridgeBuilder() - .resolveInstrumentationConfig( + .buildFromInstrumentationConfig( Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); } @@ -45,7 +45,7 @@ private static ConfigProperties create(DeclarativeConfigPropertiesBridgeBuilder DeclarativeConfigPropertiesBridgeTest.class .getClassLoader() .getResourceAsStream("config.yaml")); - return builder.resolveInstrumentationConfig( + return builder.buildFromInstrumentationConfig( SdkConfigProvider.create(model).getInstrumentationConfig()); } @@ -124,32 +124,18 @@ void vendor() { @Test void vendorTranslation() { ConfigProperties propertiesBridge = - create( - new DeclarativeConfigPropertiesBridgeBuilder() - .addTranslation("acme", "acme.full_name")); + create(new DeclarativeConfigPropertiesBridgeBuilder().addMapping("acme", "acme.full_name")); assertThat(propertiesBridge.getBoolean("acme.preserved")).isTrue(); } - @Test - void agentCommonTranslation() { - assertThat( - create( - new DeclarativeConfigPropertiesBridgeBuilder() - .addTranslation( - "otel.instrumentation.common.default-enabled", - "common.default.enabled")) - .getBoolean("otel.instrumentation.common.default-enabled")) - .isFalse(); - } - @Test void agentTranslation() { ConfigProperties bridge = create( new DeclarativeConfigPropertiesBridgeBuilder() - .addTranslation("otel.javaagent", "agent") - .addFixedValue("otel.javaagent.debug", true) - .addFixedValue("otel.javaagent.logging", "application")); + .addMapping("otel.javaagent", "agent") + .addOverride("otel.javaagent.debug", true) + .addOverride("otel.javaagent.logging", "application")); assertThat(bridge.getBoolean("otel.javaagent.debug")).isTrue(); assertThat(bridge.getBoolean("otel.javaagent.experimental.indy")).isTrue(); diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java index 1cefdc64c..0883750d6 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java @@ -75,7 +75,7 @@ static void customize( static ConfigProperties getConfigProperties(OpenTelemetryConfigurationModel model) { return new DeclarativeConfigPropertiesBridgeBuilder() - .resolveInstrumentationConfig(SdkConfigProvider.create(model).getInstrumentationConfig()); + .buildFromInstrumentationConfig(SdkConfigProvider.create(model).getInstrumentationConfig()); } private static void customizeMeter( From 454fe0d2351024bf61f855868aa5e03cd013acf0 Mon Sep 17 00:00:00 2001 From: otelbot <197425009+otelbot@users.noreply.github.com> Date: Fri, 15 Aug 2025 11:10:03 +0000 Subject: [PATCH 41/44] ./gradlew spotlessApply --- .../sdk/autoconfigure/ConfigPropertiesUtil.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java index eff0b7706..cef09e2c0 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java @@ -13,11 +13,11 @@ public static String propertyYamlPath(String propertyName) { } static String yamlPath(String property) { - String[] segments = DeclarativeConfigPropertiesBridge.getSegments(property); - if (segments.length == 0) { - throw new IllegalArgumentException("Invalid property: " + property); - } + String[] segments = DeclarativeConfigPropertiesBridge.getSegments(property); + if (segments.length == 0) { + throw new IllegalArgumentException("Invalid property: " + property); + } - return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; - } + return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; + } } From 4b10dda018c84265f9ca51243c4df8053980baf0 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 22 Aug 2025 10:30:24 +0200 Subject: [PATCH 42/44] move bridge to agent --- declarative-config-bridge/build.gradle.kts | 18 -- .../autoconfigure/ConfigPropertiesUtil.java | 23 --- .../DeclarativeConfigPropertiesBridge.java | 188 ------------------ ...larativeConfigPropertiesBridgeBuilder.java | 102 ---------- .../ConfigPropertiesUtilTest.java | 19 -- ...tiveConfigPropertiesBridgeBuilderTest.java | 90 --------- ...DeclarativeConfigPropertiesBridgeTest.java | 144 -------------- .../src/test/resources/config.yaml | 27 --- gcp-auth-extension/build.gradle.kts | 12 +- ...rativeConfigurationCustomizerProvider.java | 4 +- settings.gradle.kts | 1 - span-stacktrace/build.gradle.kts | 13 +- .../StackTraceComponentProvider.java | 6 +- 13 files changed, 26 insertions(+), 621 deletions(-) delete mode 100644 declarative-config-bridge/build.gradle.kts delete mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java delete mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java delete mode 100644 declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java delete mode 100644 declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java delete mode 100644 declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java delete mode 100644 declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java delete mode 100644 declarative-config-bridge/src/test/resources/config.yaml diff --git a/declarative-config-bridge/build.gradle.kts b/declarative-config-bridge/build.gradle.kts deleted file mode 100644 index 1da7432d0..000000000 --- a/declarative-config-bridge/build.gradle.kts +++ /dev/null @@ -1,18 +0,0 @@ -plugins { - id("otel.java-conventions") - id("otel.publish-conventions") -} - -description = "OpenTelemetry extension that provides a bridge for declarative configuration." -otelJava.moduleName.set("io.opentelemetry.contrib.sdk.declarative.config.bridge") - -dependencies { - // We use `compileOnly` dependency because during runtime all necessary classes are provided by - // javaagent itself. - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") - - testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") - testImplementation("org.mockito:mockito-inline") -} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java deleted file mode 100644 index cef09e2c0..000000000 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtil.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -public final class ConfigPropertiesUtil { - private ConfigPropertiesUtil() {} - - public static String propertyYamlPath(String propertyName) { - return yamlPath(propertyName); - } - - static String yamlPath(String property) { - String[] segments = DeclarativeConfigPropertiesBridge.getSegments(property); - if (segments.length == 0) { - throw new IllegalArgumentException("Invalid property: " + property); - } - - return "'instrumentation/development' / 'java' / '" + String.join("' / '", segments) + "'"; - } -} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java deleted file mode 100644 index bc7f4b117..000000000 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridge.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; - -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import java.time.Duration; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.BiFunction; -import javax.annotation.Nullable; - -/** - * A {@link ConfigProperties} which resolves properties based on {@link - * DeclarativeConfigProperties}. - * - *

    Only properties starting with "otel.instrumentation." are resolved. Others return null (or - * default value if provided). - * - *

    To resolve: - * - *

      - *
    • "otel.instrumentation" refers to the ".instrumentation.java" node - *
    • The portion of the property after "otel.instrumentation." is split into segments based on - * ".". - *
    • For each N-1 segment, we walk down the tree to find the relevant leaf {@link - * DeclarativeConfigProperties}. - *
    • We extract the property from the resolved {@link DeclarativeConfigProperties} using the - * last segment as the property key. - *
    - * - *

    For example, given the following YAML, asking for {@code - * ConfigProperties#getString("otel.instrumentation.common.string_key")} yields "value": - * - *

    - *   instrumentation:
    - *     java:
    - *       common:
    - *         string_key: value
    - * 
    - */ -final class DeclarativeConfigPropertiesBridge implements ConfigProperties { - - private static final String OTEL_INSTRUMENTATION_PREFIX = "otel.instrumentation."; - - private final DeclarativeConfigProperties baseNode; - - // lookup order matters - we choose the first match - private final Map mappings; - private final Map overrideValues; - - DeclarativeConfigPropertiesBridge( - DeclarativeConfigProperties baseNode, - Map mappings, - Map overrideValues) { - this.baseNode = Objects.requireNonNull(baseNode); - this.mappings = mappings; - this.overrideValues = overrideValues; - } - - @Nullable - @Override - public String getString(String propertyName) { - return getPropertyValue(propertyName, String.class, DeclarativeConfigProperties::getString); - } - - @Nullable - @Override - public Boolean getBoolean(String propertyName) { - return getPropertyValue(propertyName, Boolean.class, DeclarativeConfigProperties::getBoolean); - } - - @Nullable - @Override - public Integer getInt(String propertyName) { - return getPropertyValue(propertyName, Integer.class, DeclarativeConfigProperties::getInt); - } - - @Nullable - @Override - public Long getLong(String propertyName) { - return getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong); - } - - @Nullable - @Override - public Double getDouble(String propertyName) { - return getPropertyValue(propertyName, Double.class, DeclarativeConfigProperties::getDouble); - } - - @Nullable - @Override - public Duration getDuration(String propertyName) { - Long millis = getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong); - if (millis == null) { - return null; - } - return Duration.ofMillis(millis); - } - - @SuppressWarnings("unchecked") - @Override - public List getList(String propertyName) { - List propertyValue = - getPropertyValue( - propertyName, - List.class, - (properties, lastPart) -> properties.getScalarList(lastPart, String.class)); - return propertyValue == null ? Collections.emptyList() : propertyValue; - } - - @SuppressWarnings("unchecked") - @Override - public Map getMap(String propertyName) { - DeclarativeConfigProperties propertyValue = - getPropertyValue( - propertyName, - DeclarativeConfigProperties.class, - DeclarativeConfigProperties::getStructured); - if (propertyValue == null) { - return Collections.emptyMap(); - } - Map result = new HashMap<>(); - propertyValue - .getPropertyKeys() - .forEach( - key -> { - String value = propertyValue.getString(key); - if (value == null) { - return; - } - result.put(key, value); - }); - return Collections.unmodifiableMap(result); - } - - @Nullable - private T getPropertyValue( - String property, - Class clazz, - BiFunction extractor) { - T override = clazz.cast(overrideValues.get(property)); - if (override != null) { - return override; - } - - String[] segments = getSegments(translateProperty(property)); - if (segments.length == 0) { - return null; - } - - // Extract the value by walking to the N-1 entry - DeclarativeConfigProperties target = baseNode; - if (segments.length > 1) { - for (int i = 0; i < segments.length - 1; i++) { - target = target.getStructured(segments[i], empty()); - } - } - String lastPart = segments[segments.length - 1]; - - return extractor.apply(target, lastPart); - } - - static String[] getSegments(String property) { - if (property.startsWith(OTEL_INSTRUMENTATION_PREFIX)) { - property = property.substring(OTEL_INSTRUMENTATION_PREFIX.length()); - } - // Split the remainder of the property on "." - return property.replace('-', '_').split("\\."); - } - - private String translateProperty(String property) { - for (Map.Entry entry : mappings.entrySet()) { - if (property.startsWith(entry.getKey())) { - return entry.getValue() + property.substring(entry.getKey().length()); - } - } - return property; - } -} diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java b/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java deleted file mode 100644 index 7aafd4210..000000000 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilder.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; - -import com.google.errorprone.annotations.CanIgnoreReturnValue; -import io.opentelemetry.api.incubator.config.ConfigProvider; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import javax.annotation.Nullable; - -/** - * A builder for {@link DeclarativeConfigPropertiesBridge} that allows adding translations and fixed - * values for properties. - */ -public class DeclarativeConfigPropertiesBridgeBuilder { - /** - * order is important here, so we use LinkedHashMap - see {@link #addMapping(String, String)} for - * more details - */ - private final Map mappings = new LinkedHashMap<>(); - - private final Map overrideValues = new HashMap<>(); - - public DeclarativeConfigPropertiesBridgeBuilder() {} - - /** - * Adds a mapping from a property prefix to a YAML path. - * - *

    For example, if the property prefix is "otel.javaagent" and the YAML path is "agent", then - * any property starting with "otel.javaagent." will be resolved against the "agent" node in the - * instrumentation/java section of the YAML configuration. - * - * @param propertyPrefix the prefix of the property to translate - * @param yamlPath the YAML path to resolve the property against - */ - @CanIgnoreReturnValue - public DeclarativeConfigPropertiesBridgeBuilder addMapping( - String propertyPrefix, String yamlPath) { - mappings.put(propertyPrefix, yamlPath); - return this; - } - - /** - * Adds a fixed override value for a property. - * - * @param propertyName the name of the property to override - * @param value the value to return when the property is requested - */ - @CanIgnoreReturnValue - public DeclarativeConfigPropertiesBridgeBuilder addOverride(String propertyName, Object value) { - overrideValues.put(propertyName, value); - return this; - } - - /** Build {@link ConfigProperties} from the {@code autoConfiguredOpenTelemetrySdk}. */ - public ConfigProperties build(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - ConfigProperties sdkConfigProperties = - AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); - if (sdkConfigProperties != null) { - return sdkConfigProperties; - } - ConfigProvider configProvider = - AutoConfigureUtil.getConfigProvider(autoConfiguredOpenTelemetrySdk); - if (configProvider != null) { - return buildFromInstrumentationConfig(configProvider.getInstrumentationConfig()); - } - // Should never happen - throw new IllegalStateException( - "AutoConfiguredOpenTelemetrySdk does not have ConfigProperties or DeclarativeConfigProperties. This is likely a programming error in opentelemetry-java"); - } - - /** - * Build {@link ConfigProperties} from the {@link DeclarativeConfigProperties} provided by the - * instrumentation configuration. - * - *

    If the provided {@code instrumentationConfig} is null, an empty {@link - * DeclarativeConfigProperties} will be used. - * - * @param instrumentationConfig the instrumentation configuration to build from - * @return a new instance of {@link ConfigProperties} - */ - public ConfigProperties buildFromInstrumentationConfig( - @Nullable DeclarativeConfigProperties instrumentationConfig) { - // leave the name "build" for a future method that builds from a DeclarativeConfigProperties - // instance that doesn't come from the top-level instrumentation config - if (instrumentationConfig == null) { - instrumentationConfig = DeclarativeConfigProperties.empty(); - } - return new DeclarativeConfigPropertiesBridge( - instrumentationConfig.getStructured("java", empty()), mappings, overrideValues); - } -} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java deleted file mode 100644 index f28f943d4..000000000 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/ConfigPropertiesUtilTest.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -class ConfigPropertiesUtilTest { - @Test - void propertyYamlPath() { - assertThat(ConfigPropertiesUtil.propertyYamlPath("google.otel.auth.target.signals")) - .isEqualTo( - "'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / 'signals'"); - } -} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java deleted file mode 100644 index e07a7fbf7..000000000 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeBuilderTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import io.opentelemetry.api.incubator.config.ConfigProvider; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -@SuppressWarnings("DoNotMockAutoValue") -class DeclarativeConfigPropertiesBridgeBuilderTest { - @Test - void shouldUseConfigPropertiesForAutoConfiguration() { - ConfigProperties configPropertiesMock = mock(ConfigProperties.class); - AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); - try (MockedStatic autoConfigureUtilMock = - Mockito.mockStatic(AutoConfigureUtil.class)) { - autoConfigureUtilMock - .when(() -> AutoConfigureUtil.getConfig(sdkMock)) - .thenReturn(configPropertiesMock); - - ConfigProperties configProperties = - new DeclarativeConfigPropertiesBridgeBuilder().build(sdkMock); - - assertThat(configProperties).isSameAs(configPropertiesMock); - } - } - - @Test - void shouldUseConfigProviderForDeclarativeConfiguration() { - String propertyName = "testProperty"; - String expectedValue = "the value"; - DeclarativeConfigProperties javaNodeMock = mock(DeclarativeConfigProperties.class); - when(javaNodeMock.getString(propertyName)).thenReturn(expectedValue); - - DeclarativeConfigProperties instrumentationConfigMock = mock(DeclarativeConfigProperties.class); - when(instrumentationConfigMock.getStructured(eq("java"), any())).thenReturn(javaNodeMock); - - ConfigProvider configProviderMock = mock(ConfigProvider.class); - when(configProviderMock.getInstrumentationConfig()).thenReturn(instrumentationConfigMock); - - AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); - - try (MockedStatic autoConfigureUtilMock = - Mockito.mockStatic(AutoConfigureUtil.class)) { - autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); - autoConfigureUtilMock - .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) - .thenReturn(configProviderMock); - - ConfigProperties configProperties = - new DeclarativeConfigPropertiesBridgeBuilder().build(sdkMock); - - assertThat(configProperties.getString(propertyName)).isEqualTo(expectedValue); - } - } - - @Test - void shouldUseConfigProviderForDeclarativeConfiguration_noInstrumentationConfig() { - AutoConfiguredOpenTelemetrySdk sdkMock = mock(AutoConfiguredOpenTelemetrySdk.class); - ConfigProvider configProviderMock = mock(ConfigProvider.class); - when(configProviderMock.getInstrumentationConfig()).thenReturn(null); - - try (MockedStatic autoConfigureUtilMock = - Mockito.mockStatic(AutoConfigureUtil.class)) { - autoConfigureUtilMock.when(() -> AutoConfigureUtil.getConfig(sdkMock)).thenReturn(null); - autoConfigureUtilMock - .when(() -> AutoConfigureUtil.getConfigProvider(sdkMock)) - .thenReturn(configProviderMock); - - ConfigProperties configProperties = - new DeclarativeConfigPropertiesBridgeBuilder().build(sdkMock); - - assertThat(configProperties.getString("testProperty")).isNull(); - } - } -} diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java deleted file mode 100644 index 405cecc1c..000000000 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/contrib/sdk/autoconfigure/DeclarativeConfigPropertiesBridgeTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.sdk.autoconfigure; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; -import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.InstrumentationModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; -import java.time.Duration; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class DeclarativeConfigPropertiesBridgeTest { - - private ConfigProperties bridge; - private ConfigProperties emptyBridge; - - @BeforeEach - void setup() { - bridge = create(new DeclarativeConfigPropertiesBridgeBuilder()); - - OpenTelemetryConfigurationModel emptyModel = - new OpenTelemetryConfigurationModel() - .withAdditionalProperty("instrumentation/development", new InstrumentationModel()); - SdkConfigProvider emptyConfigProvider = SdkConfigProvider.create(emptyModel); - emptyBridge = - new DeclarativeConfigPropertiesBridgeBuilder() - .buildFromInstrumentationConfig( - Objects.requireNonNull(emptyConfigProvider.getInstrumentationConfig())); - } - - private static ConfigProperties create(DeclarativeConfigPropertiesBridgeBuilder builder) { - OpenTelemetryConfigurationModel model = - DeclarativeConfiguration.parse( - DeclarativeConfigPropertiesBridgeTest.class - .getClassLoader() - .getResourceAsStream("config.yaml")); - return builder.buildFromInstrumentationConfig( - SdkConfigProvider.create(model).getInstrumentationConfig()); - } - - @Test - void getProperties() { - // only properties starting with "otel.instrumentation." are resolved - // asking for properties which don't exist or inaccessible shouldn't result in an error - assertThat(bridge.getString("file_format")).isNull(); - assertThat(bridge.getString("file_format", "foo")).isEqualTo("foo"); - assertThat(emptyBridge.getBoolean("otel.instrumentation.common.default-enabled")).isNull(); - assertThat(emptyBridge.getBoolean("otel.instrumentation.common.default-enabled", true)) - .isTrue(); - - // common cases - assertThat(bridge.getBoolean("otel.instrumentation.runtime-telemetry.enabled")).isFalse(); - - // check all the types - Map expectedMap = new HashMap<>(); - expectedMap.put("string_key1", "value1"); - expectedMap.put("string_key2", "value2"); - assertThat(bridge.getString("otel.instrumentation.example-instrumentation.string_key")) - .isEqualTo("value"); - assertThat(bridge.getBoolean("otel.instrumentation.example-instrumentation.bool_key")).isTrue(); - assertThat(bridge.getInt("otel.instrumentation.example-instrumentation.int_key")).isEqualTo(1); - assertThat(bridge.getLong("otel.instrumentation.example-instrumentation.int_key")) - .isEqualTo(1L); - assertThat(bridge.getDuration("otel.instrumentation.example-instrumentation.int_key")) - .isEqualTo(Duration.ofMillis(1)); - assertThat(bridge.getDouble("otel.instrumentation.example-instrumentation.double_key")) - .isEqualTo(1.1); - assertThat(bridge.getList("otel.instrumentation.example-instrumentation.list_key")) - .isEqualTo(Arrays.asList("value1", "value2")); - assertThat(bridge.getMap("otel.instrumentation.example-instrumentation.map_key")) - .isEqualTo(expectedMap); - - // asking for properties with the wrong type returns null - assertThat(bridge.getBoolean("otel.instrumentation.example-instrumentation.string_key")) - .isNull(); - assertThat(bridge.getString("otel.instrumentation.example-instrumentation.bool_key")).isNull(); - assertThat(bridge.getString("otel.instrumentation.example-instrumentation.int_key")).isNull(); - assertThat(bridge.getString("otel.instrumentation.example-instrumentation.double_key")) - .isNull(); - assertThat(bridge.getString("otel.instrumentation.example-instrumentation.list_key")).isNull(); - assertThat(bridge.getString("otel.instrumentation.example-instrumentation.map_key")).isNull(); - - // check all the types - assertThat(bridge.getString("otel.instrumentation.other-instrumentation.string_key", "value")) - .isEqualTo("value"); - assertThat(bridge.getBoolean("otel.instrumentation.other-instrumentation.bool_key", true)) - .isTrue(); - assertThat(bridge.getInt("otel.instrumentation.other-instrumentation.int_key", 1)).isEqualTo(1); - assertThat(bridge.getLong("otel.instrumentation.other-instrumentation.int_key", 1L)) - .isEqualTo(1L); - assertThat( - bridge.getDuration( - "otel.instrumentation.other-instrumentation.int_key", Duration.ofMillis(1))) - .isEqualTo(Duration.ofMillis(1)); - assertThat(bridge.getDouble("otel.instrumentation.other-instrumentation.double_key", 1.1)) - .isEqualTo(1.1); - assertThat( - bridge.getList( - "otel.instrumentation.other-instrumentation.list_key", - Arrays.asList("value1", "value2"))) - .isEqualTo(Arrays.asList("value1", "value2")); - assertThat(bridge.getMap("otel.instrumentation.other-instrumentation.map_key", expectedMap)) - .isEqualTo(expectedMap); - } - - @Test - void vendor() { - // verify vendor specific property names are preserved in unchanged form (prefix is not stripped - // as for otel.instrumentation.*) - assertThat(bridge.getBoolean("acme.full_name.preserved")).isTrue(); - } - - @Test - void vendorTranslation() { - ConfigProperties propertiesBridge = - create(new DeclarativeConfigPropertiesBridgeBuilder().addMapping("acme", "acme.full_name")); - assertThat(propertiesBridge.getBoolean("acme.preserved")).isTrue(); - } - - @Test - void agentTranslation() { - ConfigProperties bridge = - create( - new DeclarativeConfigPropertiesBridgeBuilder() - .addMapping("otel.javaagent", "agent") - .addOverride("otel.javaagent.debug", true) - .addOverride("otel.javaagent.logging", "application")); - - assertThat(bridge.getBoolean("otel.javaagent.debug")).isTrue(); - assertThat(bridge.getBoolean("otel.javaagent.experimental.indy")).isTrue(); - assertThat(bridge.getString("otel.javaagent.logging")).isEqualTo("application"); - } -} diff --git a/declarative-config-bridge/src/test/resources/config.yaml b/declarative-config-bridge/src/test/resources/config.yaml deleted file mode 100644 index ef0ce9a8c..000000000 --- a/declarative-config-bridge/src/test/resources/config.yaml +++ /dev/null @@ -1,27 +0,0 @@ -file_format: 0.4 -instrumentation/development: - java: - acme: - full_name: - preserved: true - agent: - experimental: - indy: true - common: - default: - enabled: false - runtime_telemetry: - enabled: false - example_instrumentation: - string_key: value - bool_key: true - int_key: 1 - double_key: 1.1 - list_key: - - value1 - - value2 - - true - map_key: - string_key1: value1 - string_key2: value2 - bool_key: true diff --git a/gcp-auth-extension/build.gradle.kts b/gcp-auth-extension/build.gradle.kts index 093864c61..21b816f0c 100644 --- a/gcp-auth-extension/build.gradle.kts +++ b/gcp-auth-extension/build.gradle.kts @@ -15,8 +15,6 @@ val agent: Configuration by configurations.creating { dependencies { implementation(platform("org.springframework.boot:spring-boot-dependencies:2.7.18")) - implementation(project(":declarative-config-bridge")) - annotationProcessor("com.google.auto.service:auto-service") // We use `compileOnly` dependency because during runtime all necessary classes are provided by // javaagent itself. @@ -24,6 +22,7 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-api") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + compileOnly("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") compileOnly("io.opentelemetry:opentelemetry-exporter-otlp") // Only dependencies added to `implementation` configuration will be picked up by Shadow plugin @@ -41,6 +40,7 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations") + testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") testImplementation("org.awaitility:awaitility") testImplementation("org.mockito:mockito-inline") @@ -134,3 +134,11 @@ tasks.register("IntegrationTestUserCreds") { "-Dmockserver.logLevel=trace" ) } + +// todo remove when https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/14497 is merged +configurations.all { + resolutionStrategy { + force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.20.0-alpha-SNAPSHOT") + force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.19.0") + } +} diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java index 0883750d6..8ac60431f 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java @@ -12,8 +12,8 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; import com.google.common.annotations.VisibleForTesting; -import io.opentelemetry.contrib.sdk.autoconfigure.ConfigPropertiesUtil; -import io.opentelemetry.contrib.sdk.autoconfigure.DeclarativeConfigPropertiesBridgeBuilder; +import io.opentelemetry.instrumentation.api.incubator.config.bridge.ConfigPropertiesUtil; +import io.opentelemetry.instrumentation.api.incubator.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; diff --git a/settings.gradle.kts b/settings.gradle.kts index b4ff820a4..5502252e7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -43,7 +43,6 @@ include(":baggage-processor") include(":compressors:compressor-zstd") include(":cloudfoundry-resources") include(":consistent-sampling") -include(":declarative-config-bridge") include(":dependencyManagement") include(":disk-buffering") include(":example") diff --git a/span-stacktrace/build.gradle.kts b/span-stacktrace/build.gradle.kts index a9fa79e77..2a32b8b50 100644 --- a/span-stacktrace/build.gradle.kts +++ b/span-stacktrace/build.gradle.kts @@ -7,8 +7,6 @@ description = "OpenTelemetry Java span stacktrace capture module" otelJava.moduleName.set("io.opentelemetry.contrib.stacktrace") dependencies { - implementation(project(":declarative-config-bridge")) - annotationProcessor("com.google.auto.service:auto-service") compileOnly("com.google.auto.service:auto-service-annotations") @@ -17,10 +15,13 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + compileOnly("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") + testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") compileOnly("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("io.opentelemetry.semconv:opentelemetry-semconv") @@ -30,3 +31,11 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-exporter-logging") } + +// todo remove when https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/14497 is merged +configurations.all { + resolutionStrategy { + force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.20.0-alpha-SNAPSHOT") + force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.19.0") + } +} diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java index cfa36ae6d..a71275ead 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java @@ -7,7 +7,7 @@ import com.google.auto.service.AutoService; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.contrib.sdk.autoconfigure.DeclarativeConfigPropertiesBridgeBuilder; +import io.opentelemetry.instrumentation.api.incubator.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.trace.SpanProcessor; @@ -23,8 +23,8 @@ public String getName() { public SpanProcessor create(DeclarativeConfigProperties config) { return StackTraceAutoConfig.create( new DeclarativeConfigPropertiesBridgeBuilder() - .addTranslation(StackTraceAutoConfig.PREFIX, "") - .resolveConfig(config)); + .addMapping(StackTraceAutoConfig.PREFIX, "") + .build(config)); } @Override From ce46af5341b144afeea8e31c52a4092acbea9b7b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 15 Sep 2025 11:11:13 +0200 Subject: [PATCH 43/44] Merge remote-tracking branch 'origin/main' into span-stacktrace --- .github/config/lychee.toml | 14 ++ .github/copilot-instructions.md | 66 +++++++ .github/renovate.json5 | 34 +++- .github/scripts/dependencies.Dockerfile | 3 - .github/scripts/draft-change-log-entries.sh | 2 + .github/scripts/link-check.sh | 62 ------- .github/scripts/lychee-config.toml | 16 -- .github/scripts/package-lock.json | 27 +++ .github/scripts/package.json | 9 + .github/workflows/assign-issue-owners.yml | 10 +- .github/workflows/assign-reviewers.yml | 3 +- .github/workflows/auto-spotless-apply.yml | 2 +- .github/workflows/auto-spotless-check.yml | 4 +- .github/workflows/backport.yml | 13 +- .github/workflows/build-common.yml | 83 ++++++--- .github/workflows/build.yml | 6 +- .github/workflows/codeql.yml | 16 +- .github/workflows/copilot-setup-steps.yml | 34 ++++ .../workflows/gradle-wrapper-validation.yml | 2 +- .../issue-management-stale-action.yml | 2 +- .github/workflows/ossf-scorecard.yml | 4 +- .../owasp-dependency-check-daily.yml | 4 +- .github/workflows/prepare-patch-release.yml | 2 +- .github/workflows/prepare-release-branch.yml | 4 +- .github/workflows/release.yml | 140 +++++++-------- .github/workflows/reusable-link-check.yml | 26 ++- .gitignore | 3 + CHANGELOG.md | 29 ++- CONTRIBUTING.md | 89 ++++------ README.md | 26 +-- all/README.md | 4 - all/build.gradle.kts | 64 ------- .../aws/resource/BeanstalkResource.java | 6 +- .../contrib/aws/resource/DockerHelper.java | 7 +- .../contrib/aws/resource/Ec2Resource.java | 4 +- .../contrib/aws/resource/EcsResource.java | 17 +- .../contrib/aws/resource/EksResource.java | 9 +- .../aws/resource/SimpleHttpClient.java | 14 +- .../contrib/aws/resource/EksResourceTest.java | 2 +- .../propagator/AwsXrayLambdaPropagator.java | 5 +- .../awsxray/propagator/AwsXrayPropagator.java | 4 +- .../AwsXrayCompositePropagatorTest.java | 2 +- .../internal/AwsComponentProviderTest.java | 2 +- .../contrib/awsxray/AwsAttributeKeys.java | 25 ++- .../awsxray/AwsMetricAttributeGenerator.java | 47 +++-- .../awsxray/AwsSpanMetricsProcessor.java | 5 +- .../contrib/awsxray/AwsXrayRemoteSampler.java | 36 ++-- .../awsxray/AwsXrayRemoteSamplerBuilder.java | 6 +- .../contrib/awsxray/SamplingRuleApplier.java | 27 ++- .../contrib/awsxray/XrayRulesSampler.java | 9 +- .../contrib/awsxray/XraySamplerClient.java | 7 +- ...AttributePropagatingSpanProcessorTest.java | 10 +- .../AwsMetricAttributeGeneratorTest.java | 32 ++-- .../AwsMetricAttributesSpanExporterTest.java | 16 +- .../awsxray/AwsSpanMetricsProcessorTest.java | 18 +- .../contrib/awsxray/ResourceHolderTest.java | 4 +- azure-resources/build.gradle.kts | 4 +- .../resource/AzureAksResourceProvider.java | 2 +- .../AzureAppServiceResourceProvider.java | 6 +- .../AzureContainersResourceProvider.java | 2 +- .../AzureFunctionsResourceProvider.java | 2 +- .../azure/resource/AzureMetadataService.java | 17 +- .../azure/resource/AzureResourceDetector.java | 2 +- .../resource/AzureVmResourceProvider.java | 30 ++-- .../AzureAppServiceResourceProviderTest.java | 4 +- .../AzureContainersResourceProviderTest.java | 4 +- .../AzureFunctionsResourceProviderTest.java | 5 +- .../MetadataBasedResourceProviderTest.java | 16 +- baggage-processor/README.md | 30 ++++ baggage-processor/build.gradle.kts | 8 + .../BaggageLogRecordComponentProvider.java | 34 ++++ .../processor/BaggageLogRecordProcessor.java | 18 +- .../processor/BaggageProcessorCustomizer.java | 10 +- .../BaggageSpanComponentProvider.java | 34 ++++ .../processor/BaggageSpanProcessor.java | 2 +- ...re.spi.AutoConfigurationCustomizerProvider | 1 - ...BaggageLogRecordComponentProviderTest.java | 34 ++++ .../BaggageProcessorCustomizerTest.java | 18 +- .../BaggageSpanComponentProviderTest.java | 34 ++++ .../processor/BaggageSpanProcessorTest.java | 8 +- buildSrc/build.gradle.kts | 4 +- .../otel.japicmp-conventions.gradle.kts | 158 +++++++++++++++++ .../kotlin/otel.java-conventions.gradle.kts | 8 +- .../otel.spotless-conventions.gradle.kts | 11 +- .../resources/CloudFoundryResource.java | 22 +-- .../CloudFoundryResourceDetector.java | 2 +- .../CloudFoundryResourceProvider.java | 2 +- .../resources/CloudFoundryResourceTest.java | 10 +- consistent-sampling/build.gradle.kts | 4 +- ...ConsistentProbabilityBasedSamplerTest.java | 9 +- ...entReservoirSamplingSpanProcessorTest.java | 5 +- .../consistent/ConsistentSamplerTest.java | 65 +++---- .../consistent/OtelTraceStateTest.java | 103 ++++++----- .../consistent/RandomGeneratorTest.java | 2 +- .../ConsistentAlwaysOffSamplerTest.java | 2 +- .../ConsistentAlwaysOnSamplerTest.java | 2 +- .../ConsistentFixedThresholdSamplerTest.java | 6 +- .../ConsistentSamplingUtilTest.java | 2 +- .../consistent56/OtelTraceStateTest.java | 104 ++++++----- .../RandomValueGeneratorsTest.java | 2 +- dependencyManagement/build.gradle.kts | 10 +- disk-buffering/build.gradle.kts | 4 +- .../buffering/LogRecordFromDiskExporter.java | 2 +- .../buffering/LogRecordToDiskExporter.java | 3 +- .../buffering/MetricFromDiskExporter.java | 2 +- .../disk/buffering/MetricToDiskExporter.java | 2 +- .../disk/buffering/SpanFromDiskExporter.java | 2 +- .../disk/buffering/SpanToDiskExporter.java | 2 +- .../config/StorageConfiguration.java | 10 +- .../exporters/SignalStorageExporter.java | 5 +- .../exporters/SpanToDiskExporter.java | 13 +- .../internal/exporter/ToDiskExporter.java | 8 +- .../LogRecordDataDeserializer.java | 2 +- .../deserializers/MetricDataDeserializer.java | 2 +- .../deserializers/SpanDataDeserializer.java | 2 +- .../internal/storage/StorageBuilder.java | 5 +- .../buffering/internal/utils/DebugLogger.java | 4 +- .../disk/buffering/IntegrationTest.java | 16 +- .../LogRecordDataDeserializerTest.java | 61 +++++++ .../MetricDataDeserializerTest.java | 39 ++++ .../SpanDataDeserializerTest.java | 66 +++++++ .../mapping/common/AttributesMapperTest.java | 6 +- .../mapping/common/ResourceMapperTest.java | 5 +- .../mapping/logs/LogRecordDataMapperTest.java | 7 +- .../mapping/logs/ProtoLogsDataMapperTest.java | 39 ++-- .../mapping/metrics/MetricDataMapperTest.java | 8 +- .../metrics/ProtoMetricsDataMapperTest.java | 31 ++-- .../spans/ProtoSpansDataMapperTest.java | 31 ++-- .../mapping/spans/SpanDataMapperTest.java | 19 +- .../internal/storage/FolderManagerTest.java | 76 ++++---- .../internal/storage/StorageTest.java | 21 ++- .../storage/files/ReadableFileTest.java | 60 +++---- .../storage/files/WritableFileTest.java | 36 ++-- .../storage/files/utils/FileStreamTest.java | 2 +- .../disk/buffering/testutils/TestData.java | 19 ++ .../opentelemetry-aws-xray.txt | 2 + docs/style-guide.md | 166 ++++++++++++++++++ example/README.md | 3 - example/build.gradle.kts | 13 -- .../contrib/example/Library.java | 18 -- .../contrib/example/LibraryTest.java | 19 -- gcp-auth-extension/build.gradle.kts | 7 +- .../contrib/gcp/auth/ConfigurableOption.java | 6 +- ...thAutoConfigurationCustomizerProvider.java | 13 +- ...toConfigurationCustomizerProviderTest.java | 58 +++--- .../auth/GcpAuthExtensionEndToEndTest.java | 29 ++- gcp-resources/README.md | 2 +- .../gcp/resource/GCPResourceProvider.java | 1 + .../gcp/resource/IncubatingAttributes.java | 7 +- .../gcp/resource/GCPResourceProviderTest.java | 24 +-- gradle.properties | 2 + ibm-mq-metrics/build.gradle.kts | 14 +- .../io/opentelemetry/ibm/mq/WmqContext.java | 2 +- .../io/opentelemetry/ibm/mq/WmqMonitor.java | 2 +- .../ibm/mq/config/ExcludeFilters.java | 2 +- .../ibm/mq/config/QueueManager.java | 2 +- .../ibm/mq/config/ResourceFilters.java | 2 +- .../ibm/mq/metricscollector/MessageBuddy.java | 2 +- .../io/opentelemetry/ibm/mq/util/WmqUtil.java | 2 +- .../InquireChannelCmdCollectorTest.java | 2 +- .../ListenerMetricsCollectorTest.java | 2 +- .../ibm/mq/metricscollector/MetricAssert.java | 7 +- .../QueueCollectionBuddyTest.java | 2 +- .../QueueManagerMetricsCollectorTest.java | 2 +- .../TopicMetricsCollectorTest.java | 2 +- .../contrib/inferredspans/InferredSpans.java | 51 ++++++ .../InferredSpansAutoConfig.java | 5 +- .../inferredspans/InferredSpansProcessor.java | 15 +- .../InferredSpansProcessorBuilder.java | 14 +- .../inferredspans/WildcardMatcher.java | 5 +- .../internal/InferredSpansConfiguration.java | 6 +- .../internal/SamplingProfiler.java | 18 +- .../InferredSpansAutoConfigTest.java | 6 +- .../inferredspans/InferredSpansTest.java | 88 ++++++++++ .../internal/SamplingProfilerQueueTest.java | 2 +- ...corderDiagnosticCommandConnectionTest.java | 36 ++-- .../jfr/connection/OpenDataUtilsTest.java | 4 +- .../RecordingConfigurationTest.java | 23 +-- .../jfr/connection/RecordingOptionsTest.java | 55 +++--- .../contrib/jfr/connection/RecordingTest.java | 40 ++--- .../jfrevent/JfrSpanProcessorTest.java | 6 +- jmx-metrics/build.gradle.kts | 2 +- jmx-metrics/docs/target-systems/jetty.md | 2 +- .../target_systems/KafkaIntegrationTest.java | 6 +- jmx-scraper/README.md | 11 +- jmx-scraper/build.gradle.kts | 2 +- .../contrib/jmxscraper/JmxConnectionTest.java | 2 +- .../ActiveMqIntegrationTest.java | 2 +- .../CassandraIntegrationTest.java | 2 +- .../target_systems/CustomIntegrationTest.java | 2 +- .../target_systems/HBaseIntegrationTest.java | 2 +- .../target_systems/HadoopIntegrationTest.java | 2 +- .../target_systems/JettyIntegrationTest.java | 2 +- .../target_systems/JvmIntegrationTest.java | 2 +- .../target_systems/SolrIntegrationTest.java | 2 +- .../target_systems/TomcatIntegrationTest.java | 2 +- .../WildflyIntegrationTest.java | 2 +- .../kafka/KafkaConsumerIntegrationTest.java | 2 +- .../kafka/KafkaContainerFactory.java | 2 +- .../kafka/KafkaIntegrationTest.java | 2 +- .../kafka/KafkaProducerIntegrationTest.java | 2 +- .../jmxscraper/InvalidArgumentException.java | 2 +- .../jmxscraper/JmxConnectorBuilder.java | 7 +- .../contrib/jmxscraper/JmxScraper.java | 36 ++-- .../jmxscraper/config/JmxScraperConfig.java | 20 ++- .../config/PropertiesCustomizer.java | 2 +- .../jmxscraper/config/PropertiesSupplier.java | 2 +- .../contrib/jmxscraper/JmxScraperTest.java | 12 +- kafka-exporter/build.gradle.kts | 2 +- .../contrib/kafka/KafkaSpanExporter.java | 38 ++-- .../kafka/KafkaSpanExporterBuilder.java | 2 +- .../contrib/kafka/SpanDataDeserializer.java | 2 +- .../contrib/kafka/SpanDataSerializer.java | 2 +- .../kafka/KafkaSpanExporterBuilderTest.java | 133 +++++++------- .../KafkaSpanExporterIntegrationTest.java | 27 ++- .../kafka/SpanDataDeserializerTest.java | 10 +- .../contrib/kafka/SpanDataSerializerTest.java | 19 +- maven-extension/README.md | 8 +- .../maven/OpenTelemetrySdkServiceTest.java | 12 +- .../opentelemetry/maven/SpanRegistryTest.java | 4 +- ...GoalExecutionHandlerConfigurationTest.java | 5 +- .../handler/MojoGoalExecutionHandlerTest.java | 16 +- micrometer-meter-provider/build.gradle.kts | 4 +- .../micrometer/PrometheusIntegrationTest.java | 2 +- .../metrics/micrometer/MicrometerMeter.java | 11 +- .../micrometer/MicrometerMeterProvider.java | 9 +- .../MicrometerMeterProviderBuilder.java | 2 +- .../ScheduledCallbackRegistrar.java | 5 +- .../ScheduledCallbackRegistrarBuilder.java | 7 +- .../MicrometerMeterProviderTest.java | 2 +- .../micrometer/MicrometerMeterTest.java | 2 +- .../MicrometerDoubleCounterTest.java | 2 +- .../MicrometerDoubleGaugeTest.java | 2 +- .../MicrometerDoubleHistogramTest.java | 2 +- .../MicrometerDoubleUpDownCounterTest.java | 2 +- .../MicrometerLongCounterTest.java | 2 +- .../instruments/MicrometerLongGaugeTest.java | 2 +- .../MicrometerLongHistogramTest.java | 2 +- .../MicrometerLongUpDownCounterTest.java | 2 +- mise.toml | 12 ++ .../noopapi/NoopContextStorageProvider.java | 2 +- .../contrib/noopapi/NoopOpenTelemetry.java | 2 +- opamp-client/build.gradle.kts | 42 ++--- .../client/{internal => }/OpampClient.java | 2 +- .../{internal => }/OpampClientBuilder.java | 11 +- .../websocket/OkHttpWebSocket.java | 5 +- .../client/internal/impl/OpampClientImpl.java | 4 +- .../request/service/HttpRequestService.java | 1 + .../service/WebSocketRequestService.java | 1 + .../client/internal/response/MessageData.java | 2 +- .../client/internal/state/InMemoryState.java | 5 +- .../request/service/RequestService.java | 6 +- .../internal/impl/OpampClientImplTest.java | 4 +- .../service/HttpRequestServiceTest.java | 3 +- .../service/WebSocketRequestServiceTest.java | 3 +- .../filter/FilteringLogRecordProcessor.java | 6 +- ...ventToSpanBridgeComponentProviderTest.java | 2 +- .../FilteringLogRecordProcessorTest.java | 12 +- .../InterceptableLogRecordExporterTest.java | 20 +-- .../InterceptableMetricExporterTest.java | 7 +- .../InterceptableSpanExporterTest.java | 18 +- .../clientbridge/MetricAdapter.java | 13 +- .../clientbridge/PrometheusCollector.java | 5 +- .../prometheus/clientbridge/Serializer.java | 5 +- .../AppServerResourceDetector.java | 2 +- .../JettyServiceNameDetectorTest.java | 23 ++- .../attach/AbstractAttachmentTest.java | 2 +- ...gentDisabledByEnvironmentVariableTest.java | 2 +- .../AgentDisabledBySystemPropertyTest.java | 2 +- .../attach/RunTimeAttachBasicTest.java | 2 +- samplers/README.md | 2 +- .../LinksParentAlwaysOnSamplerProvider.java | 2 +- ...edRoutingSamplerComponentProviderTest.java | 2 +- .../sampler/RuleBasedRoutingSamplerTest.java | 14 +- settings.gradle.kts | 10 +- .../stacktrace/StackTraceAutoConfig.java | 7 +- .../stacktrace/StackTraceAutoConfigTest.java | 2 +- version.gradle.kts | 4 +- 278 files changed, 2536 insertions(+), 1581 deletions(-) create mode 100644 .github/config/lychee.toml create mode 100644 .github/copilot-instructions.md delete mode 100644 .github/scripts/dependencies.Dockerfile delete mode 100755 .github/scripts/link-check.sh delete mode 100644 .github/scripts/lychee-config.toml create mode 100644 .github/scripts/package-lock.json create mode 100644 .github/scripts/package.json create mode 100644 .github/workflows/copilot-setup-steps.yml delete mode 100644 all/README.md delete mode 100644 all/build.gradle.kts create mode 100644 baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java create mode 100644 baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java delete mode 100644 baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider create mode 100644 baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProviderTest.java create mode 100644 baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProviderTest.java create mode 100644 buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts create mode 100644 disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializerTest.java create mode 100644 disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializerTest.java create mode 100644 disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializerTest.java create mode 100644 docs/apidiffs/current_vs_latest/opentelemetry-aws-xray.txt create mode 100644 docs/style-guide.md delete mode 100644 example/README.md delete mode 100644 example/build.gradle.kts delete mode 100644 example/src/main/java/io/opentelemetry/contrib/example/Library.java delete mode 100644 example/src/test/java/io/opentelemetry/contrib/example/LibraryTest.java create mode 100644 inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpans.java create mode 100644 inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansTest.java create mode 100644 mise.toml rename opamp-client/src/main/java/io/opentelemetry/opamp/client/{internal => }/OpampClient.java (98%) rename opamp-client/src/main/java/io/opentelemetry/opamp/client/{internal => }/OpampClientBuilder.java (98%) rename opamp-client/src/main/java/io/opentelemetry/opamp/client/{internal => }/request/service/RequestService.java (91%) diff --git a/.github/config/lychee.toml b/.github/config/lychee.toml new file mode 100644 index 000000000..bde272fc9 --- /dev/null +++ b/.github/config/lychee.toml @@ -0,0 +1,14 @@ +timeout = 30 +retry_wait_time = 5 +max_retries = 6 +max_concurrency = 4 + +# Check link anchors +include_fragments = true + +exclude = [ + # until https://github.com/open-telemetry/opentelemetry-java-contrib/issues/2221 is resolved + "^https?://www.ibm.com", + # excluding links to pull requests and issues is done for performance + "^https://github.com/open-telemetry/opentelemetry-java-contrib/(issues|pull)/\\d+$", +] diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..d7f693363 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,66 @@ +# Copilot Instructions for OpenTelemetry Java Contrib + +This repository provides observability instrumentation for Java applications. + +## Code Review Priorities + +### Style Guide Compliance + +**PRIORITY**: Verify that all code changes follow the [Style Guide](../docs/style-guide.md). Check: + +- Code formatting (auto-formatting, static imports, class organization) +- Java language conventions (`final` usage, `@Nullable` annotations, `Optional` usage) +- Performance constraints (hot path allocations) +- Implementation patterns (SPI registration, configuration conventions) +- Gradle conventions (Kotlin DSL, plugin usage, module naming) +- Documentation standards (README files, deprecation processes) + +### Critical Areas + +- **Public APIs**: Changes affect downstream users and require careful review +- **Performance**: Instrumentation must have minimal overhead +- **Thread Safety**: Ensure safe concurrent access patterns +- **Memory Management**: Prevent leaks and excessive allocations + +### Quality Standards + +- Proper error handling with appropriate logging levels +- OpenTelemetry specification and semantic convention compliance +- Resource cleanup and lifecycle management +- Comprehensive unit tests for new functionality + +### Test suites + +This project uses gradle 9 which requires specifying test classes and paths explicitly. + +For example, this will NOT work because it registers a `Test` without specifying the test classes or paths: + +```kotlin +tasks.register("IntegrationTestUserCreds") { + dependsOn(tasks.shadowJar) + dependsOn(tasks.named("copyAgent")) + ... +} +``` + +This is fixed by specifying the test classes and classpath explicitly: + +```kotlin +tasks.register("IntegrationTestUserCreds") { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + dependsOn(tasks.shadowJar) + dependsOn(tasks.named("copyAgent")) + ... +} +``` + +## Coding Agent Instructions + +When implementing changes or new features: + +1. Follow all [Style Guide](../docs/style-guide.md) conventions and the Code Review Priorities above +2. Run tests to ensure they still pass (use `./gradlew test` and `./gradlew integrationTest` as needed) +3. **Always run `./gradlew spotlessApply`** after making code changes to ensure proper formatting +4. Run markdown lint to ensure it still passes: `npx markdownlint-cli@0.45.0 -c .github/config/markdownlint.yml **/*.md` diff --git a/.github/renovate.json5 b/.github/renovate.json5 index df236f85e..c6a64fbe0 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -85,7 +85,7 @@ ], enabled: false, matchPackageNames: [ - 'org.mockito:{/,}**', + 'org.mockito:**', ], }, { @@ -123,25 +123,33 @@ matchCurrentVersion: '3.5.0', enabled: false, matchPackageNames: [ - 'org.apache.maven:{/,}**', + 'org.apache.maven:**', ], }, { groupName: 'spotless packages', matchPackageNames: [ - 'com.diffplug.spotless{/,}**', + 'com.diffplug.spotless', + 'com.diffplug.spotless:**', ], }, { groupName: 'hipparchus packages', matchPackageNames: [ - 'org.hipparchus{/,}**', + 'org.hipparchus:**', ], }, { groupName: 'errorprone packages', matchPackageNames: [ - 'com.google.errorprone{/,}**', + 'com.google.errorprone:**', + ], + }, + { + groupName: 'jackson packages', + matchPackageNames: [ + 'com.fasterxml.jackson:**', + 'com.fasterxml.jackson.core:**', ], }, { @@ -151,7 +159,7 @@ ], enabled: false, matchPackageNames: [ - 'org.openjdk.jmc{/,}**', + 'org.openjdk.jmc:**', ], }, { @@ -162,7 +170,7 @@ matchCurrentVersion: '5.0.0', enabled: false, matchPackageNames: [ - 'jakarta.servlet:{/,}**', + 'jakarta.servlet:**', ], }, { @@ -175,7 +183,7 @@ ], enabled: false, matchPackageNames: [ - 'org.springframework.boot{/,}**', + 'org.springframework.boot:**', ], }, ], @@ -202,5 +210,15 @@ depNameTemplate: 'java', extractVersionTemplate: '^(?\\d+)', }, + { + customType: 'regex', + datasourceTemplate: 'github-releases', + managerFilePatterns: [ + '**/build.gradle.kts', + ], + matchStrings: [ + '"https://github.com/(?[^/]+/[^/]+)/zipball/(?.+?)"', + ], + }, ], } diff --git a/.github/scripts/dependencies.Dockerfile b/.github/scripts/dependencies.Dockerfile deleted file mode 100644 index d8e3bbfe1..000000000 --- a/.github/scripts/dependencies.Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -# this file exists so that Renovate can auto-update docker image versions that are then used elsewhere - -FROM lycheeverse/lychee:sha-2aa22f8@sha256:2e3786630482c41f9f2dd081e06d7da1c36d66996e8cf6573409b8bc418d48c4 AS lychee diff --git a/.github/scripts/draft-change-log-entries.sh b/.github/scripts/draft-change-log-entries.sh index 845c92672..489c1fe4d 100755 --- a/.github/scripts/draft-change-log-entries.sh +++ b/.github/scripts/draft-change-log-entries.sh @@ -35,6 +35,7 @@ component_names["consistent-sampling/"]="Consistent sampling" component_names["disk-buffering/"]="Disk buffering" component_names["gcp-resources/"]="GCP resources" component_names["gcp-auth-extension/"]="GCP authentication extension" +component_names["ibm-mq-metrics/"]="IBM MQ metrics" component_names["inferred-spans/"]="Inferred spans" component_names["jfr-connection/"]="JFR connection" component_names["jfr-events/"]="JFR events" @@ -44,6 +45,7 @@ component_names["kafka-exporter/"]="Kafka exporter" component_names["maven-extension/"]="Maven extension" component_names["micrometer-meter-provider/"]="Micrometer MeterProvider" component_names["noop-api/"]="No-op API" +component_names["opamp-client/"]="OpAMP client" component_names["processors/"]="Telemetry processors" component_names["prometheus-client-bridge/"]="Prometheus client bridge" component_names["runtime-attach/"]="Runtime attach" diff --git a/.github/scripts/link-check.sh b/.github/scripts/link-check.sh deleted file mode 100755 index 7e6b6910a..000000000 --- a/.github/scripts/link-check.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -set -e - -export MSYS_NO_PATHCONV=1 # for Git Bash on Windows - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT_DIR="$SCRIPT_DIR/../.." -DEPENDENCIES_DOCKERFILE="$SCRIPT_DIR/dependencies.Dockerfile" - -# Parse command line arguments -LOCAL_LINKS_ONLY=false -TARGET="" - -while [[ $# -gt 0 ]]; do - case $1 in - --local-links-only) - LOCAL_LINKS_ONLY=true - shift - ;; - *) - # Treat any other arguments as file paths - TARGET="$TARGET $1" - shift - ;; - esac -done - -# Extract lychee version from dependencies.dockerfile -LYCHEE_VERSION=$(grep "FROM lycheeverse/lychee:" "$DEPENDENCIES_DOCKERFILE" | sed 's/.*FROM lycheeverse\/lychee:\([^ ]*\).*/\1/') - -if [[ -z "$TARGET" ]]; then - TARGET="." -fi - -# Build the lychee command with optional GitHub token -CMD="lycheeverse/lychee:$LYCHEE_VERSION --verbose --root-dir /data" - -# Add GitHub token if available -if [[ -n "$GITHUB_TOKEN" ]]; then - CMD="$CMD --github-token $GITHUB_TOKEN" -fi - -if [[ "$LOCAL_LINKS_ONLY" == "true" ]]; then - CMD="$CMD --scheme file --include-fragments" -else - CMD="$CMD --config .github/scripts/lychee-config.toml" -fi - -CMD="$CMD $TARGET" - -# Determine if we should allocate a TTY -DOCKER_FLAGS="--rm --init" -if [[ -t 0 ]]; then - DOCKER_FLAGS="$DOCKER_FLAGS -it" -else - DOCKER_FLAGS="$DOCKER_FLAGS -i" -fi - -# Run lychee with proper signal handling -# shellcheck disable=SC2086 -exec docker run $DOCKER_FLAGS -v "$ROOT_DIR":/data -w /data $CMD diff --git a/.github/scripts/lychee-config.toml b/.github/scripts/lychee-config.toml deleted file mode 100644 index d368a2404..000000000 --- a/.github/scripts/lychee-config.toml +++ /dev/null @@ -1,16 +0,0 @@ -timeout = 30 -retry_wait_time = 5 -max_retries = 6 -max_concurrency = 4 - -# Check link anchors -include_fragments = true - -# excluding links to pull requests and issues is done for performance -# sonatype snapshots are currrently unbrowseable -exclude = [ - "^https://github.com/open-telemetry/opentelemetry-java-contrib/(issues|pull)/\\d+$", - '^https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/opentelemetry/contrib/$', -] - - diff --git a/.github/scripts/package-lock.json b/.github/scripts/package-lock.json new file mode 100644 index 000000000..f364e1106 --- /dev/null +++ b/.github/scripts/package-lock.json @@ -0,0 +1,27 @@ +{ + "name": "github-scripts", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "github-scripts", + "version": "1.0.0", + "dependencies": { + "yaml": "2.8.1" + } + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + } + } +} diff --git a/.github/scripts/package.json b/.github/scripts/package.json new file mode 100644 index 000000000..efca3b345 --- /dev/null +++ b/.github/scripts/package.json @@ -0,0 +1,9 @@ +{ + "//": "Dependencies for GitHub Actions workflows that use actions/github-script", + "name": "github-scripts", + "version": "1.0.0", + "private": true, + "dependencies": { + "yaml": "2.8.1" + } +} diff --git a/.github/workflows/assign-issue-owners.yml b/.github/workflows/assign-issue-owners.yml index 232396d9c..7d7acba67 100644 --- a/.github/workflows/assign-issue-owners.yml +++ b/.github/workflows/assign-issue-owners.yml @@ -19,15 +19,15 @@ jobs: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Install js-yaml - run: npm install js-yaml + - name: Install yaml dependency used below + run: npm install .github/scripts - name: Parse component label and assign owners - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | const fs = require('fs'); - const yaml = require('js-yaml'); + const { parse } = require('yaml'); // Extract component name from label const labelName = context.payload.label.name; @@ -42,7 +42,7 @@ jobs: // Read and parse component_owners.yml const yamlContent = fs.readFileSync('.github/component_owners.yml', 'utf8'); - const data = yaml.load(yamlContent); + const data = parse(yamlContent); if (!data || !data.components) { core.setFailed('Invalid component_owners.yml structure'); diff --git a/.github/workflows/assign-reviewers.yml b/.github/workflows/assign-reviewers.yml index 5994bd2e1..d1cf86ce8 100644 --- a/.github/workflows/assign-reviewers.yml +++ b/.github/workflows/assign-reviewers.yml @@ -18,6 +18,7 @@ jobs: pull-requests: write # for assigning reviewers runs-on: ubuntu-latest steps: - - uses: open-telemetry/assign-reviewers-action@2f4f06ccc561740d5094d9ca5e66dc2392d13e8f # main + - uses: dyladan/component-owners@58bd86e9814d23f1525d0a970682cead459fa783 # v0.1.0 with: config-file: .github/component_owners.yml + assign-owners: false diff --git a/.github/workflows/auto-spotless-apply.yml b/.github/workflows/auto-spotless-apply.yml index 36da59e0d..b363b4977 100644 --- a/.github/workflows/auto-spotless-apply.yml +++ b/.github/workflows/auto-spotless-apply.yml @@ -32,7 +32,7 @@ jobs: echo "exists=true" >> $GITHUB_OUTPUT fi - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: steps.unzip-patch.outputs.exists == 'true' id: otelbot-token with: diff --git a/.github/workflows/auto-spotless-check.yml b/.github/workflows/auto-spotless-check.yml index f6b873119..f4e171bb0 100644 --- a/.github/workflows/auto-spotless-check.yml +++ b/.github/workflows/auto-spotless-check.yml @@ -19,13 +19,13 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: true diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index eeb3ce5e3..a798378c6 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -12,7 +12,7 @@ permissions: jobs: backport: permissions: - contents: write # for Git to git push + contents: write # for git push to PR branch runs-on: ubuntu-latest steps: - run: | @@ -29,7 +29,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} @@ -48,6 +48,15 @@ jobs: git checkout -b $branch git cherry-pick $commit + + if git diff --name-only HEAD~1 HEAD | grep -q '^\.github/workflows/'; then + echo "::error::This PR contains changes to workflow files (.github/workflows/)." + echo "::error::Workflow files cannot be automatically backported because the standard" + echo "::error::GitHub token doesn't have the required 'workflow' write permission." + echo "::error::Please backport this PR manually." + exit 1 + fi + git push --set-upstream origin $branch gh pr create --title "[$GITHUB_REF_NAME] $title" \ --body "Clean cherry-pick of #$NUMBER to the \`$GITHUB_REF_NAME\` branch." \ diff --git a/.github/workflows/build-common.yml b/.github/workflows/build-common.yml index e66619ec9..bb50858cc 100644 --- a/.github/workflows/build-common.yml +++ b/.github/workflows/build-common.yml @@ -18,24 +18,59 @@ permissions: contents: read jobs: + spotless: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Set up JDK for running Gradle + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + with: + distribution: temurin + java-version: 17 + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + with: + cache-read-only: ${{ inputs.cache-read-only }} + + - name: Spotless + run: ./gradlew spotlessCheck ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + build: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: ${{ inputs.cache-read-only }} - - name: Gradle build and test - run: ./gradlew build -x test ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + - name: Build + run: ./gradlew build -x spotlessCheck -x test ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + + - name: Check for jApiCmp diffs + # The jApiCmp diff compares current to latest, which isn't appropriate for release branches + if: ${{ !startsWith(github.ref_name, 'release/') && !startsWith(github.base_ref, 'release/') }} + run: | + # need to "git add" in case any generated files did not already exist + git add docs/apidiffs + if git diff --cached --quiet + then + echo "No diff detected." + else + echo "Diff detected - did you run './gradlew jApiCmp'?" + git diff --cached --name-only + git diff --cached + exit 1 + fi test: name: Test @@ -44,8 +79,6 @@ jobs: fail-fast: false matrix: os: - - macos-latest - - macos-13 - ubuntu-latest - windows-latest test-java-version: @@ -54,41 +87,29 @@ jobs: - 17 - 21 - 24 # renovate: datasource=java-version - # macos-latest drops support for java 8 temurin. Run java 8 on macos-13. Run java 11, 17, 21 on macos-latest. - exclude: - - os: macos-latest - test-java-version: 8 - - os: macos-13 - test-java-version: 11 - - os: macos-13 - test-java-version: 17 - - os: macos-13 - test-java-version: 21 - - os: macos-13 - test-java-version: 24 # renovate: datasource=java-version steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - id: setup-java-test name: Set up Java ${{ matrix.test-java-version }} for tests - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: ${{ matrix.test-java-version }} - id: setup-java name: Set up Java for build - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: ${{ inputs.cache-read-only }} - - name: Gradle test + - name: Test run: > ./gradlew test "-PtestJavaVersion=${{ matrix.test-java-version }}" @@ -97,25 +118,33 @@ jobs: "-PmaxTestRetries=${{ inputs.max-test-retries }}" ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + - name: Build scan + if: ${{ !cancelled() && hashFiles('build-scan.txt') != '' }} + run: cat build-scan.txt + integration-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: ${{ inputs.cache-read-only }} - name: Integration test run: ./gradlew integrationTest "-PmaxTestRetries=${{ inputs.max-test-retries }}" ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + - name: Build scan + if: ${{ !cancelled() && hashFiles('build-scan.txt') != '' }} + run: cat build-scan.txt + - name: Save integration test results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2620367bb..badd5f855 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,17 +21,19 @@ jobs: needs: - common runs-on: ubuntu-latest + # skipping release branches because the versions in those branches are not snapshots + if: github.ref_name == 'main' && github.repository == 'open-telemetry/opentelemetry-java-contrib' steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - name: Build and publish snapshots run: ./gradlew assemble publishToSonatype diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 63d475c02..d22ef1ab5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,10 +1,6 @@ name: CodeQL on: - push: - branches: - - main - - release/* pull_request: branches: - main @@ -15,6 +11,10 @@ on: # - https://github.com/github/codeql-action/issues/1537 # - https://github.com/github/codeql-action/issues/2691 # merge_group: + push: + branches: + - main + - release/* schedule: - cron: "29 13 * * 2" # weekly at 13:29 UTC on Tuesday @@ -40,17 +40,17 @@ jobs: - name: Set up Java 17 if: matrix.language == 'java' - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle if: matrix.language == 'java' - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - name: Initialize CodeQL - uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 with: languages: ${{ matrix.language }} # using "linked" helps to keep up with the latest Kotlin support @@ -65,6 +65,6 @@ jobs: run: ./gradlew assemble --no-build-cache --no-daemon - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000..8638dc7ee --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,34 @@ +# Custom setup steps for GitHub Copilot coding agent to speed up Copilot's work on coding tasks +name: "Copilot Setup Steps" + +on: + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + push: + paths: + - .github/workflows/copilot-setup-steps.yml + workflow_dispatch: + +permissions: + contents: read + +jobs: + copilot-setup-steps: # Job name required by GitHub Copilot coding agent + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Set up JDK for running Gradle + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + with: + distribution: temurin + java-version: 17 + + - name: Set up gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + + - name: Build project and download dependencies + run: ./gradlew build -x test diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 45e549ad0..6fbd70463 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -17,4 +17,4 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: gradle/actions/wrapper-validation@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - uses: gradle/actions/wrapper-validation@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 diff --git a/.github/workflows/issue-management-stale-action.yml b/.github/workflows/issue-management-stale-action.yml index 483df9b15..7282d3fcd 100644 --- a/.github/workflows/issue-management-stale-action.yml +++ b/.github/workflows/issue-management-stale-action.yml @@ -16,7 +16,7 @@ jobs: pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 + - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 7 diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 0c8d3af84..c186d16e2 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -23,7 +23,7 @@ jobs: with: persist-credentials: false - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: create-token with: # analyzing classic branch protections requires a token with admin read permissions @@ -52,6 +52,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 with: sarif_file: results.sarif diff --git a/.github/workflows/owasp-dependency-check-daily.yml b/.github/workflows/owasp-dependency-check-daily.yml index 724b7605b..1494926ba 100644 --- a/.github/workflows/owasp-dependency-check-daily.yml +++ b/.github/workflows/owasp-dependency-check-daily.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 @@ -27,7 +27,7 @@ jobs: run: | sed -i "s/org.gradle.jvmargs=/org.gradle.jvmargs=-Xmx3g /" gradle.properties - - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - run: ./gradlew dependencyCheckAnalyze env: diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml index a6d2a64aa..70bfd208a 100644 --- a/.github/workflows/prepare-patch-release.yml +++ b/.github/workflows/prepare-patch-release.yml @@ -47,7 +47,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} diff --git a/.github/workflows/prepare-release-branch.yml b/.github/workflows/prepare-release-branch.yml index f1c5160d5..58c5dc8bb 100644 --- a/.github/workflows/prepare-release-branch.yml +++ b/.github/workflows/prepare-release-branch.yml @@ -59,7 +59,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} @@ -116,7 +116,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7b7f9af7a..68800fa37 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,64 +1,25 @@ name: Release on: workflow_dispatch: + inputs: + already-published: + description: 'Skip publishing, download artifacts from Maven Central instead' + default: false + type: boolean permissions: contents: read jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 - with: - distribution: temurin - java-version: 17 - - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 - - name: Gradle build - run: ./gradlew build - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - name: Save unit test results - if: always() - with: - name: test-results - path: jmx-metrics/build/reports/tests/test - - integration-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 - with: - distribution: temurin - java-version: 17 - - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 - - name: Integration test - run: ./gradlew integrationTest - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - name: Save integration test results - if: always() - with: - name: integration-test-results - path: jmx-metrics/build/reports/tests/integrationTest + common: + uses: ./.github/workflows/build-common.yml release: permissions: contents: write # for creating the release runs-on: ubuntu-latest needs: - - build - - integration-test + - common outputs: version: ${{ steps.create-github-release.outputs.version }} steps: @@ -118,14 +79,16 @@ jobs: fetch-depth: 0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + - name: Build and publish artifacts + if: ${{ !inputs.already-published }} run: ./gradlew assemble publishToSonatype closeAndReleaseSonatypeStagingRepository env: SONATYPE_USER: ${{ secrets.SONATYPE_USER }} @@ -133,6 +96,21 @@ jobs: GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} + - name: Download artifacts from Maven Central (when already published) + if: ${{ inputs.already-published }} + run: | + mkdir -p jmx-metrics/build/libs + mkdir -p jmx-scraper/build/libs + + curl -L -o jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-metrics/$VERSION-alpha/opentelemetry-jmx-metrics-$VERSION-alpha.jar" + curl -L -o jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar.asc \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-metrics/$VERSION-alpha/opentelemetry-jmx-metrics-$VERSION-alpha.jar.asc" + curl -L -o jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-scraper/$VERSION-alpha/opentelemetry-jmx-scraper-$VERSION-alpha.jar" + curl -L -o jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar.asc \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-scraper/$VERSION-alpha/opentelemetry-jmx-scraper-$VERSION-alpha.jar.asc" + - name: Generate release notes env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -182,27 +160,28 @@ jobs: cp jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar opentelemetry-jmx-metrics.jar cp jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar.asc opentelemetry-jmx-metrics.jar.asc cp jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar opentelemetry-jmx-scraper.jar - cp jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar opentelemetry-jmx-scraper.jar.asc + cp jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar.asc opentelemetry-jmx-scraper.jar.asc gh release create --target $GITHUB_REF_NAME \ --title "Version $VERSION" \ --notes-file /tmp/release-notes.txt \ v$VERSION \ opentelemetry-jmx-metrics.jar \ - opentelemetry-jmx-metrics.jar.asc \ + opentelemetry-jmx-metrics.jar.asc \ opentelemetry-jmx-scraper.jar \ - opentelemetry-jmx-scraper.jar.asc - + opentelemetry-jmx-scraper.jar.asc echo "version=$VERSION" >> $GITHUB_OUTPUT - merge-change-log-to-main: + post-release-updates: permissions: contents: write # for git push to PR branch runs-on: ubuntu-latest needs: - release steps: + # add change log sync (if any) into this PR since the apidiff update + # is required before any other PR can be merged anyway - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Copy change log section from release branch @@ -224,10 +203,41 @@ jobs: release_date=$(gh release view v$VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//') RELEASE_DATE=$release_date .github/scripts/merge-change-log-after-release.sh + - name: Wait for release to be available in maven central + env: + VERSION: ${{ needs.release.outputs.version }} + run: | + until curl --silent \ + --show-error \ + --output /dev/null \ + --head \ + --fail \ + https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-aws-xray/$VERSION/opentelemetry-aws-xray-$VERSION.jar + do + sleep 60 + done + + - name: Set up JDK for running Gradle + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + with: + distribution: temurin + java-version: 17 + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + + - name: Update apidiff baseline + env: + VERSION: ${{ needs.release.outputs.version }} + PRIOR_VERSION: ${{ needs.release.outputs.prior-version }} + run: | + ./gradlew japicmp -PapiBaseVersion=$PRIOR_VERSION -PapiNewVersion=$VERSION + ./gradlew --refresh-dependencies japicmp + - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} @@ -239,22 +249,14 @@ jobs: # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows GH_TOKEN: ${{ steps.otelbot-token.outputs.token }} run: | - if git diff --quiet; then - if [[ $VERSION == *.0 ]]; then - echo there are no updates to merge, not creating pull request - exit 0 # success - else - echo patch release notes did not get applied for some reason - exit 1 # failure - fi - fi - - message="Merge change log updates from $GITHUB_REF_NAME" - body="Merge log updates from \`$GITHUB_REF_NAME\`." - branch="otelbot/merge-change-log-updates-from-${GITHUB_REF_NAME//\//-}" + message="Post-release updates for $VERSION" + body="Post-release updates for `$VERSION`." + branch="otelbot/update-apidiff-baseline-to-released-version-${VERSION}" git checkout -b $branch - git commit -a -m "$message" + git add CHANGELOG.md + git add docs/apidiffs + git commit -m "$message" git push --set-upstream origin $branch gh pr create --title "$message" \ --body "$body" \ diff --git a/.github/workflows/reusable-link-check.yml b/.github/workflows/reusable-link-check.yml index da70758ff..9cfd9ff48 100644 --- a/.github/workflows/reusable-link-check.yml +++ b/.github/workflows/reusable-link-check.yml @@ -14,11 +14,13 @@ jobs: with: fetch-depth: 0 # needed for merge-base below + - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0 + - name: Link check - relative links (all files) if: github.event_name == 'pull_request' env: GITHUB_TOKEN: ${{ github.token }} - run: ./.github/scripts/link-check.sh --local-links-only + run: mise run lint-local-links - name: Get modified files if: github.event_name == 'pull_request' @@ -26,20 +28,34 @@ jobs: run: | merge_base=$(git merge-base origin/${{ github.base_ref }} HEAD) # Using lychee's default extension filter here to match when it runs against all files - modified_files=$(git diff --name-only $merge_base...${{ github.event.pull_request.head.sha }} \ + # Note: --diff-filter=d filters out deleted files + modified_files=$(git diff --name-only --diff-filter=d $merge_base...${{ github.event.pull_request.head.sha }} \ | grep -E '\.(md|mkd|mdx|mdown|mdwn|mkdn|mkdown|markdown|html|htm|txt)$' \ | tr '\n' ' ' || true) echo "files=$modified_files" >> $GITHUB_OUTPUT echo "Modified files: $modified_files" + - name: Check if lychee config was modified + if: github.event_name == 'pull_request' + id: config-check + run: | + merge_base=$(git merge-base origin/${{ github.base_ref }} HEAD) + config_modified=$(git diff --name-only $merge_base...${{ github.event.pull_request.head.sha }} \ + | grep -E '^(\.github/config/lychee\.toml|mise\.toml)$' || true) + if [ -n "$config_modified" ]; then + echo "modified=true" >> $GITHUB_OUTPUT + else + echo "modified=false" >> $GITHUB_OUTPUT + fi + - name: Link check - all links (modified files only) if: github.event_name == 'pull_request' && steps.modified-files.outputs.files != '' env: GITHUB_TOKEN: ${{ github.token }} - run: ./.github/scripts/link-check.sh ${{ steps.modified-files.outputs.files }} + run: mise run lint-links ${{ steps.modified-files.outputs.files }} - name: Link check - all links (all files) - if: github.event_name != 'pull_request' + if: github.event_name != 'pull_request' || steps.config-check.outputs.modified == 'true' env: GITHUB_TOKEN: ${{ github.token }} - run: ./.github/scripts/link-check.sh + run: mise run lint-links diff --git a/.gitignore b/.gitignore index 641751d61..4743c99e3 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ bin .swp .gitpod.yml + +# Gradle build scans +build-scan.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index e6744eff5..1f34222ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,33 @@ ## Unreleased +## Version 1.49.0 (2025-08-25) + +### Consistent sampling + +- Add updateable threshold sampler for dynamic sampling configuration + ([#2137](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2137)) + +### Disk buffering + +- Introduce API changes for improved disk buffering functionality + ([#2084](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2084)) +- Implement more efficient serializer with direct disk write capabilities + ([#2138](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2138)) + +### IBM MQ metrics - New 🌟 + +IBM MQ metrics collection utility. + +### Inferred spans + +- Update async profiler to version 4.1 for improved performance + ([#2096](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2096)) + +### OpAMP client - New 🌟 + +OpenTelemetry Agent Management Protocol (OpAMP) client implementation. + ## Version 1.48.0 (2025-07-23) ### AWS resources @@ -243,7 +270,7 @@ The extension takes care of the necessary configuration required to authenticate The future of the [JMX metrics](./jmx-metrics/README.md) component, built on top of the -[JMX metrics](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/jmx-metrics/javaagent#jmx-metric-insight) +[JMX metrics](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/jmx-metrics#jmx-metric-insight) component from the opentelemetry-java-instrumentation repository. ### Maven extension diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6d8a6a806..04a50c300 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,82 +1,65 @@ # Contributing -Welcome to the OpenTelemetry Java Contrib Repository! +Welcome to the OpenTelemetry Java Contrib repository! ## Introduction -This repository focuses on providing tools and utilities for Java-based observability, such as remote JMX metric gathering and reporting. We’re excited to have you here! Whether you’re fixing a bug, adding a feature, or suggesting an idea, your contributions are invaluable. +This repository provides observability libraries and utilities for Java applications that complement +the [OpenTelemetry Java SDK](https://github.com/open-telemetry/opentelemetry-java) and +[OpenTelemetry Java Instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation) +projects. -Before submitting new features or changes to current functionality, it is recommended to first -[open an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new) -and discuss your ideas or propose the changes you wish to make. - -Questions? Ask in the OpenTelemetry [java channel](https://cloud-native.slack.com/archives/C014L2KCTE3) +Before submitting new features or changes, please consider +[opening an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new) first to +discuss your ideas. Pull requests for bug fixes are always welcome! -## Pre-requisites - -To work with this repository, ensure you have: - -### Tools: - -Java 17 or higher - -### Platform Notes: +## Building and Testing -macOS/Linux: Ensure JAVA_HOME is set correctly. +While most modules target Java 8, building this project requires Java 17 or higher. -## Workflow - -1. Fork the repository -2. Clone locally -3. Create a branch before working on an issue - -## Local Run/Build - -In order to build and test this whole repository you need JDK 11+. - -#### Snapshot builds - -For developers testing code changes before a release is complete, there are -snapshot builds of the `main` branch. They are available from -the Sonatype snapshot repository at `https://central.sonatype.com/repository/maven-snapshots/` -([browse](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/opentelemetry/contrib/)). - -#### Building from source - -Building using Java 11+: +To build the project: ```bash -$ java -version +./gradlew assemble ``` +To run the tests: + ```bash -$ ./gradlew assemble +./gradlew test ``` -## Testing +Some modules include integration tests that can be run with: ```bash -$ ./gradlew test +./gradlew integrationTest ``` -### Some modules have integration tests +## Snapshot Builds -``` -$ ./gradlew integrationTest -``` +Snapshot builds of the `main` branch are available from the Sonatype snapshot repository at: +`https://central.sonatype.com/repository/maven-snapshots/` +([browse](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/opentelemetry/contrib/)). + +## Style Guide + +See [Style Guide](docs/style-guide.md). -Follow the Java Instrumentation [Style Guide](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/contributing/style-guideline.md) from the opentelemetry-java-instrumentation repository. +## Pull Request Guidelines -Failure? Check logs for errors or mismatched dependencies. +When submitting a pull request, please ensure that you: -## Gradle conventions +- Clearly describe the change and its motivation +- Mention any breaking changes +- Include tests for new functionality +- Follow the [Style Guide](docs/style-guide.md) -- Use kotlin instead of groovy -- Plugin versions should be specified in `settings.gradle.kts`, not in individual modules -- All modules use `plugins { id("otel.java-conventions") }` +## Getting Help -## Further Help +If you need assistance or have questions: -Join [#otel-java](https://cloud-native.slack.com/archives/C014L2KCTE3) on OpenTelemetry Slack +- Post on the [#otel-java](https://cloud-native.slack.com/archives/C014L2KCTE3) Slack channel +- [Open an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new/choose) in + this repository diff --git a/README.md b/README.md index c42ea7e27..4ba3fdc12 100644 --- a/README.md +++ b/README.md @@ -48,30 +48,9 @@ On reaching stable status, the `otel.stable` value in `gradle.properties` should Note that currently all the libraries are released together with the version of this repo, so breaking changes (after stable status is reached) would bump the major version of all libraries together. This could get complicated so `stable` has a high bar. -## Getting Started - -```bash -# Apply formatting -$ ./gradlew spotlessApply - -# Build the complete project -$ ./gradlew build - -# Run integration tests -$ ./gradlew integrationTest - -# Clean artifacts -$ ./gradlew clean -``` - ## Contributing -The Java Contrib project was initially formed to provide methods of easy remote JMX metric gathering and reporting, -which is actively in development. If you have an idea for a similar use case in the metrics, traces, or logging -domain we would be very interested in supporting it. Please -[open an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new/choose) to share your idea or -suggestion. PRs are always welcome and greatly appreciated, but for larger functional changes a pre-coding introduction -can be helpful to ensure this is the correct place and that active or conflicting efforts don't exist. +See [CONTRIBUTING.md](CONTRIBUTING.md). ### Maintainers @@ -84,7 +63,8 @@ For more information about the maintainer role, see the [community repository](h ### Approvers -- [John Watson](https://github.com/jkwatson), Verta.ai +- [Jay DeLuca](https://github.com/jaydeluca), Grafana +- [John Watson](https://github.com/jkwatson), Cloudera For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver). diff --git a/all/README.md b/all/README.md deleted file mode 100644 index dca83da7b..000000000 --- a/all/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# opentelemetry-contrib-all (utility project) - -This is a utility project which depends on all other projects in this repository. -We use it for collecting all coverage reports from all modules for uploading to codecov. diff --git a/all/build.gradle.kts b/all/build.gradle.kts deleted file mode 100644 index 58f0f6d72..000000000 --- a/all/build.gradle.kts +++ /dev/null @@ -1,64 +0,0 @@ -plugins { - `jacoco-report-aggregation` - - id("otel.java-conventions") -} - -description = "OpenTelemetry Contrib All" - -dependencies { - rootProject.subprojects.forEach { subproject -> - // Generate aggregate coverage report for published modules that enable jacoco. - subproject.plugins.withId("jacoco") { - subproject.plugins.withId("maven-publish") { - // TODO(anuraaga): Figure out how to avoid transitive dependencies being pulled into jacoco due to the use - // of shadow plugin. - if (subproject.name != "jmx-metrics") { - implementation(project(subproject.path)) { - isTransitive = false - } - } - } - } - } -} - -tasks { - // We don't compile anything here. This project is mostly for - // aggregating jacoco reports and it doesn't work if this isn't at least as high as the - // highest supported Java version in any of our projects. Most of our projects target - // Java 8, but some target Java 11 or 17. - withType(JavaCompile::class) { - options.release.set(17) - } -} - -afterEvaluate { - tasks { - testCodeCoverageReport { - classDirectories.setFrom( - classDirectories.files.map { - zipTree(it).filter { - // Exclude mrjar (jacoco complains), shaded, and generated code - !it.absolutePath.contains("META-INF/versions/") && - !it.absolutePath.contains("AutoValue_") - } - }, - ) - - reports { - // xml is usually used to integrate code coverage with - // other tools like SonarQube, Coveralls or Codecov - xml.required.set(true) - - // HTML reports can be used to see code coverage - // without any external tools - html.required.set(true) - } - } - } -} - -dependencyCheck { - skip = true -} diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java index 9f294d4fb..7441b7c81 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java @@ -12,6 +12,7 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.SERVICE_INSTANCE_ID; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.SERVICE_NAMESPACE; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_VERSION; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -22,7 +23,6 @@ import io.opentelemetry.semconv.SchemaUrls; import java.io.File; import java.io.IOException; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -65,7 +65,7 @@ static Resource buildResource(String configPath) { parser.nextToken(); if (!parser.isExpectedStartObjectToken()) { - logger.log(Level.WARNING, "Invalid Beanstalk config: ", configPath); + logger.log(WARNING, "Invalid Beanstalk config: ", configPath); return Resource.create(attrBuilders.build(), SchemaUrls.V1_25_0); } @@ -87,7 +87,7 @@ static Resource buildResource(String configPath) { } } } catch (IOException e) { - logger.log(Level.WARNING, "Could not parse Beanstalk config.", e); + logger.log(WARNING, "Could not parse Beanstalk config.", e); return Resource.empty(); } diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java index 5b8aefeac..a52cf1c18 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java @@ -5,11 +5,12 @@ package io.opentelemetry.contrib.aws.resource; +import static java.util.logging.Level.WARNING; + import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.util.logging.Level; import java.util.logging.Logger; class DockerHelper { @@ -44,9 +45,9 @@ public String getContainerId() { } } } catch (FileNotFoundException e) { - logger.log(Level.WARNING, "Failed to read container id, cgroup file does not exist."); + logger.log(WARNING, "Failed to read container id, cgroup file does not exist."); } catch (IOException e) { - logger.log(Level.WARNING, "Unable to read container id: " + e.getMessage()); + logger.log(WARNING, "Unable to read container id: " + e.getMessage()); } return ""; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java index d4bdb4228..5aa930b1c 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java @@ -15,6 +15,7 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.HOST_IMAGE_ID; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.HOST_NAME; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.HOST_TYPE; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -28,7 +29,6 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -125,7 +125,7 @@ static Resource buildResource(String endpoint) { } } } catch (IOException e) { - logger.log(Level.WARNING, "Could not parse identity document, resource not filled.", e); + logger.log(WARNING, "Could not parse identity document, resource not filled.", e); return Resource.empty(); } diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java index efb112de8..83440819b 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java @@ -26,6 +26,9 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CONTAINER_NAME; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudPlatformIncubatingValues.AWS_ECS; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudProviderIncubatingValues.AWS; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonList; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -35,11 +38,9 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.SchemaUrls; import java.io.IOException; -import java.util.Collections; import java.util.Locale; import java.util.Map; import java.util.Optional; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -88,7 +89,7 @@ static Resource buildResource(Map sysEnv, SimpleHttpClient httpC static void fetchMetadata( SimpleHttpClient httpClient, String url, AttributesBuilder attrBuilders) { - String json = httpClient.fetchString("GET", url, Collections.emptyMap(), null); + String json = httpClient.fetchString("GET", url, emptyMap(), null); if (json.isEmpty()) { return; } @@ -103,17 +104,17 @@ static void fetchMetadata( .getLogGroupArn() .ifPresent( logGroupArn -> { - attrBuilders.put(AWS_LOG_GROUP_ARNS, Collections.singletonList(logGroupArn)); + attrBuilders.put(AWS_LOG_GROUP_ARNS, singletonList(logGroupArn)); }); logArnBuilder .getLogStreamArn() .ifPresent( logStreamArn -> { - attrBuilders.put(AWS_LOG_STREAM_ARNS, Collections.singletonList(logStreamArn)); + attrBuilders.put(AWS_LOG_STREAM_ARNS, singletonList(logStreamArn)); }); } catch (IOException e) { - logger.log(Level.WARNING, "Can't get ECS metadata", e); + logger.log(WARNING, "Can't get ECS metadata", e); } } @@ -156,7 +157,7 @@ static void parseResponse( JsonParser parser, AttributesBuilder attrBuilders, LogArnBuilder logArnBuilder) throws IOException { if (!parser.isExpectedStartObjectToken()) { - logger.log(Level.WARNING, "Couldn't parse ECS metadata, invalid JSON"); + logger.log(WARNING, "Couldn't parse ECS metadata, invalid JSON"); return; } @@ -339,7 +340,7 @@ static DockerImage parse(@Nullable String image) { } Matcher matcher = imagePattern.matcher(image); if (!matcher.matches()) { - logger.log(Level.WARNING, "Couldn't parse image '" + image + "'"); + logger.log(WARNING, "Couldn't parse image '" + image + "'"); return null; } String repository = matcher.group("repository"); diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java index 8ed3fb512..156755446 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java @@ -11,6 +11,8 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudPlatformIncubatingValues.AWS_EKS; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudProviderIncubatingValues.AWS; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.K8S_CLUSTER_NAME; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -26,7 +28,6 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -91,7 +92,7 @@ static Resource buildResource( private static boolean isEks( String k8sTokenPath, String k8sKeystorePath, SimpleHttpClient httpClient) { if (!isK8s(k8sTokenPath, k8sKeystorePath)) { - logger.log(Level.FINE, "Not running on k8s."); + logger.log(FINE, "Not running on k8s."); return false; } @@ -145,7 +146,7 @@ private static String getClusterName(SimpleHttpClient httpClient) { } } } catch (IOException e) { - logger.log(Level.WARNING, "Can't get cluster name on EKS.", e); + logger.log(WARNING, "Can't get cluster name on EKS.", e); } return ""; } @@ -156,7 +157,7 @@ private static String getK8sCredHeader() { new String(Files.readAllBytes(Paths.get(K8S_TOKEN_PATH)), StandardCharsets.UTF_8); return "Bearer " + content; } catch (IOException e) { - logger.log(Level.WARNING, "Unable to load K8s client token.", e); + logger.log(WARNING, "Unable to load K8s client token.", e); } return ""; } diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java index 12bc6e34e..f78719d99 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.aws.resource; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.WARNING; + import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; @@ -13,7 +16,6 @@ import java.time.Duration; import java.util.Collection; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; import javax.net.ssl.SSLContext; @@ -72,7 +74,7 @@ public String fetchString( int responseCode = response.code(); if (responseCode != 200) { logger.log( - Level.FINE, + FINE, "Error response from " + urlStr + " code (" @@ -84,7 +86,7 @@ public String fetchString( ResponseBody body = response.body(); return body != null ? body.string() : ""; } catch (IOException e) { - logger.log(Level.FINE, "SimpleHttpClient fetch string failed.", e); + logger.log(FINE, "SimpleHttpClient fetch string failed.", e); } return ""; @@ -101,7 +103,7 @@ private static X509TrustManager buildTrustManager(@Nullable KeyStore keyStore) { tmf.init(keyStore); return (X509TrustManager) tmf.getTrustManagers()[0]; } catch (Exception e) { - logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); + logger.log(WARNING, "Build SslSocketFactory for K8s restful client exception.", e); return null; } } @@ -117,7 +119,7 @@ private static SSLSocketFactory buildSslSocketFactory(@Nullable TrustManager tru return context.getSocketFactory(); } catch (Exception e) { - logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); + logger.log(WARNING, "Build SslSocketFactory for K8s restful client exception.", e); } return null; } @@ -138,7 +140,7 @@ private static KeyStore getKeystoreForTrustedCert(String certPath) { } return trustStore; } catch (Exception e) { - logger.log(Level.WARNING, "Cannot load KeyStore from " + certPath); + logger.log(WARNING, "Cannot load KeyStore from " + certPath); return null; } } diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java index 7eaec5e55..31b05be57 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java @@ -34,7 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class EksResourceTest { +class EksResourceTest { @Mock private DockerHelper mockDockerHelper; diff --git a/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java b/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java index a6b6a2ab4..b34bc961c 100644 --- a/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java +++ b/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java @@ -5,12 +5,13 @@ package io.opentelemetry.contrib.awsxray.propagator; +import static java.util.Collections.singletonMap; + import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.context.propagation.TextMapSetter; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -75,7 +76,7 @@ public Context extract(Context context, @Nullable C carrier, TextMapGetter FIELDS = Collections.singletonList(TRACE_HEADER_KEY); + private static final List FIELDS = singletonList(TRACE_HEADER_KEY); private static final AwsXrayPropagator INSTANCE = new AwsXrayPropagator(); diff --git a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java index 53e806fdc..99998d974 100644 --- a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java +++ b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java @@ -15,7 +15,7 @@ import java.util.LinkedHashMap; import org.junit.jupiter.api.Test; -public class AwsXrayCompositePropagatorTest extends AwsXrayPropagatorTest { +class AwsXrayCompositePropagatorTest extends AwsXrayPropagatorTest { @Override TextMapPropagator propagator() { diff --git a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java index c2869d265..5bcd62137 100644 --- a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java +++ b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java @@ -21,7 +21,7 @@ class AwsComponentProviderTest { @Test void endToEnd() { String yaml = - "file_format: 0.4\n" + "file_format: 1.0-rc.1\n" + "propagator:\n" + " composite:\n" + " - xray:\n" diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java index 101641f08..c9e762d63 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.stringKey; + import io.opentelemetry.api.common.AttributeKey; /** Utility class holding attribute keys with special meaning to AWS components */ @@ -12,28 +14,25 @@ final class AwsAttributeKeys { private AwsAttributeKeys() {} - static final AttributeKey AWS_SPAN_KIND = AttributeKey.stringKey("aws.span.kind"); + static final AttributeKey AWS_SPAN_KIND = stringKey("aws.span.kind"); - static final AttributeKey AWS_LOCAL_SERVICE = AttributeKey.stringKey("aws.local.service"); + static final AttributeKey AWS_LOCAL_SERVICE = stringKey("aws.local.service"); - static final AttributeKey AWS_LOCAL_OPERATION = - AttributeKey.stringKey("aws.local.operation"); + static final AttributeKey AWS_LOCAL_OPERATION = stringKey("aws.local.operation"); - static final AttributeKey AWS_REMOTE_SERVICE = - AttributeKey.stringKey("aws.remote.service"); + static final AttributeKey AWS_REMOTE_SERVICE = stringKey("aws.remote.service"); - static final AttributeKey AWS_REMOTE_OPERATION = - AttributeKey.stringKey("aws.remote.operation"); + static final AttributeKey AWS_REMOTE_OPERATION = stringKey("aws.remote.operation"); - static final AttributeKey AWS_REMOTE_TARGET = AttributeKey.stringKey("aws.remote.target"); + static final AttributeKey AWS_REMOTE_TARGET = stringKey("aws.remote.target"); // use the same AWS Resource attribute name defined by OTel java auto-instr for aws_sdk_v_1_1 // TODO: all AWS specific attributes should be defined in semconv package and reused cross all // otel packages. Related sim - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/8710 - static final AttributeKey AWS_BUCKET_NAME = AttributeKey.stringKey("aws.bucket.name"); - static final AttributeKey AWS_QUEUE_NAME = AttributeKey.stringKey("aws.queue.name"); - static final AttributeKey AWS_STREAM_NAME = AttributeKey.stringKey("aws.stream.name"); - static final AttributeKey AWS_TABLE_NAME = AttributeKey.stringKey("aws.table.name"); + static final AttributeKey AWS_BUCKET_NAME = stringKey("aws.bucket.name"); + static final AttributeKey AWS_QUEUE_NAME = stringKey("aws.queue.name"); + static final AttributeKey AWS_STREAM_NAME = stringKey("aws.stream.name"); + static final AttributeKey AWS_TABLE_NAME = stringKey("aws.table.name"); } diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java index 42275b4b1..3fed3b3f3 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.longKey; +import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_BUCKET_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_LOCAL_OPERATION; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_LOCAL_SERVICE; @@ -16,6 +18,7 @@ import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_STREAM_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_TABLE_NAME; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; +import static java.util.logging.Level.FINEST; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -27,7 +30,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Optional; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -54,36 +56,31 @@ final class AwsMetricAttributeGenerator implements MetricAttributeGenerator { private static final String UNKNOWN_REMOTE_OPERATION = "UnknownRemoteOperation"; // copied from DbIncubatingAttributes - private static final AttributeKey DB_OPERATION = AttributeKey.stringKey("db.operation"); - private static final AttributeKey DB_SYSTEM = AttributeKey.stringKey("db.system"); + private static final AttributeKey DB_OPERATION = stringKey("db.operation"); + private static final AttributeKey DB_SYSTEM = stringKey("db.system"); // copied from FaasIncubatingAttributes - private static final AttributeKey FAAS_INVOKED_NAME = - AttributeKey.stringKey("faas.invoked_name"); - private static final AttributeKey FAAS_TRIGGER = AttributeKey.stringKey("faas.trigger"); + private static final AttributeKey FAAS_INVOKED_NAME = stringKey("faas.invoked_name"); + private static final AttributeKey FAAS_TRIGGER = stringKey("faas.trigger"); // copied from GraphqlIncubatingAttributes private static final AttributeKey GRAPHQL_OPERATION_TYPE = - AttributeKey.stringKey("graphql.operation.type"); + stringKey("graphql.operation.type"); // copied from HttpIncubatingAttributes - private static final AttributeKey HTTP_METHOD = AttributeKey.stringKey("http.method"); - private static final AttributeKey HTTP_TARGET = AttributeKey.stringKey("http.target"); - private static final AttributeKey HTTP_URL = AttributeKey.stringKey("http.url"); + private static final AttributeKey HTTP_METHOD = stringKey("http.method"); + private static final AttributeKey HTTP_TARGET = stringKey("http.target"); + private static final AttributeKey HTTP_URL = stringKey("http.url"); // copied from MessagingIncubatingAttributes - private static final AttributeKey MESSAGING_OPERATION = - AttributeKey.stringKey("messaging.operation"); - private static final AttributeKey MESSAGING_SYSTEM = - AttributeKey.stringKey("messaging.system"); + private static final AttributeKey MESSAGING_OPERATION = stringKey("messaging.operation"); + private static final AttributeKey MESSAGING_SYSTEM = stringKey("messaging.system"); // copied from NetIncubatingAttributes - private static final AttributeKey NET_PEER_NAME = AttributeKey.stringKey("net.peer.name"); - private static final AttributeKey NET_PEER_PORT = AttributeKey.longKey("net.peer.port"); - private static final AttributeKey NET_SOCK_PEER_ADDR = - AttributeKey.stringKey("net.sock.peer.addr"); - private static final AttributeKey NET_SOCK_PEER_PORT = - AttributeKey.longKey("net.sock.peer.port"); + private static final AttributeKey NET_PEER_NAME = stringKey("net.peer.name"); + private static final AttributeKey NET_PEER_PORT = longKey("net.peer.port"); + private static final AttributeKey NET_SOCK_PEER_ADDR = stringKey("net.sock.peer.addr"); + private static final AttributeKey NET_SOCK_PEER_PORT = longKey("net.sock.peer.port"); // copied from PeerIncubatingAttributes - private static final AttributeKey PEER_SERVICE = AttributeKey.stringKey("peer.service"); + private static final AttributeKey PEER_SERVICE = stringKey("peer.service"); // copied from RpcIncubatingAttributes - private static final AttributeKey RPC_METHOD = AttributeKey.stringKey("rpc.method"); - private static final AttributeKey RPC_SERVICE = AttributeKey.stringKey("rpc.service"); + private static final AttributeKey RPC_METHOD = stringKey("rpc.method"); + private static final AttributeKey RPC_SERVICE = stringKey("rpc.service"); @Override public Attributes generateMetricAttributesFromSpan(SpanData span, Resource resource) { @@ -307,7 +304,7 @@ private static String generateRemoteOperation(SpanData span) { remoteOperation = extractApiPathValue(url.getPath()); } } catch (MalformedURLException e) { - logger.log(Level.FINEST, "invalid http.url attribute: ", httpUrl); + logger.log(FINEST, "invalid http.url attribute: ", httpUrl); } } if (isKeyPresent(span, HTTP_METHOD)) { @@ -387,6 +384,6 @@ private static void logUnknownAttribute(AttributeKey attributeKey, SpanD String[] params = { attributeKey.getKey(), span.getKind().name(), span.getSpanContext().getSpanId() }; - logger.log(Level.FINEST, "No valid {0} value found for {1} span {2}", params); + logger.log(FINEST, "No valid {0} value found for {1} span {2}", params); } } diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java index 244138a47..9a3e60519 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.longKey; + import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; @@ -40,8 +42,7 @@ @Immutable public final class AwsSpanMetricsProcessor implements SpanProcessor { - private static final AttributeKey HTTP_STATUS_CODE = - AttributeKey.longKey("http.status_code"); + private static final AttributeKey HTTP_STATUS_CODE = longKey("http.status_code"); private static final double NANOS_TO_MILLIS = 1_000_000.0; diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java index ad9b72a2c..9c997f042 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java @@ -5,6 +5,14 @@ package io.opentelemetry.contrib.awsxray; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.function.Function.identity; +import static java.util.logging.Level.FINE; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; + import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; @@ -29,17 +37,13 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; import javax.annotation.Nullable; /** Remote sampler that gets sampling configuration from AWS X-Ray. */ public final class AwsXrayRemoteSampler implements Sampler, Closeable { - static final long DEFAULT_TARGET_INTERVAL_NANOS = TimeUnit.SECONDS.toNanos(10); + static final long DEFAULT_TARGET_INTERVAL_NANOS = SECONDS.toNanos(10); private static final Logger logger = Logger.getLogger(AwsXrayRemoteSampler.class.getName()); @@ -134,7 +138,7 @@ private void getAndUpdateSampler() { initialSampler, response.getSamplingRules().stream() .map(SamplingRuleRecord::getRule) - .collect(Collectors.toList()))); + .collect(toList()))); previousRulesResponse = response; ScheduledFuture existingFetchTargetsFuture = fetchTargetsFuture; @@ -142,18 +146,17 @@ private void getAndUpdateSampler() { existingFetchTargetsFuture.cancel(false); } fetchTargetsFuture = - executor.schedule( - this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, TimeUnit.NANOSECONDS); + executor.schedule(this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, NANOSECONDS); } } catch (Throwable t) { - logger.log(Level.FINE, "Failed to update sampler", t); + logger.log(FINE, "Failed to update sampler", t); } scheduleSamplerUpdate(); } private void scheduleSamplerUpdate() { long delay = pollingIntervalNanos + jitterNanos.next(); - pollFuture = executor.schedule(this::getAndUpdateSampler, delay, TimeUnit.NANOSECONDS); + pollFuture = executor.schedule(this::getAndUpdateSampler, delay, NANOSECONDS); } /** @@ -168,7 +171,7 @@ Duration getNextSamplerUpdateScheduledDuration() { if (pollFuture == null) { return null; } - return Duration.ofNanos(pollFuture.getDelay(TimeUnit.NANOSECONDS)); + return Duration.ofNanos(pollFuture.getDelay(NANOSECONDS)); } private void fetchTargets() { @@ -181,28 +184,25 @@ private void fetchTargets() { Date now = Date.from(Instant.ofEpochSecond(0, clock.now())); List statistics = xrayRulesSampler.snapshot(now); Set requestedTargetRuleNames = - statistics.stream() - .map(SamplingStatisticsDocument::getRuleName) - .collect(Collectors.toSet()); + statistics.stream().map(SamplingStatisticsDocument::getRuleName).collect(toSet()); GetSamplingTargetsResponse response = client.getSamplingTargets(GetSamplingTargetsRequest.create(statistics)); Map targets = response.getDocuments().stream() - .collect(Collectors.toMap(SamplingTargetDocument::getRuleName, Function.identity())); + .collect(toMap(SamplingTargetDocument::getRuleName, identity())); updateInternalSamplers(xrayRulesSampler.withTargets(targets, requestedTargetRuleNames, now)); } catch (Throwable t) { // Might be a transient API failure, try again after a default interval. fetchTargetsFuture = - executor.schedule( - this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, TimeUnit.NANOSECONDS); + executor.schedule(this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, NANOSECONDS); return; } long nextTargetFetchIntervalNanos = xrayRulesSampler.nextTargetFetchTimeNanos() - clock.nanoTime(); fetchTargetsFuture = - executor.schedule(this::fetchTargets, nextTargetFetchIntervalNanos, TimeUnit.NANOSECONDS); + executor.schedule(this::fetchTargets, nextTargetFetchIntervalNanos, NANOSECONDS); } @Override diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java index 1ce0d41c1..25485e4b0 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java @@ -6,6 +6,8 @@ package io.opentelemetry.contrib.awsxray; import static java.util.Objects.requireNonNull; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.sdk.common.Clock; @@ -26,7 +28,7 @@ public final class AwsXrayRemoteSamplerBuilder { private Clock clock = Clock.getDefault(); private String endpoint = DEFAULT_ENDPOINT; @Nullable private Sampler initialSampler; - private long pollingIntervalNanos = TimeUnit.SECONDS.toNanos(DEFAULT_POLLING_INTERVAL_SECS); + private long pollingIntervalNanos = SECONDS.toNanos(DEFAULT_POLLING_INTERVAL_SECS); AwsXrayRemoteSamplerBuilder(Resource resource) { this.resource = resource; @@ -51,7 +53,7 @@ public AwsXrayRemoteSamplerBuilder setEndpoint(String endpoint) { @CanIgnoreReturnValue public AwsXrayRemoteSamplerBuilder setPollingInterval(Duration delay) { requireNonNull(delay, "delay"); - return setPollingInterval(delay.toNanos(), TimeUnit.NANOSECONDS); + return setPollingInterval(delay.toNanos(), NANOSECONDS); } /** diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java index 1d97c4aed..ae4cac018 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java @@ -5,7 +5,10 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; +import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.stream.Collectors.toMap; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -28,22 +31,18 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; import java.util.regex.Pattern; -import java.util.stream.Collectors; import javax.annotation.Nullable; final class SamplingRuleApplier { // copied from AwsIncubatingAttributes private static final AttributeKey AWS_ECS_CONTAINER_ARN = - AttributeKey.stringKey("aws.ecs.container.arn"); + stringKey("aws.ecs.container.arn"); // copied from CloudIncubatingAttributes - private static final AttributeKey CLOUD_PLATFORM = - AttributeKey.stringKey("cloud.platform"); - private static final AttributeKey CLOUD_RESOURCE_ID = - AttributeKey.stringKey("cloud.resource_id"); + private static final AttributeKey CLOUD_PLATFORM = stringKey("cloud.platform"); + private static final AttributeKey CLOUD_RESOURCE_ID = stringKey("cloud.resource_id"); // copied from CloudIncubatingAttributes.CloudPlatformIncubatingValues public static final String AWS_EC2 = "aws_ec2"; public static final String AWS_ECS = "aws_ecs"; @@ -51,12 +50,12 @@ final class SamplingRuleApplier { public static final String AWS_LAMBDA = "aws_lambda"; public static final String AWS_ELASTIC_BEANSTALK = "aws_elastic_beanstalk"; // copied from HttpIncubatingAttributes - private static final AttributeKey HTTP_HOST = AttributeKey.stringKey("http.host"); - private static final AttributeKey HTTP_METHOD = AttributeKey.stringKey("http.method"); - private static final AttributeKey HTTP_TARGET = AttributeKey.stringKey("http.target"); - private static final AttributeKey HTTP_URL = AttributeKey.stringKey("http.url"); + private static final AttributeKey HTTP_HOST = stringKey("http.host"); + private static final AttributeKey HTTP_METHOD = stringKey("http.method"); + private static final AttributeKey HTTP_TARGET = stringKey("http.target"); + private static final AttributeKey HTTP_URL = stringKey("http.url"); // copied from NetIncubatingAttributes - private static final AttributeKey NET_HOST_NAME = AttributeKey.stringKey("net.host.name"); + private static final AttributeKey NET_HOST_NAME = stringKey("net.host.name"); private static final Map XRAY_CLOUD_PLATFORM; @@ -131,7 +130,7 @@ final class SamplingRuleApplier { } else { attributeMatchers = rule.getAttributes().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> toMatcher(e.getValue()))); + .collect(toMap(Map.Entry::getKey, e -> toMatcher(e.getValue()))); } urlPathMatcher = toMatcher(rule.getUrlPath()); @@ -317,7 +316,7 @@ SamplingRuleApplier withTarget(SamplingTargetDocument target, Date now) { } long intervalNanos = target.getIntervalSecs() != null - ? TimeUnit.SECONDS.toNanos(target.getIntervalSecs()) + ? SECONDS.toNanos(target.getIntervalSecs()) : AwsXrayRemoteSampler.DEFAULT_TARGET_INTERVAL_NANOS; long newNextSnapshotTimeNanos = clock.nanoTime() + intervalNanos; diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java index 75977dc0f..e187da972 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.awsxray; +import static java.util.logging.Level.FINE; +import static java.util.stream.Collectors.toList; + import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; @@ -21,9 +24,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; final class XrayRulesSampler implements Sampler { @@ -84,7 +85,7 @@ public SamplingResult shouldSample( // In practice, X-Ray always returns a Default rule that matches all requests so it is a bug in // our code or X-Ray to reach here, fallback just in case. logger.log( - Level.FINE, + FINE, "No sampling rule matched the request. " + "This is a bug in either the OpenTelemetry SDK or X-Ray."); return fallbackSampler.shouldSample( @@ -100,7 +101,7 @@ List snapshot(Date now) { return Arrays.stream(ruleAppliers) .map(rule -> rule.snapshot(now)) .filter(Objects::nonNull) - .collect(Collectors.toList()); + .collect(toList()); } long nextTargetFetchTimeNanos() { diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java index 5dbbbbbbf..84dbd0144 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java @@ -25,6 +25,8 @@ package io.opentelemetry.contrib.awsxray; +import static java.util.logging.Level.FINE; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -37,7 +39,6 @@ import java.io.UncheckedIOException; import java.math.BigDecimal; import java.util.Date; -import java.util.logging.Level; import java.util.logging.Logger; import okhttp3.Call; import okhttp3.MediaType; @@ -51,7 +52,7 @@ final class XraySamplerClient { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .setSerializationInclusion(JsonInclude.Include.NON_EMPTY) + .setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY) // AWS APIs return timestamps as floats. .registerModule( new SimpleModule().addDeserializer(Date.class, new FloatDateDeserializer())) @@ -114,7 +115,7 @@ private T executeJsonRequest(String endpoint, Object request, Class respo private static String readResponse(Response response, String endpoint) throws IOException { if (!response.isSuccessful()) { logger.log( - Level.FINE, + FINE, "Error response from " + endpoint + " code (" diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java index b4f40e408..0bf394e0e 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java @@ -41,7 +41,7 @@ public void setup() { } @Test - public void testAttributesPropagation() { + void testAttributesPropagation() { Span spanWithAppOnly = tracer.spanBuilder("parent").startSpan(); spanWithAppOnly.setAttribute(testKey1, "testValue1"); validateSpanAttributesInheritance(spanWithAppOnly, null, "testValue1", null); @@ -57,7 +57,7 @@ public void testAttributesPropagation() { } @Test - public void testOverrideAttributes() { + void testOverrideAttributes() { Span parentSpan = tracer.spanBuilder("parent").startSpan(); parentSpan.setAttribute(testKey1, "testValue1"); parentSpan.setAttribute(testKey2, "testValue2"); @@ -75,13 +75,13 @@ public void testOverrideAttributes() { } @Test - public void testAttributesDoNotExist() { + void testAttributesDoNotExist() { Span span = tracer.spanBuilder("parent").startSpan(); validateSpanAttributesInheritance(span, null, null, null); } @Test - public void testSpanNamePropagationBySpanKind() { + void testSpanNamePropagationBySpanKind() { for (SpanKind value : SpanKind.values()) { Span span = tracer.spanBuilder("parent").setSpanKind(value).startSpan(); if (value == SpanKind.SERVER || value == SpanKind.CONSUMER) { @@ -93,7 +93,7 @@ public void testSpanNamePropagationBySpanKind() { } @Test - public void testSpanNamePropagationWithRemoteParentSpan() { + void testSpanNamePropagationWithRemoteParentSpan() { Span remoteParent = Span.wrap( SpanContext.createFromRemoteParent( diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java index 135a1eeff..4d38e89ff 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java @@ -79,7 +79,7 @@ public void setUpMocks() { } @Test - public void testConsumerSpanWithoutAttributes() { + void testConsumerSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.CONSUMER.name(), @@ -89,7 +89,7 @@ public void testConsumerSpanWithoutAttributes() { } @Test - public void testServerSpanWithoutAttributes() { + void testServerSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.SERVER.name(), @@ -99,7 +99,7 @@ public void testServerSpanWithoutAttributes() { } @Test - public void testProducerSpanWithoutAttributes() { + void testProducerSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.PRODUCER.name(), @@ -111,7 +111,7 @@ public void testProducerSpanWithoutAttributes() { } @Test - public void testClientSpanWithoutAttributes() { + void testClientSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.CLIENT.name(), @@ -123,13 +123,13 @@ public void testClientSpanWithoutAttributes() { } @Test - public void testInternalSpan() { + void testInternalSpan() { // Spans with internal span kind should not produce any attributes. validateAttributesProducedForSpanOfKind(Attributes.empty(), SpanKind.INTERNAL); } @Test - public void testConsumerSpanWithAttributes() { + void testConsumerSpanWithAttributes() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn(SPAN_NAME_VALUE); @@ -142,7 +142,7 @@ public void testConsumerSpanWithAttributes() { } @Test - public void testServerSpanWithAttributes() { + void testServerSpanWithAttributes() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn(SPAN_NAME_VALUE); @@ -155,7 +155,7 @@ public void testServerSpanWithAttributes() { } @Test - public void testServerSpanWithNullSpanName() { + void testServerSpanWithNullSpanName() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn(null); @@ -168,7 +168,7 @@ public void testServerSpanWithNullSpanName() { } @Test - public void testServerSpanWithSpanNameAsHttpMethod() { + void testServerSpanWithSpanNameAsHttpMethod() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("GET"); mockAttribute(HTTP_METHOD, "GET"); @@ -183,7 +183,7 @@ public void testServerSpanWithSpanNameAsHttpMethod() { } @Test - public void testServerSpanWithSpanNameWithHttpTarget() { + void testServerSpanWithSpanNameWithHttpTarget() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("POST"); mockAttribute(HTTP_METHOD, "POST"); @@ -203,7 +203,7 @@ public void testServerSpanWithSpanNameWithHttpTarget() { } @Test - public void testProducerSpanWithAttributes() { + void testProducerSpanWithAttributes() { updateResourceWithServiceName(); mockAttribute(AWS_LOCAL_OPERATION, AWS_LOCAL_OPERATION_VALUE); mockAttribute(AWS_REMOTE_SERVICE, AWS_REMOTE_SERVICE_VALUE); @@ -220,7 +220,7 @@ public void testProducerSpanWithAttributes() { } @Test - public void testClientSpanWithAttributes() { + void testClientSpanWithAttributes() { updateResourceWithServiceName(); mockAttribute(AWS_LOCAL_OPERATION, AWS_LOCAL_OPERATION_VALUE); mockAttribute(AWS_REMOTE_SERVICE, AWS_REMOTE_SERVICE_VALUE); @@ -237,7 +237,7 @@ public void testClientSpanWithAttributes() { } @Test - public void testRemoteAttributesCombinations() { + void testRemoteAttributesCombinations() { // Set all expected fields to a test string, we will overwrite them in descending order to test // the priority-order logic in AwsMetricAttributeGenerator remote attribute methods. mockAttribute(AWS_REMOTE_SERVICE, "TestString"); @@ -333,7 +333,7 @@ public void testRemoteAttributesCombinations() { } @Test - public void testPeerServiceDoesOverrideOtherRemoteServices() { + void testPeerServiceDoesOverrideOtherRemoteServices() { validatePeerServiceDoesOverride(RPC_SERVICE); validatePeerServiceDoesOverride(DB_SYSTEM); validatePeerServiceDoesOverride(FAAS_INVOKED_PROVIDER); @@ -346,7 +346,7 @@ public void testPeerServiceDoesOverrideOtherRemoteServices() { } @Test - public void testPeerServiceDoesNotOverrideAwsRemoteService() { + void testPeerServiceDoesNotOverrideAwsRemoteService() { mockAttribute(AWS_REMOTE_SERVICE, "TestString"); mockAttribute(PEER_SERVICE, "PeerService"); @@ -357,7 +357,7 @@ public void testPeerServiceDoesNotOverrideAwsRemoteService() { } @Test - public void testClientSpanWithRemoteTargetAttributes() { + void testClientSpanWithRemoteTargetAttributes() { // Validate behaviour of aws bucket name attribute, then remove it. mockAttribute(AWS_BUCKET_NAME, "aws_s3_bucket_name"); validateRemoteTargetAttributes(AWS_REMOTE_TARGET, "aws_s3_bucket_name"); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java index aedf5fa06..8502734d7 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java @@ -62,7 +62,7 @@ public void setUpMocks() { } @Test - public void testPassthroughDelegations() { + void testPassthroughDelegations() { awsMetricAttributesSpanExporter.flush(); awsMetricAttributesSpanExporter.shutdown(); awsMetricAttributesSpanExporter.close(); @@ -72,7 +72,7 @@ public void testPassthroughDelegations() { } @Test - public void testExportDelegationWithoutAttributeOrModification() { + void testExportDelegationWithoutAttributeOrModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -88,7 +88,7 @@ public void testExportDelegationWithoutAttributeOrModification() { } @Test - public void testExportDelegationWithAttributeButWithoutModification() { + void testExportDelegationWithAttributeButWithoutModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -104,7 +104,7 @@ public void testExportDelegationWithAttributeButWithoutModification() { } @Test - public void testExportDelegationWithoutAttributeButWithModification() { + void testExportDelegationWithoutAttributeButWithModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -124,7 +124,7 @@ public void testExportDelegationWithoutAttributeButWithModification() { } @Test - public void testExportDelegationWithAttributeAndModification() { + void testExportDelegationWithAttributeAndModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -146,7 +146,7 @@ public void testExportDelegationWithAttributeAndModification() { } @Test - public void testExportDelegationWithMultipleSpans() { + void testExportDelegationWithMultipleSpans() { Attributes spanAttributes1 = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); SpanData spanDataMock1 = buildSpanDataMock(spanAttributes1); Attributes metricAttributes1 = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -185,7 +185,7 @@ public void testExportDelegationWithMultipleSpans() { } @Test - public void testOverridenAttributes() { + void testOverridenAttributes() { Attributes spanAttributes = Attributes.of( AttributeKey.stringKey("key1"), @@ -217,7 +217,7 @@ public void testOverridenAttributes() { } @Test - public void testExportDelegatingSpanDataBehaviour() { + void testExportDelegatingSpanDataBehaviour() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java index 0836f5a8e..5d10a6a3d 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java @@ -101,13 +101,13 @@ public void setUpMocks() { } @Test - public void testIsRequired() { + void testIsRequired() { assertThat(awsSpanMetricsProcessor.isStartRequired()).isFalse(); assertThat(awsSpanMetricsProcessor.isEndRequired()).isTrue(); } @Test - public void testStartDoesNothingToSpan() { + void testStartDoesNothingToSpan() { Context parentContextMock = mock(Context.class); ReadWriteSpan spanMock = mock(ReadWriteSpan.class); awsSpanMetricsProcessor.onStart(parentContextMock, spanMock); @@ -115,7 +115,7 @@ public void testStartDoesNothingToSpan() { } @Test - public void testTearDown() { + void testTearDown() { assertThat(awsSpanMetricsProcessor.shutdown()).isEqualTo(CompletableResultCode.ofSuccess()); assertThat(awsSpanMetricsProcessor.forceFlush()).isEqualTo(CompletableResultCode.ofSuccess()); @@ -128,7 +128,7 @@ public void testTearDown() { * AwsSpanMetricsProcessor's onEnd method pertaining to metrics generation. */ @Test - public void testOnEndMetricsGenerationWithoutSpanAttributes() { + void testOnEndMetricsGenerationWithoutSpanAttributes() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -141,7 +141,7 @@ public void testOnEndMetricsGenerationWithoutSpanAttributes() { } @Test - public void testOnEndMetricsGenerationWithoutMetricAttributes() { + void testOnEndMetricsGenerationWithoutMetricAttributes() { Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -154,7 +154,7 @@ public void testOnEndMetricsGenerationWithoutMetricAttributes() { } @Test - public void testOnEndMetricsGenerationWithoutEndRequired() { + void testOnEndMetricsGenerationWithoutEndRequired() { Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -167,7 +167,7 @@ public void testOnEndMetricsGenerationWithoutEndRequired() { } @Test - public void testOnEndMetricsGenerationWithLatency() { + void testOnEndMetricsGenerationWithLatency() { Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 200L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -182,7 +182,7 @@ public void testOnEndMetricsGenerationWithLatency() { } @Test - public void testOnEndMetricsGenerationWithAwsStatusCodes() { + void testOnEndMetricsGenerationWithAwsStatusCodes() { validateMetricsGeneratedForAwsStatusCode(399L, ExpectedStatusMetric.NEITHER); validateMetricsGeneratedForAwsStatusCode(400L, ExpectedStatusMetric.ERROR); validateMetricsGeneratedForAwsStatusCode(499L, ExpectedStatusMetric.ERROR); @@ -192,7 +192,7 @@ public void testOnEndMetricsGenerationWithAwsStatusCodes() { } @Test - public void testOnEndMetricsGenerationWithStatusCodes() { + void testOnEndMetricsGenerationWithStatusCodes() { // Invalid HTTP status codes validateMetricsGeneratedForHttpStatusCode(null, ExpectedStatusMetric.NEITHER); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java index 1140abc5f..f81f3d370 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java @@ -21,11 +21,11 @@ * Unit tests for {@link ResourceHolder}. Note that there isn't a great way to test the "default" * fallback logic, as when the test suite is run, the customize logic appears to be invoked. */ -public class ResourceHolderTest { +class ResourceHolderTest { @Test @SuppressWarnings("unchecked") - public void testCustomized() { + void testCustomized() { Resource customizedResource = Resource.create(Attributes.empty()); AutoConfigurationCustomizer mockCustomizer = mock(AutoConfigurationCustomizer.class); ResourceHolder resourceHolder = new ResourceHolder(); diff --git a/azure-resources/build.gradle.kts b/azure-resources/build.gradle.kts index c17d14787..43a154970 100644 --- a/azure-resources/build.gradle.kts +++ b/azure-resources/build.gradle.kts @@ -5,8 +5,8 @@ plugins { id("maven-publish") } -description = "OpenTelemetry GCP Resources Support" -otelJava.moduleName.set("io.opentelemetry.contrib.gcp.resource") +description = "OpenTelemetry Azure Resources Support" +otelJava.moduleName.set("io.opentelemetry.contrib.azure.resource") // enable publishing to maven local java { diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java index 9823c6f9e..987492dd8 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java @@ -14,7 +14,7 @@ import java.util.Optional; import java.util.function.Supplier; -public class AzureAksResourceProvider extends CloudResourceProvider { +public final class AzureAksResourceProvider extends CloudResourceProvider { private static final Map COMPUTE_MAPPING = new HashMap<>(); diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java index 74ad96334..3a658428a 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java @@ -12,6 +12,7 @@ import static io.opentelemetry.contrib.azure.resource.IncubatingAttributes.HOST_ID; import static io.opentelemetry.contrib.azure.resource.IncubatingAttributes.SERVICE_INSTANCE_ID; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; +import static java.util.Objects.requireNonNull; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -20,10 +21,9 @@ import io.opentelemetry.sdk.resources.Resource; import java.util.HashMap; import java.util.Map; -import java.util.Objects; import javax.annotation.Nullable; -public class AzureAppServiceResourceProvider extends CloudResourceProvider { +public final class AzureAppServiceResourceProvider extends CloudResourceProvider { static final AttributeKey AZURE_APP_SERVICE_STAMP_RESOURCE_ATTRIBUTE = AttributeKey.stringKey("azure.app.service.stamp"); @@ -68,7 +68,7 @@ public Attributes getAttributes() { if (detect != AzureEnvVarPlatform.APP_SERVICE) { return Attributes.empty(); } - String name = Objects.requireNonNull(env.get(WEBSITE_SITE_NAME)); + String name = requireNonNull(env.get(WEBSITE_SITE_NAME)); AttributesBuilder builder = AzureVmResourceProvider.azureAttributeBuilder(AZURE_APP_SERVICE); builder.put(SERVICE_NAME, name); diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java index 63d0f4428..014ec5b41 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java @@ -16,7 +16,7 @@ import java.util.HashMap; import java.util.Map; -public class AzureContainersResourceProvider extends CloudResourceProvider { +public final class AzureContainersResourceProvider extends CloudResourceProvider { static final String CONTAINER_APP_NAME = "CONTAINER_APP_NAME"; diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java index e35fe95c4..d98a41be4 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java @@ -19,7 +19,7 @@ import java.util.HashMap; import java.util.Map; -public class AzureFunctionsResourceProvider extends CloudResourceProvider { +public final class AzureFunctionsResourceProvider extends CloudResourceProvider { static final String FUNCTIONS_VERSION = "FUNCTIONS_EXTENSION_VERSION"; private static final String FUNCTIONS_MEM_LIMIT = "WEBSITE_MEMORY_LIMIT_MB"; diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java index d5bf44520..a93413a24 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java @@ -5,12 +5,13 @@ package io.opentelemetry.contrib.azure.resource; +import static java.util.Objects.requireNonNull; + import com.fasterxml.jackson.core.JsonFactory; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; -import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; import java.util.logging.Level; @@ -19,9 +20,11 @@ import okhttp3.Request; import okhttp3.Response; -public class AzureMetadataService { +public final class AzureMetadataService { static final JsonFactory JSON_FACTORY = new JsonFactory(); private static final URL METADATA_URL; + private static final Duration TIMEOUT = Duration.ofSeconds(5); + private static final Logger logger = Logger.getLogger(AzureMetadataService.class.getName()); static { try { @@ -31,12 +34,6 @@ public class AzureMetadataService { } } - private AzureMetadataService() {} - - private static final Duration TIMEOUT = Duration.ofSeconds(5); - - private static final Logger logger = Logger.getLogger(AzureMetadataService.class.getName()); - static Supplier> defaultClient() { return () -> fetchMetadata(METADATA_URL); } @@ -66,10 +63,12 @@ static Optional fetchMetadata(URL url) { return Optional.empty(); } - return Optional.of(Objects.requireNonNull(response.body()).string()); + return Optional.of(requireNonNull(response.body()).string()); } catch (IOException e) { logger.log(Level.FINE, "Failed to fetch Azure VM metadata", e); return Optional.empty(); } } + + private AzureMetadataService() {} } diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java index 556e1d60c..27da91c4c 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java @@ -11,7 +11,7 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.resources.ResourceBuilder; -public class AzureResourceDetector implements ComponentProvider { +public final class AzureResourceDetector implements ComponentProvider { @Override public Class getType() { diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java index 38c983b4a..2a87a0488 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java @@ -34,21 +34,7 @@ import java.util.logging.Logger; import org.jetbrains.annotations.NotNull; -public class AzureVmResourceProvider extends CloudResourceProvider { - - static class Entry { - final AttributeKey key; - final Function transform; - - Entry(AttributeKey key) { - this(key, Function.identity()); - } - - Entry(AttributeKey key, Function transform) { - this.key = key; - this.transform = transform; - } - } +public final class AzureVmResourceProvider extends CloudResourceProvider { private static final Map COMPUTE_MAPPING = new HashMap<>(); @@ -161,4 +147,18 @@ private static void consumeJson(JsonParser parser, BiConsumer co consumer.accept(parser.currentName(), parser.nextTextValue()); } } + + static class Entry { + final AttributeKey key; + final Function transform; + + Entry(AttributeKey key) { + this(key, Function.identity()); + } + + Entry(AttributeKey key, Function transform) { + this.key = key; + this.transform = transform; + } + } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java index 20d856cba..75360f0e9 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PROVIDER; @@ -16,7 +17,6 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.util.HashMap; import java.util.Map; import org.jetbrains.annotations.NotNull; @@ -98,7 +98,7 @@ void isFunction() { @NotNull private static AttributesAssert createResource(Map map) { - return OpenTelemetryAssertions.assertThat( + return assertThat( new AzureAppServiceResourceProvider(map).createResource(null).getAttributes()); } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java index 5ac1a4be7..082ceaf6a 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_VERSION; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; @@ -13,7 +14,6 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.util.HashMap; import java.util.Map; import org.jetbrains.annotations.NotNull; @@ -50,7 +50,7 @@ void isNotContainer() { @NotNull private static AttributesAssert createResource(Map map) { - return OpenTelemetryAssertions.assertThat( + return assertThat( new AzureContainersResourceProvider(map).createResource(null).getAttributes()); } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java index 520e44543..e2c39cc7a 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PROVIDER; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INSTANCE; @@ -14,7 +15,6 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.util.HashMap; import java.util.Map; import org.jetbrains.annotations.NotNull; @@ -55,7 +55,6 @@ void isNotFunction() { @NotNull private static AttributesAssert createResource(Map map) { - return OpenTelemetryAssertions.assertThat( - new AzureFunctionsResourceProvider(map).createResource(null).getAttributes()); + return assertThat(new AzureFunctionsResourceProvider(map).createResource(null).getAttributes()); } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java index d827e8fd4..3d65c1e0a 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PROVIDER; @@ -16,7 +17,6 @@ import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; @@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -public abstract class MetadataBasedResourceProviderTest { +abstract class MetadataBasedResourceProviderTest { @RegisterExtension public static final MockWebServerExtension server = new MockWebServerExtension(); @@ -47,7 +47,7 @@ private AttributesAssert mockServerResponse() { @NotNull private AttributesAssert createResource(Supplier> client) { Resource resource = getResourceProvider(client).createResource(null); - return OpenTelemetryAssertions.assertThat(resource.getAttributes()); + return assertThat(resource.getAttributes()); } @NotNull @@ -79,30 +79,30 @@ protected static String okResponse() { } @Test - public void successFromFile() { + void successFromFile() { assertDefaultAttributes(createResource(() -> Optional.of(okResponse()))); } @Test - public void successFromMockServer() { + void successFromMockServer() { server.enqueue(HttpResponse.of(MediaType.JSON, okResponse())); assertDefaultAttributes(mockServerResponse()); } @Test - public void responseNotFound() { + void responseNotFound() { server.enqueue(HttpResponse.of(HttpStatus.NOT_FOUND)); mockServerResponse().isEmpty(); } @Test - public void responseEmpty() { + void responseEmpty() { server.enqueue(HttpResponse.of("")); assertOnlyProvider(mockServerResponse()); } @Test - public void responseEmptyJson() { + void responseEmptyJson() { server.enqueue(HttpResponse.of("{}")); assertOnlyProvider(mockServerResponse()); } diff --git a/baggage-processor/README.md b/baggage-processor/README.md index 44719770b..10e98910d 100644 --- a/baggage-processor/README.md +++ b/baggage-processor/README.md @@ -25,6 +25,36 @@ processors through configuration. | `otel.java.experimental.span-attributes.copy-from-baggage.include` | Add baggage entries as span attributes, e.g. `key1,key2` or `*` to add all baggage items as keys. | | `otel.java.experimental.log-attributes.copy-from-baggage.include` | Add baggage entries as log attributes, e.g. `key1,key2` or `*` to add all baggage items as keys. | +### Usage with declarative configuration + +You can configure the baggage span and log record processors using declarative YAML configuration with the OpenTelemetry SDK. + +For the tracer provider (span processor): + +```yaml +file_format: 1.0-rc.1 +tracer_provider: + processors: + - baggage: + included: [foo] + excluded: [bar] +``` + +For the logger provider (log record processor): + +```yaml +file_format: 1.0-rc.1 +logger_provider: + processors: + - baggage: + included: [foo] + excluded: [bar] +``` + +This will configure the respective processor to include baggage keys listed in `included` and +exclude those in `excluded` as explained in +[Properties which pattern matching](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/CONTRIBUTING.md#properties-which-pattern-matching). + ### Usage through programmatic activation Add the span and log processor when configuring the tracer and logger providers. diff --git a/baggage-processor/build.gradle.kts b/baggage-processor/build.gradle.kts index 017158399..0ff9dd52a 100644 --- a/baggage-processor/build.gradle.kts +++ b/baggage-processor/build.gradle.kts @@ -8,11 +8,19 @@ description = "OpenTelemetry Baggage Span Processor" otelJava.moduleName.set("io.opentelemetry.contrib.baggage.processor") dependencies { + annotationProcessor("com.google.auto.service:auto-service") + compileOnly("com.google.auto.service:auto-service-annotations") api("io.opentelemetry:opentelemetry-api") api("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") + compileOnly("io.opentelemetry:opentelemetry-sdk-common") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + testAnnotationProcessor("com.google.auto.service:auto-service") + testCompileOnly("com.google.auto.service:auto-service-annotations") + testImplementation("io.opentelemetry:opentelemetry-sdk-common") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("org.mockito:mockito-inline") testImplementation("com.google.guava:guava") diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java new file mode 100644 index 000000000..be40ab97c --- /dev/null +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.internal.IncludeExcludePredicate; +import io.opentelemetry.sdk.logs.LogRecordProcessor; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class BaggageLogRecordComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "baggage"; + } + + @Override + public LogRecordProcessor create(DeclarativeConfigProperties config) { + return new BaggageLogRecordProcessor( + IncludeExcludePredicate.createPatternMatching( + config.getScalarList("included", String.class), + config.getScalarList("excluded", String.class))); + } + + @Override + public Class getType() { + return LogRecordProcessor.class; + } +} diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java index 4e8c91505..474f4caef 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java @@ -16,15 +16,7 @@ * This log record processor copies attributes stored in {@link Baggage} into each newly created log * record. */ -public class BaggageLogRecordProcessor implements LogRecordProcessor { - - /** - * Creates a new {@link BaggageLogRecordProcessor} that copies all baggage entries into the newly - * created log record. - */ - public static BaggageLogRecordProcessor allowAllBaggageKeys() { - return new BaggageLogRecordProcessor(baggageKey -> true); - } +public final class BaggageLogRecordProcessor implements LogRecordProcessor { private final Predicate baggageKeyPredicate; @@ -36,6 +28,14 @@ public BaggageLogRecordProcessor(Predicate baggageKeyPredicate) { this.baggageKeyPredicate = baggageKeyPredicate; } + /** + * Creates a new {@link BaggageLogRecordProcessor} that copies all baggage entries into the newly + * created log record. + */ + public static BaggageLogRecordProcessor allowAllBaggageKeys() { + return new BaggageLogRecordProcessor(baggageKey -> true); + } + @Override public void onEmit(Context context, ReadWriteLogRecord logRecord) { Baggage.fromContext(context) diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index da35512a3..2e07722e6 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.baggage.processor; +import com.google.auto.service.AutoService; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -12,7 +13,8 @@ import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import java.util.List; -public class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider { +@AutoService(AutoConfigurationCustomizerProvider.class) +public final class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider { @Override public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { autoConfigurationCustomizer @@ -37,7 +39,8 @@ private static void addSpanProcessor( return; } - sdkTracerProviderBuilder.addSpanProcessor(createBaggageSpanProcessor(keys)); + // need to add before the batch span processor + sdkTracerProviderBuilder.addSpanProcessorFirst(createBaggageSpanProcessor(keys)); } static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { @@ -56,7 +59,8 @@ private static void addLogRecordProcessor( return; } - sdkLoggerProviderBuilder.addLogRecordProcessor(createBaggageLogRecordProcessor(keys)); + // need to add before the batch log processor + sdkLoggerProviderBuilder.addLogRecordProcessorFirst(createBaggageLogRecordProcessor(keys)); } static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List keys) { diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java new file mode 100644 index 000000000..19acb6ba7 --- /dev/null +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.internal.IncludeExcludePredicate; +import io.opentelemetry.sdk.trace.SpanProcessor; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class BaggageSpanComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "baggage"; + } + + @Override + public SpanProcessor create(DeclarativeConfigProperties config) { + return new BaggageSpanProcessor( + IncludeExcludePredicate.createPatternMatching( + config.getScalarList("included", String.class), + config.getScalarList("excluded", String.class))); + } + + @Override + public Class getType() { + return SpanProcessor.class; + } +} diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java index 5f0f53d03..1ba62b19d 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java @@ -16,7 +16,7 @@ * This span processor copies attributes stored in {@link Baggage} into each newly created {@link * io.opentelemetry.api.trace.Span}. */ -public class BaggageSpanProcessor implements SpanProcessor { +public final class BaggageSpanProcessor implements SpanProcessor { private final Predicate baggageKeyPredicate; /** diff --git a/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider b/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider deleted file mode 100644 index 8eb4afb06..000000000 --- a/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.contrib.baggage.processor.BaggageProcessorCustomizer diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProviderTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProviderTest.java new file mode 100644 index 000000000..1c8bd28bb --- /dev/null +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProviderTest.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; + +class BaggageLogRecordComponentProviderTest { + + @Test + void declarativeConfig() { + String yaml = + "file_format: 1.0-rc.1\n" + + "logger_provider:\n" + + " processors:\n" + + " - baggage:\n" + + " included: [foo]\n" + + " excluded: [bar]\n"; + + OpenTelemetrySdk sdk = + DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + + assertThat(sdk).asString().contains("BaggageLogRecordProcessor"); + } +} diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java index bfa8835ae..645ff5334 100644 --- a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java @@ -48,11 +48,15 @@ class BaggageProcessorCustomizerTest { private static final String MEMORY_EXPORTER = "memory"; @Test - void test_customizer() { + void test_empty_customizer() { assertCustomizer( Collections.emptyMap(), span -> assertThat(span).hasTotalAttributeCount(0), logRecord -> assertThat(logRecord).hasTotalAttributeCount(0)); + } + + @Test + void test_customizer() { Map properties = new HashMap<>(); properties.put("otel.java.experimental.span-attributes.copy-from-baggage.include", "key"); properties.put("otel.java.experimental.log-attributes.copy-from-baggage.include", "key"); @@ -117,7 +121,7 @@ private static OpenTelemetrySdk getOpenTelemetrySdk( new ComponentLoader() { @Override public List load(Class spiClass) { - if (spiClass == ConfigurableSpanExporterProvider.class) { + if (spiClass.equals(ConfigurableSpanExporterProvider.class)) { return Collections.singletonList( spiClass.cast( new ConfigurableSpanExporterProvider() { @@ -132,7 +136,7 @@ public String getName() { return MEMORY_EXPORTER; } })); - } else if (spiClass == ConfigurableLogRecordExporterProvider.class) { + } else if (spiClass.equals(ConfigurableLogRecordExporterProvider.class)) { return Collections.singletonList( spiClass.cast( new ConfigurableLogRecordExporterProvider() { @@ -155,7 +159,7 @@ public String getName() { } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { + void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("*"))) { try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) { @@ -166,7 +170,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSp } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( + void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( @Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("key"))) { @@ -184,7 +188,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_m } @Test - public void test_baggageLogRecordProcessor_adds_attributes_to_logRecord( + void test_baggageLogRecordProcessor_adds_attributes_to_logRecord( @Mock ReadWriteLogRecord logRecord) { try (BaggageLogRecordProcessor processor = BaggageProcessorCustomizer.createBaggageLogRecordProcessor( @@ -197,7 +201,7 @@ public void test_baggageLogRecordProcessor_adds_attributes_to_logRecord( } @Test - public void test_baggageLogRecordProcessor_adds_attributes_to_spans_when_key_filter_matches( + void test_baggageLogRecordProcessor_adds_attributes_to_spans_when_key_filter_matches( @Mock ReadWriteLogRecord logRecord) { try (BaggageLogRecordProcessor processor = BaggageProcessorCustomizer.createBaggageLogRecordProcessor( diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProviderTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProviderTest.java new file mode 100644 index 000000000..77399305e --- /dev/null +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProviderTest.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; + +class BaggageSpanComponentProviderTest { + + @Test + void declarativeConfig() { + String yaml = + "file_format: 1.0-rc.1\n" + + "tracer_provider:\n" + + " processors:\n" + + " - baggage:\n" + + " included: [foo]\n" + + " excluded: [bar]\n"; + + OpenTelemetrySdk sdk = + DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + + assertThat(sdk).asString().contains("BaggageSpanProcessor"); + } +} diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java index ca1180dcc..dd7ea3826 100644 --- a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java @@ -17,10 +17,10 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class BaggageSpanProcessorTest { +class BaggageSpanProcessorTest { @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { + void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = BaggageSpanProcessor.allowAllBaggageKeys()) { try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) { processor.onStart(Context.current(), span); @@ -30,7 +30,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSp } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( + void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( @Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = new BaggageSpanProcessor(key -> key.startsWith("k"))) { try (Scope ignore = @@ -47,7 +47,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_m } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches_regex( + void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches_regex( @Mock ReadWriteSpan span) { Pattern pattern = Pattern.compile("k.*"); try (BaggageSpanProcessor processor = diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 6de6f8e1e..03f959388 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -14,10 +14,12 @@ dependencies { // When updating, update above in plugins too implementation("com.diffplug.spotless:spotless-plugin-gradle:7.2.1") implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.3.0") - implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.2.0") + implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.3.0") implementation("org.owasp:dependency-check-gradle:12.1.3") implementation("ru.vyarus.animalsniffer:ru.vyarus.animalsniffer.gradle.plugin:2.0.1") implementation("com.gradle:develocity-gradle-plugin:4.1.1") + implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.6") + implementation("com.google.auto.value:auto-value-annotations:1.11.0") } spotless { diff --git a/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts new file mode 100644 index 000000000..3905c2526 --- /dev/null +++ b/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts @@ -0,0 +1,158 @@ +import com.google.auto.value.AutoValue +import japicmp.model.* +import me.champeau.gradle.japicmp.JapicmpTask +import me.champeau.gradle.japicmp.report.Violation +import me.champeau.gradle.japicmp.report.stdrules.* + + +plugins { + base + + id("me.champeau.gradle.japicmp") +} + +/** + * The latest *released* version of the project. Evaluated lazily so the work is only done if necessary. + */ +val latestReleasedVersion: String by lazy { + // hack to find the current released version of the project + val temp: Configuration = configurations.create("tempConfig") { + resolutionStrategy.cacheChangingModulesFor(0, "seconds") + resolutionStrategy.cacheDynamicVersionsFor(0, "seconds") + } + // pick aws-xray, since it's a stable module that's always there. + dependencies.add(temp.name, "io.opentelemetry.contrib:opentelemetry-aws-xray:latest.release") + val moduleVersion = configurations["tempConfig"].resolvedConfiguration.firstLevelModuleDependencies.elementAt(0).moduleVersion + configurations.remove(temp) + logger.debug("Discovered latest release version: " + moduleVersion) + moduleVersion +} + +class AllowNewAbstractMethodOnAutovalueClasses : AbstractRecordingSeenMembers() { + override fun maybeAddViolation(member: JApiCompatibility): Violation? { + val allowableAutovalueChanges = setOf(JApiCompatibilityChangeType.METHOD_ABSTRACT_ADDED_TO_CLASS, + JApiCompatibilityChangeType.METHOD_ADDED_TO_PUBLIC_CLASS, JApiCompatibilityChangeType.ANNOTATION_ADDED) + if (member.compatibilityChanges.filter { !allowableAutovalueChanges.contains(it.type) }.isEmpty() && + member is JApiMethod && isAutoValueClass(member.getjApiClass())) + { + return Violation.accept(member, "Autovalue will automatically add implementation") + } + if (member.compatibilityChanges.isEmpty() && + member is JApiClass && isAutoValueClass(member)) { + return Violation.accept(member, "Autovalue class modification is allowed") + } + return null + } + + fun isAutoValueClass(japiClass: JApiClass): Boolean { + return japiClass.newClass.get().getAnnotation(AutoValue::class.java) != null || + japiClass.newClass.get().getAnnotation(AutoValue.Builder::class.java) != null + } +} + +class SourceIncompatibleRule : AbstractRecordingSeenMembers() { + override fun maybeAddViolation(member: JApiCompatibility): Violation? { + if (!member.isSourceCompatible()) { + return Violation.error(member, "Not source compatible: $member") + } + return null + } +} + +/** + * Locate the project's artifact of a particular version. + */ +fun findArtifact(version: String): File { + val existingGroup = group + try { + // Temporarily change the group name because we want to fetch an artifact with the same + // Maven coordinates as the project, which Gradle would not allow otherwise. + group = "virtual_group" + val depModule = "io.opentelemetry.contrib:${base.archivesName.get()}:$version@jar" + val depJar = "${base.archivesName.get()}-$version.jar" + val configuration: Configuration = configurations.detachedConfiguration( + dependencies.create(depModule), + ) + return files(configuration.files).filter { + it.name.equals(depJar) + }.singleFile + } finally { + group = existingGroup + } +} + +// generate the api diff report for any module that is stable and publishes a jar. +if (project.findProperty("otel.stable") == "true" && !project.name.startsWith("bom")) { + afterEvaluate { + tasks { + val jApiCmp by registering(JapicmpTask::class) { + dependsOn("jar") + + // the japicmp "new" version is either the user-specified one, or the locally built jar. + val apiNewVersion: String? by project + val newArtifact = apiNewVersion?.let { findArtifact(it) } + ?: file(getByName("jar").archiveFile) + newClasspath.from(files(newArtifact)) + + // only output changes, not everything + onlyModified.set(true) + + // the japicmp "old" version is either the user-specified one, or the latest release. + val apiBaseVersion: String? by project + val baselineVersion = apiBaseVersion ?: latestReleasedVersion + oldClasspath.from( + try { + files(findArtifact(baselineVersion)) + } catch (e: Exception) { + // if we can't find the baseline artifact, this is probably one that's never been published before, + // so publish the whole API. We do that by flipping this flag, and comparing the current against nothing. + onlyModified.set(false) + files() + }, + ) + + // Reproduce defaults from https://github.com/melix/japicmp-gradle-plugin/blob/09f52739ef1fccda6b4310cf3f4b19dc97377024/src/main/java/me/champeau/gradle/japicmp/report/ViolationsGenerator.java#L130 + // with some changes. + val exclusions = mutableListOf() + // Generics are not detected correctly + exclusions.add("CLASS_GENERIC_TEMPLATE_CHANGED") + // Allow new default methods on interfaces + exclusions.add("METHOD_NEW_DEFAULT") + // Allow adding default implementations for default methods + exclusions.add("METHOD_ABSTRACT_NOW_DEFAULT") + // Bug prevents recognizing default methods of superinterface. + // Fixed in https://github.com/siom79/japicmp/pull/343 but not yet available in me.champeau.gradle.japicmp + exclusions.add("METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE") + compatibilityChangeExcludes.set(exclusions) + richReport { + addSetupRule(RecordSeenMembersSetup::class.java) + addRule(JApiChangeStatus.NEW, SourceCompatibleRule::class.java) + addRule(JApiChangeStatus.MODIFIED, SourceCompatibleRule::class.java) + addRule(JApiChangeStatus.UNCHANGED, UnchangedMemberRule::class.java) + // Allow new abstract methods on autovalue + addRule(AllowNewAbstractMethodOnAutovalueClasses::class.java) + addRule(BinaryIncompatibleRule::class.java) + // Disallow source incompatible changes, which are allowed by default for some reason + addRule(SourceIncompatibleRule::class.java) + } + + // this is needed so that we only consider the current artifact, and not dependencies + ignoreMissingClasses.set(true) + packageExcludes.addAll( + "*.internal", + "*.internal.*" + ) + annotationExcludes.add("@kotlin.Metadata") + val baseVersionString = if (apiBaseVersion == null) "latest" else baselineVersion + txtOutputFile.set( + apiNewVersion?.let { file("$rootDir/docs/apidiffs/${apiNewVersion}_vs_$baselineVersion/${base.archivesName.get()}.txt") } + ?: file("$rootDir/docs/apidiffs/current_vs_$baseVersionString/${base.archivesName.get()}.txt"), + ) + } + // have the check task depend on the api comparison task, to make it more likely it will get used. + named("check") { + dependsOn(jApiCmp) + } + } + } +} diff --git a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts index e3639a9d5..48f443d67 100644 --- a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts @@ -7,6 +7,7 @@ plugins { id("otel.errorprone-conventions") id("otel.spotless-conventions") + id("otel.japicmp-conventions") id("org.owasp.dependencycheck") } @@ -106,12 +107,13 @@ plugins.withId("otel.publish-conventions") { register("generateVersionResource") { val moduleName = otelJava.moduleName val propertiesDir = moduleName.map { layout.buildDirectory.file("generated/properties/${it.replace('.', '/')}") } + val projectVersion = project.version.toString() - inputs.property("project.version", project.version.toString()) + inputs.property("project.version", projectVersion) outputs.dir(propertiesDir) doLast { - File(propertiesDir.get().get().asFile, "version.properties").writeText("contrib.version=${project.version}") + File(propertiesDir.get().get().asFile, "version.properties").writeText("contrib.version=${projectVersion}") } } } @@ -151,7 +153,7 @@ testing { implementation(enforcedPlatform("org.junit:junit-bom:5.13.4")) implementation(enforcedPlatform("org.testcontainers:testcontainers-bom:1.21.3")) implementation(enforcedPlatform("com.google.guava:guava-bom:33.4.8-jre")) - implementation(enforcedPlatform("com.linecorp.armeria:armeria-bom:1.33.1")) + implementation(enforcedPlatform("com.linecorp.armeria:armeria-bom:1.33.2")) compileOnly("com.google.auto.value:auto-value-annotations") compileOnly("com.google.errorprone:error_prone_annotations") diff --git a/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts index b1c39dcd0..f3d387872 100644 --- a/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts @@ -8,11 +8,12 @@ spotless { licenseHeaderFile(rootProject.file("buildscripts/spotless.license.java"), "(package|import|public|// Includes work from:)") target("src/**/*.java") } - plugins.withId("groovy") { - groovy { - licenseHeaderFile(rootProject.file("buildscripts/spotless.license.java"), "(package|import|class)") - } - } + // commented out for now due to incompatibility with gradle cache configuration + // plugins.withId("groovy") { + // groovy { + // licenseHeaderFile(rootProject.file("buildscripts/spotless.license.java"), "(package|import|class)") + // } + // } plugins.withId("scala") { scala { scalafmt() diff --git a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java index 7d6313928..c8e7bd2f2 100644 --- a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java +++ b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.cloudfoundry.resources; +import static io.opentelemetry.api.common.AttributeKey.stringKey; + import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -22,24 +24,22 @@ public final class CloudFoundryResource { private static final String ENV_VCAP_APPLICATION = "VCAP_APPLICATION"; // copied from CloudfoundryIncubatingAttributes - private static final AttributeKey CLOUDFOUNDRY_APP_ID = - AttributeKey.stringKey("cloudfoundry.app.id"); + private static final AttributeKey CLOUDFOUNDRY_APP_ID = stringKey("cloudfoundry.app.id"); private static final AttributeKey CLOUDFOUNDRY_APP_INSTANCE_ID = - AttributeKey.stringKey("cloudfoundry.app.instance.id"); + stringKey("cloudfoundry.app.instance.id"); private static final AttributeKey CLOUDFOUNDRY_APP_NAME = - AttributeKey.stringKey("cloudfoundry.app.name"); - private static final AttributeKey CLOUDFOUNDRY_ORG_ID = - AttributeKey.stringKey("cloudfoundry.org.id"); + stringKey("cloudfoundry.app.name"); + private static final AttributeKey CLOUDFOUNDRY_ORG_ID = stringKey("cloudfoundry.org.id"); private static final AttributeKey CLOUDFOUNDRY_ORG_NAME = - AttributeKey.stringKey("cloudfoundry.org.name"); + stringKey("cloudfoundry.org.name"); private static final AttributeKey CLOUDFOUNDRY_PROCESS_ID = - AttributeKey.stringKey("cloudfoundry.process.id"); + stringKey("cloudfoundry.process.id"); private static final AttributeKey CLOUDFOUNDRY_PROCESS_TYPE = - AttributeKey.stringKey("cloudfoundry.process.type"); + stringKey("cloudfoundry.process.type"); private static final AttributeKey CLOUDFOUNDRY_SPACE_ID = - AttributeKey.stringKey("cloudfoundry.space.id"); + stringKey("cloudfoundry.space.id"); private static final AttributeKey CLOUDFOUNDRY_SPACE_NAME = - AttributeKey.stringKey("cloudfoundry.space.name"); + stringKey("cloudfoundry.space.name"); private static final Logger LOG = Logger.getLogger(CloudFoundryResource.class.getName()); private static final JsonFactory JSON_FACTORY = new JsonFactory(); private static final Resource INSTANCE = buildResource(System::getenv); diff --git a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java index 02b9a6b09..357d83533 100644 --- a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java +++ b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.resources.Resource; -public class CloudFoundryResourceDetector implements ComponentProvider { +public final class CloudFoundryResourceDetector implements ComponentProvider { @Override public Class getType() { diff --git a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java index e3f3e3c64..992eb93dc 100644 --- a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java +++ b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; -public class CloudFoundryResourceProvider implements ResourceProvider { +public final class CloudFoundryResourceProvider implements ResourceProvider { @Override public Resource createResource(ConfigProperties configProperties) { diff --git a/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java b/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java index 1c533cd8a..96474c966 100644 --- a/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java +++ b/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java @@ -5,7 +5,9 @@ package io.opentelemetry.contrib.cloudfoundry.resources; +import static java.util.stream.Collectors.joining; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.SchemaUrls; @@ -18,8 +20,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; class CloudFoundryResourceTest { @@ -36,11 +36,11 @@ private static String loadVcapApplicationSample(String filename) { if (is != null) { return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)) .lines() - .collect(Collectors.joining()); + .collect(joining()); } - Assertions.fail("Cannot load resource " + filename); + fail("Cannot load resource " + filename); } catch (IOException e) { - Assertions.fail("Error reading " + filename); + fail("Error reading " + filename); } return ""; } diff --git a/consistent-sampling/build.gradle.kts b/consistent-sampling/build.gradle.kts index 66fca90c9..5fc4135bb 100644 --- a/consistent-sampling/build.gradle.kts +++ b/consistent-sampling/build.gradle.kts @@ -9,8 +9,8 @@ otelJava.moduleName.set("io.opentelemetry.contrib.sampler") dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - testImplementation("org.hipparchus:hipparchus-core:4.0.1") - testImplementation("org.hipparchus:hipparchus-stat:4.0.1") + testImplementation("org.hipparchus:hipparchus-core:4.0.2") + testImplementation("org.hipparchus:hipparchus-stat:4.0.2") } tasks { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java index 4b9d3e425..a05506bc8 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.sampler.consistent; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; @@ -25,7 +24,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class ConsistentProbabilityBasedSamplerTest { +class ConsistentProbabilityBasedSamplerTest { private Context parentContext; private String traceId; @@ -63,8 +62,8 @@ private void test(SplittableRandom rng, double samplingProbability) { .getUpdatedTraceState(TraceState.getDefault()) .get(OtelTraceState.TRACE_STATE_KEY); OtelTraceState traceState = OtelTraceState.parse(traceStateString); - assertTrue(traceState.hasValidR()); - assertTrue(traceState.hasValidP()); + assertThat(traceState.hasValidR()).isTrue(); + assertThat(traceState.hasValidP()).isTrue(); observedPvalues.merge(traceState.getP(), 1L, Long::sum); } } @@ -72,7 +71,7 @@ private void test(SplittableRandom rng, double samplingProbability) { } @Test - public void test() { + void test() { // fix seed to get reproducible results SplittableRandom random = new SplittableRandom(0); diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java index 5eaefd482..1415d0f6f 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java @@ -11,7 +11,6 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.argThat; @@ -566,8 +565,8 @@ private void testConsistentSampling( String traceStateString = spanData.getSpanContext().getTraceState().get(OtelTraceState.TRACE_STATE_KEY); OtelTraceState traceState = OtelTraceState.parse(traceStateString); - assertTrue(traceState.hasValidR()); - assertTrue(traceState.hasValidP()); + assertThat(traceState.hasValidR()).isTrue(); + assertThat(traceState.hasValidP()).isTrue(); observedPvalues.merge(traceState.getP(), 1L, Long::sum); totalAdjustedCount += 1L << traceState.getP(); spanNameCounts.merge(spanData.getName(), 1L, Long::sum); diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java index 082ac3068..1a61868c8 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java @@ -8,9 +8,7 @@ import static io.opentelemetry.contrib.sampler.consistent.OtelTraceState.getInvalidP; import static io.opentelemetry.contrib.sampler.consistent.OtelTraceState.getInvalidR; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.Span; @@ -32,45 +30,50 @@ class ConsistentSamplerTest { @Test void testGetSamplingRate() { - assertThrows( - IllegalArgumentException.class, () -> ConsistentSampler.getSamplingProbability(-1)); + assertThatThrownBy(() -> ConsistentSampler.getSamplingProbability(-1)) + .isInstanceOf(IllegalArgumentException.class); for (int i = 0; i < OtelTraceState.getMaxP() - 1; i += 1) { - assertEquals(Math.pow(0.5, i), ConsistentSampler.getSamplingProbability(i)); + assertThat(ConsistentSampler.getSamplingProbability(i)).isEqualTo(Math.pow(0.5, i)); } - assertEquals(0., ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP())); - assertThrows( - IllegalArgumentException.class, - () -> ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP() + 1)); + assertThat(ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP())).isEqualTo(0.); + assertThatThrownBy(() -> ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP() + 1)) + .isInstanceOf(IllegalArgumentException.class); } @Test void testGetLowerBoundP() { - assertEquals(0, ConsistentSampler.getLowerBoundP(1.0)); - assertEquals(0, ConsistentSampler.getLowerBoundP(Math.nextDown(1.0))); + assertThat(ConsistentSampler.getLowerBoundP(1.0)).isEqualTo(0); + assertThat(ConsistentSampler.getLowerBoundP(Math.nextDown(1.0))).isEqualTo(0); for (int i = 1; i < OtelTraceState.getMaxP() - 1; i += 1) { double samplingProbability = Math.pow(0.5, i); - assertEquals(i, ConsistentSampler.getLowerBoundP(samplingProbability)); - assertEquals(i - 1, ConsistentSampler.getLowerBoundP(Math.nextUp(samplingProbability))); - assertEquals(i, ConsistentSampler.getLowerBoundP(Math.nextDown(samplingProbability))); + assertThat(ConsistentSampler.getLowerBoundP(samplingProbability)).isEqualTo(i); + assertThat(ConsistentSampler.getLowerBoundP(Math.nextUp(samplingProbability))) + .isEqualTo(i - 1); + assertThat(ConsistentSampler.getLowerBoundP(Math.nextDown(samplingProbability))).isEqualTo(i); } - assertEquals(OtelTraceState.getMaxP() - 1, ConsistentSampler.getLowerBoundP(Double.MIN_NORMAL)); - assertEquals(OtelTraceState.getMaxP() - 1, ConsistentSampler.getLowerBoundP(Double.MIN_VALUE)); - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getLowerBoundP(0.0)); + assertThat(ConsistentSampler.getLowerBoundP(Double.MIN_NORMAL)) + .isEqualTo(OtelTraceState.getMaxP() - 1); + assertThat(ConsistentSampler.getLowerBoundP(Double.MIN_VALUE)) + .isEqualTo(OtelTraceState.getMaxP() - 1); + assertThat(ConsistentSampler.getLowerBoundP(0.0)).isEqualTo(OtelTraceState.getMaxP()); } @Test void testGetUpperBoundP() { - assertEquals(0, ConsistentSampler.getUpperBoundP(1.0)); - assertEquals(1, ConsistentSampler.getUpperBoundP(Math.nextDown(1.0))); + assertThat(ConsistentSampler.getUpperBoundP(1.0)).isEqualTo(0); + assertThat(ConsistentSampler.getUpperBoundP(Math.nextDown(1.0))).isEqualTo(1); for (int i = 1; i < OtelTraceState.getMaxP() - 1; i += 1) { double samplingProbability = Math.pow(0.5, i); - assertEquals(i, ConsistentSampler.getUpperBoundP(samplingProbability)); - assertEquals(i, ConsistentSampler.getUpperBoundP(Math.nextUp(samplingProbability))); - assertEquals(i + 1, ConsistentSampler.getUpperBoundP(Math.nextDown(samplingProbability))); + assertThat(ConsistentSampler.getUpperBoundP(samplingProbability)).isEqualTo(i); + assertThat(ConsistentSampler.getUpperBoundP(Math.nextUp(samplingProbability))).isEqualTo(i); + assertThat(ConsistentSampler.getUpperBoundP(Math.nextDown(samplingProbability))) + .isEqualTo(i + 1); } - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getUpperBoundP(Double.MIN_NORMAL)); - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getUpperBoundP(Double.MIN_VALUE)); - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getUpperBoundP(0.0)); + assertThat(ConsistentSampler.getUpperBoundP(Double.MIN_NORMAL)) + .isEqualTo(OtelTraceState.getMaxP()); + assertThat(ConsistentSampler.getUpperBoundP(Double.MIN_VALUE)) + .isEqualTo(OtelTraceState.getMaxP()); + assertThat(ConsistentSampler.getUpperBoundP(0.0)).isEqualTo(OtelTraceState.getMaxP()); } @Test @@ -168,18 +171,18 @@ private static void assertConsistentSampling( SamplingResult samplingResult = sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); - assertEquals(expectSampled, getSampledFlag(samplingResult)); + assertThat(getSampledFlag(samplingResult)).isEqualTo(expectSampled); OptionalInt p = getP(samplingResult, parentContext); if (OtelTraceState.isValidP(expectedP)) { - assertEquals(expectedP, p.getAsInt()); + assertThat(p.getAsInt()).isEqualTo(expectedP); } else { - assertFalse(p.isPresent()); + assertThat(p.isPresent()).isFalse(); } OptionalInt r = getR(samplingResult, parentContext); if (OtelTraceState.isValidR(expectedR)) { - assertEquals(expectedR, r.getAsInt()); + assertThat(r.getAsInt()).isEqualTo(expectedR); } else { - assertFalse(r.isPresent()); + assertThat(r.isPresent()).isFalse(); } } diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java index a6fd85d47..fbb6b6dc7 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java @@ -5,75 +5,72 @@ package io.opentelemetry.contrib.sampler.consistent; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class OtelTraceStateTest { +class OtelTraceStateTest { private static String getXString(int len) { return Stream.generate(() -> "X").limit(len).collect(Collectors.joining()); } @Test - public void test() { + void test() { - Assertions.assertEquals("", OtelTraceState.parse("").serialize()); - assertEquals("", OtelTraceState.parse("").serialize()); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); - assertEquals("", OtelTraceState.parse("a").serialize()); - assertEquals("", OtelTraceState.parse("#").serialize()); - assertEquals("", OtelTraceState.parse(" ").serialize()); + assertThat(OtelTraceState.parse("a").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("#").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse(" ").serialize()).isEqualTo(""); - assertEquals("p:5", OtelTraceState.parse("p:5").serialize()); - assertEquals("p:63", OtelTraceState.parse("p:63").serialize()); - assertEquals("", OtelTraceState.parse("p:64").serialize()); - assertEquals("", OtelTraceState.parse("p:5;").serialize()); - assertEquals("", OtelTraceState.parse("p:99").serialize()); - assertEquals("", OtelTraceState.parse("p:").serialize()); - assertEquals("", OtelTraceState.parse("p:232").serialize()); - assertEquals("", OtelTraceState.parse("x;p:5").serialize()); - assertEquals("", OtelTraceState.parse("p:5;x").serialize()); - assertEquals("p:5;x:3", OtelTraceState.parse("x:3;p:5").serialize()); - assertEquals("p:5;x:3", OtelTraceState.parse("p:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("p:5;x:3;").serialize()); - assertEquals( - "p:5;a:" + getXString(246) + ";x:3", - OtelTraceState.parse("a:" + getXString(246) + ";p:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("a:" + getXString(247) + ";p:5;x:3").serialize()); + assertThat(OtelTraceState.parse("p:5").serialize()).isEqualTo("p:5"); + assertThat(OtelTraceState.parse("p:63").serialize()).isEqualTo("p:63"); + assertThat(OtelTraceState.parse("p:64").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:5;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:99").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:232").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x;p:5").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:5;x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x:3;p:5").serialize()).isEqualTo("p:5;x:3"); + assertThat(OtelTraceState.parse("p:5;x:3").serialize()).isEqualTo("p:5;x:3"); + assertThat(OtelTraceState.parse("p:5;x:3;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("a:" + getXString(246) + ";p:5;x:3").serialize()) + .isEqualTo("p:5;a:" + getXString(246) + ";x:3"); + assertThat(OtelTraceState.parse("a:" + getXString(247) + ";p:5;x:3").serialize()).isEqualTo(""); - assertEquals("r:5", OtelTraceState.parse("r:5").serialize()); - assertEquals("r:62", OtelTraceState.parse("r:62").serialize()); - assertEquals("", OtelTraceState.parse("r:63").serialize()); - assertEquals("", OtelTraceState.parse("r:5;").serialize()); - assertEquals("", OtelTraceState.parse("r:99").serialize()); - assertEquals("", OtelTraceState.parse("r:").serialize()); - assertEquals("", OtelTraceState.parse("r:232").serialize()); - assertEquals("", OtelTraceState.parse("x;r:5").serialize()); - assertEquals("", OtelTraceState.parse("r:5;x").serialize()); - assertEquals("r:5;x:3", OtelTraceState.parse("x:3;r:5").serialize()); - assertEquals("r:5;x:3", OtelTraceState.parse("r:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("r:5;x:3;").serialize()); - assertEquals( - "r:5;a:" + getXString(246) + ";x:3", - OtelTraceState.parse("a:" + getXString(246) + ";r:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("a:" + getXString(247) + ";r:5;x:3").serialize()); + assertThat(OtelTraceState.parse("r:5").serialize()).isEqualTo("r:5"); + assertThat(OtelTraceState.parse("r:62").serialize()).isEqualTo("r:62"); + assertThat(OtelTraceState.parse("r:63").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:5;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:99").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:232").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x;r:5").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:5;x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x:3;r:5").serialize()).isEqualTo("r:5;x:3"); + assertThat(OtelTraceState.parse("r:5;x:3").serialize()).isEqualTo("r:5;x:3"); + assertThat(OtelTraceState.parse("r:5;x:3;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("a:" + getXString(246) + ";r:5;x:3").serialize()) + .isEqualTo("r:5;a:" + getXString(246) + ";x:3"); + assertThat(OtelTraceState.parse("a:" + getXString(247) + ";r:5;x:3").serialize()).isEqualTo(""); - assertEquals("p:7;r:5", OtelTraceState.parse("r:5;p:7").serialize()); - assertEquals("p:4;r:5", OtelTraceState.parse("r:5;p:4").serialize()); - assertEquals("p:7;r:5", OtelTraceState.parse("r:5;p:7").serialize()); - assertEquals("p:4;r:5", OtelTraceState.parse("r:5;p:4").serialize()); + assertThat(OtelTraceState.parse("r:5;p:7").serialize()).isEqualTo("p:7;r:5"); + assertThat(OtelTraceState.parse("r:5;p:4").serialize()).isEqualTo("p:4;r:5"); + assertThat(OtelTraceState.parse("r:5;p:7").serialize()).isEqualTo("p:7;r:5"); + assertThat(OtelTraceState.parse("r:5;p:4").serialize()).isEqualTo("p:4;r:5"); - assertEquals("r:6", OtelTraceState.parse("r:5;r:6").serialize()); - assertEquals("p:6;r:10", OtelTraceState.parse("p:5;p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse("p5;p:6;r:10").serialize()); - assertEquals("p:6;r:10;p5:3", OtelTraceState.parse("p5:3;p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse(":p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse(";p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse("_;p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse("5;p:6;r:10").serialize()); + assertThat(OtelTraceState.parse("r:5;r:6").serialize()).isEqualTo("r:6"); + assertThat(OtelTraceState.parse("p:5;p:6;r:10").serialize()).isEqualTo("p:6;r:10"); + assertThat(OtelTraceState.parse("p5;p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p5:3;p:6;r:10").serialize()).isEqualTo("p:6;r:10;p5:3"); + assertThat(OtelTraceState.parse(":p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse(";p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("_;p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("5;p:6;r:10").serialize()).isEqualTo(""); } } diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java index f94e7eef4..e2f336727 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java @@ -14,7 +14,7 @@ import org.hipparchus.stat.inference.GTest; import org.junit.jupiter.api.Test; -public class RandomGeneratorTest { +class RandomGeneratorTest { private static void testGenerateRandomBitSet(long seed, int numBits, int numOneBits) { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java index 9b5fc050b..d0425aa0b 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; -public class ConsistentAlwaysOffSamplerTest { +class ConsistentAlwaysOffSamplerTest { @Test void testDescription() { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java index 3a6b8531b..115c39c41 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; -public class ConsistentAlwaysOnSamplerTest { +class ConsistentAlwaysOnSamplerTest { @Test void testDescription() { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java index 7eac3ffb1..3d78de81a 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java @@ -25,7 +25,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class ConsistentFixedThresholdSamplerTest { +class ConsistentFixedThresholdSamplerTest { private Context parentContext; private String name; @@ -75,7 +75,7 @@ private void testSampling(SplittableRandom rng, double samplingProbability) { } @Test - public void testSampling() { + void testSampling() { // fix seed to get reproducible results SplittableRandom random = new SplittableRandom(0); @@ -92,7 +92,7 @@ public void testSampling() { } @Test - public void testDescription() { + void testDescription() { assertThat(ConsistentSampler.probabilityBased(1.0).getDescription()) .isEqualTo("ConsistentFixedThresholdSampler{threshold=0, sampling probability=1.0}"); assertThat(ConsistentSampler.probabilityBased(0.5).getDescription()) diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java index fcf2dcd8d..d612f9e0a 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java @@ -19,7 +19,7 @@ import org.junit.jupiter.api.Test; -public class ConsistentSamplingUtilTest { +class ConsistentSamplingUtilTest { @Test void testCalculateSamplingProbability() { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java index a131e9b78..8e8b3ef96 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java @@ -5,71 +5,79 @@ package io.opentelemetry.contrib.sampler.consistent56; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; -public class OtelTraceStateTest { +class OtelTraceStateTest { private static String getXString(int len) { return Stream.generate(() -> "X").limit(len).collect(Collectors.joining()); } @Test - public void test() { + void test() { - assertEquals("", OtelTraceState.parse("").serialize()); - assertEquals("", OtelTraceState.parse("").serialize()); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); - assertEquals("", OtelTraceState.parse("a").serialize()); - assertEquals("", OtelTraceState.parse("#").serialize()); - assertEquals("", OtelTraceState.parse(" ").serialize()); + assertThat(OtelTraceState.parse("a").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("#").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse(" ").serialize()).isEqualTo(""); - assertEquals("rv:1234567890abcd", OtelTraceState.parse("rv:1234567890abcd").serialize()); - assertEquals("rv:01020304050607", OtelTraceState.parse("rv:01020304050607").serialize()); - assertEquals("", OtelTraceState.parse("rv:1234567890abcde").serialize()); + assertThat(OtelTraceState.parse("rv:1234567890abcd").serialize()) + .isEqualTo("rv:1234567890abcd"); + assertThat(OtelTraceState.parse("rv:01020304050607").serialize()) + .isEqualTo("rv:01020304050607"); + assertThat(OtelTraceState.parse("rv:1234567890abcde").serialize()).isEqualTo(""); - assertEquals("th:1234567890abcd", OtelTraceState.parse("th:1234567890abcd").serialize()); - assertEquals("th:01020304050607", OtelTraceState.parse("th:01020304050607").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000000000").serialize()); - assertEquals("th:12345", OtelTraceState.parse("th:1234500000000").serialize()); - assertEquals("th:0", OtelTraceState.parse("th:0").serialize()); // TODO - assertEquals("", OtelTraceState.parse("th:100000000000000").serialize()); - assertEquals("", OtelTraceState.parse("th:1234567890abcde").serialize()); + assertThat(OtelTraceState.parse("th:1234567890abcd").serialize()) + .isEqualTo("th:1234567890abcd"); + assertThat(OtelTraceState.parse("th:01020304050607").serialize()) + .isEqualTo("th:01020304050607"); + assertThat(OtelTraceState.parse("th:10000000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1234500000000").serialize()).isEqualTo("th:12345"); + assertThat(OtelTraceState.parse("th:0").serialize()).isEqualTo("th:0"); // TODO + assertThat(OtelTraceState.parse("th:100000000000000").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("th:1234567890abcde").serialize()).isEqualTo(""); - assertEquals( - "th:1234567890abcd;rv:1234567890abcd;a:" + getXString(214) + ";x:3", - OtelTraceState.parse("a:" + getXString(214) + ";rv:1234567890abcd;th:1234567890abcd;x:3") - .serialize()); - assertEquals( - "", - OtelTraceState.parse("a:" + getXString(215) + ";rv:1234567890abcd;th:1234567890abcd;x:3") - .serialize()); + assertThat( + OtelTraceState.parse( + "a:" + getXString(214) + ";rv:1234567890abcd;th:1234567890abcd;x:3") + .serialize()) + .isEqualTo("th:1234567890abcd;rv:1234567890abcd;a:" + getXString(214) + ";x:3"); + assertThat( + OtelTraceState.parse( + "a:" + getXString(215) + ";rv:1234567890abcd;th:1234567890abcd;x:3") + .serialize()) + .isEqualTo(""); - assertEquals("", OtelTraceState.parse("th:x").serialize()); - assertEquals("", OtelTraceState.parse("th:100000000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1").serialize()); + assertThat(OtelTraceState.parse("th:x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("th:100000000000000").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("th:10000000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1").serialize()).isEqualTo("th:1"); - assertEquals("th:10000000000001", OtelTraceState.parse("th:10000000000001").serialize()); - assertEquals("th:1000000000001", OtelTraceState.parse("th:10000000000010").serialize()); - assertEquals("", OtelTraceState.parse("rv:x").serialize()); - assertEquals("", OtelTraceState.parse("rv:100000000000000").serialize()); - assertEquals("rv:10000000000000", OtelTraceState.parse("rv:10000000000000").serialize()); - assertEquals("", OtelTraceState.parse("rv:1000000000000").serialize()); + assertThat(OtelTraceState.parse("th:10000000000001").serialize()) + .isEqualTo("th:10000000000001"); + assertThat(OtelTraceState.parse("th:10000000000010").serialize()).isEqualTo("th:1000000000001"); + assertThat(OtelTraceState.parse("rv:x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("rv:100000000000000").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("rv:10000000000000").serialize()) + .isEqualTo("rv:10000000000000"); + assertThat(OtelTraceState.parse("rv:1000000000000").serialize()).isEqualTo(""); } } diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java index ab7d378b6..d9a34255f 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; -public class RandomValueGeneratorsTest { +class RandomValueGeneratorsTest { @Test void testRandomRange() { int attempts = 10000; diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 58d3e04d7..637f8fbac 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } val otelInstrumentationVersion = "2.19.0-alpha" -val semconvVersion = "1.34.0" +val semconvVersion = "1.37.0" javaPlatform { allowDependencies() @@ -15,8 +15,8 @@ dependencies { // (the constraints section below doesn't have this issue, and will only show up // as runtime dependencies if they are actually used as runtime dependencies) api(enforcedPlatform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:${otelInstrumentationVersion}")) - api(enforcedPlatform("com.fasterxml.jackson:jackson-bom:2.19.2")) - api(enforcedPlatform("com.google.protobuf:protobuf-bom:4.32.0")) + api(enforcedPlatform("com.fasterxml.jackson:jackson-bom:2.20.0")) + api(enforcedPlatform("com.google.protobuf:protobuf-bom:4.32.1")) api(enforcedPlatform("com.squareup.okhttp3:okhttp-bom:5.1.0")) constraints { @@ -30,7 +30,7 @@ dependencies { api("com.google.errorprone:error_prone_annotations:2.41.0") api("com.google.errorprone:error_prone_core:2.41.0") api("io.github.netmikey.logunit:logunit-jul:2.0.0") - api("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + api("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") api("io.prometheus:simpleclient:0.16.0") api("io.prometheus:simpleclient_common:0.16.0") api("io.prometheus:simpleclient_httpserver:0.16.0") @@ -51,7 +51,7 @@ dependencies { api("org.bouncycastle:bcpkix-jdk15on:1.70") api("org.junit-pioneer:junit-pioneer:1.9.1") api("org.skyscreamer:jsonassert:1.5.3") - api("org.apache.kafka:kafka-clients:4.0.0") + api("org.apache.kafka:kafka-clients:4.1.0") api("org.testcontainers:kafka:1.21.3") api("com.lmax:disruptor:3.4.4") api("org.jctools:jctools-core:4.0.5") diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index 0a883cf73..c36d73588 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -6,7 +6,7 @@ plugins { id("otel.animalsniffer-conventions") id("com.gradleup.shadow") id("me.champeau.jmh") version "0.7.3" - id("com.squareup.wire") version "5.3.11" + id("com.squareup.wire") version "5.4.0" } description = "Exporter implementations that store signals on disk" @@ -23,7 +23,7 @@ dependencies { testImplementation("org.mockito:mockito-inline") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") - protos("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha@jar") + protos("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha@jar") } jmh { diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java index c26a383d6..6c38be04a 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -public class LogRecordFromDiskExporter implements FromDiskExporter { +public final class LogRecordFromDiskExporter implements FromDiskExporter { private final FromDiskExporterImpl delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java index 665e90f76..1524723e8 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java @@ -18,7 +18,8 @@ * This class implements a {@link LogRecordExporter} that delegates to an instance of {@code * ToDiskExporter}. */ -public class LogRecordToDiskExporter implements LogRecordExporter { +public final class LogRecordToDiskExporter implements LogRecordExporter { + private final ToDiskExporter delegate; /** diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java index 8bb4f3dcd..36d478e7b 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -public class MetricFromDiskExporter implements FromDiskExporter { +public final class MetricFromDiskExporter implements FromDiskExporter { private final FromDiskExporterImpl delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java index 83d2fc73c..2e0848684 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java @@ -21,7 +21,7 @@ * This class implements a {@link MetricExporter} that delegates to an instance of {@code * ToDiskExporter}. */ -public class MetricToDiskExporter implements MetricExporter { +public final class MetricToDiskExporter implements MetricExporter { private final ToDiskExporter delegate; private final AggregationTemporalitySelector aggregationTemporalitySelector; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java index e3c7992ba..9523c8a2f 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -public class SpanFromDiskExporter implements FromDiskExporter { +public final class SpanFromDiskExporter implements FromDiskExporter { private final FromDiskExporterImpl delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java index d5ca81518..dcd79d3b0 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java @@ -18,7 +18,7 @@ * This class implements a SpanExporter that delegates to an instance of {@code * ToDiskExporter}. */ -public class SpanToDiskExporter implements SpanExporter { +public final class SpanToDiskExporter implements SpanExporter { private final ToDiskExporter delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java index 4853ee72f..e8a7f0bd0 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java @@ -5,9 +5,11 @@ package io.opentelemetry.contrib.disk.buffering.config; +import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.SECONDS; + import com.google.auto.value.AutoValue; import java.io.File; -import java.util.concurrent.TimeUnit; /** Defines how the storage should be managed. */ @AutoValue @@ -56,9 +58,9 @@ public static Builder builder() { return new AutoValue_StorageConfiguration.Builder() .setMaxFileSize(1024 * 1024) // 1MB .setMaxFolderSize(10 * 1024 * 1024) // 10MB - .setMaxFileAgeForWriteMillis(TimeUnit.SECONDS.toMillis(30)) - .setMinFileAgeForReadMillis(TimeUnit.SECONDS.toMillis(33)) - .setMaxFileAgeForReadMillis(TimeUnit.HOURS.toMillis(18)) + .setMaxFileAgeForWriteMillis(SECONDS.toMillis(30)) + .setMinFileAgeForReadMillis(SECONDS.toMillis(33)) + .setMaxFileAgeForReadMillis(HOURS.toMillis(18)) .setDebugEnabled(false); } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java index 51d135299..c508d042f 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.exporters; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import io.opentelemetry.contrib.disk.buffering.SignalType; import io.opentelemetry.contrib.disk.buffering.storage.SignalStorage; import io.opentelemetry.contrib.disk.buffering.storage.result.WriteResult; @@ -13,7 +15,6 @@ import java.util.Collection; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** Internal utility for common export to disk operations across all exporters. */ @@ -34,7 +35,7 @@ public SignalStorageExporter( public CompletableResultCode exportToStorage(Collection items) { CompletableFuture future = storage.write(items); try { - WriteResult operation = future.get(writeTimeout.toMillis(), TimeUnit.MILLISECONDS); + WriteResult operation = future.get(writeTimeout.toMillis(), MILLISECONDS); if (operation.isSuccessful()) { callback.onExportSuccess(type); return CompletableResultCode.ofSuccess(); diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java index 2bda19da9..3efe5c367 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java @@ -16,9 +16,10 @@ /** Exporter that stores spans into disk. */ public final class SpanToDiskExporter implements SpanExporter { + private static final SignalType TYPE = SignalType.SPAN; + private final SignalStorageExporter storageExporter; private final ExporterCallback callback; - private static final SignalType TYPE = SignalType.SPAN; private SpanToDiskExporter( SignalStorageExporter storageExporter, ExporterCallback callback) { @@ -26,7 +27,7 @@ private SpanToDiskExporter( this.callback = callback; } - public Builder builder(SignalStorage.Span storage) { + public static Builder builder(SignalStorage.Span storage) { return new Builder(storage); } @@ -51,6 +52,10 @@ public static final class Builder { private ExporterCallback callback = ExporterCallback.noop(); private Duration writeTimeout = Duration.ofSeconds(10); + private Builder(SignalStorage.Span storage) { + this.storage = storage; + } + @CanIgnoreReturnValue public Builder setExporterCallback(ExporterCallback value) { callback = value; @@ -68,9 +73,5 @@ public SpanToDiskExporter build() { new SignalStorageExporter<>(storage, callback, writeTimeout, TYPE); return new SpanToDiskExporter(storageExporter, callback); } - - private Builder(SignalStorage.Span storage) { - this.storage = storage; - } } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java index 5b2dcd186..a3104a892 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.disk.buffering.internal.exporter; +import static java.util.logging.Level.FINER; +import static java.util.logging.Level.WARNING; + import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; import io.opentelemetry.contrib.disk.buffering.internal.storage.Storage; import io.opentelemetry.contrib.disk.buffering.internal.utils.DebugLogger; @@ -12,7 +15,6 @@ import java.io.IOException; import java.util.Collection; import java.util.function.Function; -import java.util.logging.Level; import java.util.logging.Logger; public class ToDiskExporter { @@ -39,7 +41,7 @@ public static ToDiskExporterBuilder builder(Storage storage) { } public synchronized CompletableResultCode export(Collection data) { - logger.log("Intercepting exporter batch.", Level.FINER); + logger.log("Intercepting exporter batch.", FINER); try { serializer.initialize(data); if (storage.write(serializer)) { @@ -50,7 +52,7 @@ public synchronized CompletableResultCode export(Collection data) { } catch (IOException e) { logger.log( "An unexpected error happened while attempting to write the data in disk. Exporting it right away.", - Level.WARNING, + WARNING, e); return exportFunction.apply(data); } finally { diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java index cbbb4a0ad..075a0f103 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java @@ -26,7 +26,7 @@ public List deserialize(byte[] source) throws DeserializationExce try { return ProtoLogsDataMapper.getInstance() .fromProto(ExportLogsServiceRequest.ADAPTER.decode(source)); - } catch (IOException e) { + } catch (IOException | IllegalStateException e) { throw new DeserializationException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java index d6410d4e7..463c07b75 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java @@ -26,7 +26,7 @@ public List deserialize(byte[] source) throws DeserializationExcepti try { return ProtoMetricsDataMapper.getInstance() .fromProto(ExportMetricsServiceRequest.ADAPTER.decode(source)); - } catch (IOException e) { + } catch (IOException | IllegalStateException e) { throw new DeserializationException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java index eb4406ff3..b703c3ade 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java @@ -26,7 +26,7 @@ public List deserialize(byte[] source) throws DeserializationException try { return ProtoSpansDataMapper.getInstance() .fromProto(ExportTraceServiceRequest.ADAPTER.decode(source)); - } catch (IOException e) { + } catch (IOException | IllegalStateException e) { throw new DeserializationException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java index d43bc18b2..ebea37171 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java @@ -5,13 +5,14 @@ package io.opentelemetry.contrib.disk.buffering.internal.storage; +import static java.util.logging.Level.INFO; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.contrib.disk.buffering.config.StorageConfiguration; import io.opentelemetry.contrib.disk.buffering.internal.utils.SignalTypes; import io.opentelemetry.sdk.common.Clock; import java.io.File; import java.io.IOException; -import java.util.logging.Level; import java.util.logging.Logger; public class StorageBuilder { @@ -43,7 +44,7 @@ public Storage build() throws IOException { File folder = ensureSubdir(configuration.getRootDir(), folderName); FolderManager folderManager = new FolderManager(folder, configuration, clock); if (configuration.isDebugEnabled()) { - logger.log(Level.INFO, "Building storage with configuration => " + configuration); + logger.log(INFO, "Building storage with configuration => " + configuration); } return new Storage(folderManager, configuration.isDebugEnabled()); } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java index 46ff72ebf..b0bb67624 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.utils; +import static java.util.logging.Level.INFO; + import java.util.logging.Level; import java.util.logging.Logger; @@ -22,7 +24,7 @@ public static DebugLogger wrap(Logger logger, boolean debugEnabled) { } public void log(String msg) { - log(msg, Level.INFO); + log(msg, INFO); } public void log(String msg, Level level) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java index b46cba12f..ee4deb57a 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java @@ -6,9 +6,7 @@ package io.opentelemetry.contrib.disk.buffering; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -53,7 +51,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -public class IntegrationTest { +class IntegrationTest { private InMemorySpanExporter memorySpanExporter; private Tracer tracer; private InMemoryMetricExporter memoryMetricExporter; @@ -168,20 +166,20 @@ void verifyLogRecordsIntegration() throws IOException { private void assertExporter(FromDiskExporterImpl exporter, Supplier finishedItems) throws IOException { // Verify no data has been received in the original exporter until this point. - assertEquals(0, finishedItems.get()); + assertThat(finishedItems.get()).isEqualTo(0); // Go to the future when we can read the stored items. fastForwardTimeByMillis(storageConfig.getMinFileAgeForReadMillis()); // Read and send stored data. - assertTrue(exporter.exportStoredBatch(1, TimeUnit.SECONDS)); + assertThat(exporter.exportStoredBatch(1, TimeUnit.SECONDS)).isTrue(); // Now the data must have been delegated to the original exporter. - assertEquals(1, finishedItems.get()); + assertThat(finishedItems.get()).isEqualTo(1); // Bonus: Try to read again, no more data should be available. - assertFalse(exporter.exportStoredBatch(1, TimeUnit.SECONDS)); - assertEquals(1, finishedItems.get()); + assertThat(exporter.exportStoredBatch(1, TimeUnit.SECONDS)).isFalse(); + assertThat(finishedItems.get()).isEqualTo(1); } @SuppressWarnings("DirectInvocationOnMock") diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializerTest.java new file mode 100644 index 000000000..a428956a7 --- /dev/null +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializerTest.java @@ -0,0 +1,61 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.serialization.deserializers; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import io.opentelemetry.api.common.Value; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.logs.models.LogRecordDataImpl; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; +import io.opentelemetry.contrib.disk.buffering.testutils.BaseSignalSerializerTest; +import io.opentelemetry.contrib.disk.buffering.testutils.TestData; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import org.junit.jupiter.api.Test; + +class LogRecordDataDeserializerTest extends BaseSignalSerializerTest { + private static final LogRecordData LOG_RECORD = + LogRecordDataImpl.builder() + .setResource(TestData.RESOURCE_FULL) + .setSpanContext(TestData.SPAN_CONTEXT) + .setInstrumentationScopeInfo(TestData.INSTRUMENTATION_SCOPE_INFO_FULL) + .setAttributes(TestData.ATTRIBUTES) + .setBodyValue(Value.of("Log body")) + .setSeverity(Severity.DEBUG) + .setSeverityText("Log severity text") + .setTimestampEpochNanos(100L) + .setObservedTimestampEpochNanos(200L) + .setTotalAttributeCount(3) + .setEventName("event") + .build(); + + @Test + void verifyDeserialization() { + assertSerializeDeserialize(LOG_RECORD, LOG_RECORD); + } + + @Test + void whenDecodingMalformedMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeMalformedSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Test + void whenDecodingTooShortMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeTooShortSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Override + protected SignalSerializer getSerializer() { + return SignalSerializer.ofLogs(); + } + + @Override + protected SignalDeserializer getDeserializer() { + return SignalDeserializer.ofLogs(); + } +} diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializerTest.java new file mode 100644 index 000000000..7364d865f --- /dev/null +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializerTest.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.serialization.deserializers; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; +import io.opentelemetry.contrib.disk.buffering.testutils.BaseSignalSerializerTest; +import io.opentelemetry.contrib.disk.buffering.testutils.TestData; +import io.opentelemetry.sdk.metrics.data.MetricData; +import org.junit.jupiter.api.Test; + +class MetricDataDeserializerTest extends BaseSignalSerializerTest { + + @Test + void whenDecodingMalformedMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeMalformedSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Test + void whenDecodingTooShortMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeTooShortSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Override + protected SignalSerializer getSerializer() { + return SignalSerializer.ofMetrics(); + } + + @Override + protected SignalDeserializer getDeserializer() { + return SignalDeserializer.ofMetrics(); + } +} diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializerTest.java new file mode 100644 index 000000000..1b9c61874 --- /dev/null +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.serialization.deserializers; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans.models.SpanDataImpl; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; +import io.opentelemetry.contrib.disk.buffering.testutils.BaseSignalSerializerTest; +import io.opentelemetry.contrib.disk.buffering.testutils.TestData; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.data.StatusData; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class SpanDataDeserializerTest extends BaseSignalSerializerTest { + private static final SpanData SPAN_DATA = + SpanDataImpl.builder() + .setSpanContext(TestData.SPAN_CONTEXT) + .setParentSpanContext(TestData.PARENT_SPAN_CONTEXT) + .setName("Test span") + .setKind(SpanKind.SERVER) + .setStartEpochNanos(100L) + .setEndEpochNanos(200L) + .setStatus(StatusData.ok()) + .setAttributes(TestData.ATTRIBUTES) + .setResource(TestData.RESOURCE_FULL) + .setInstrumentationScopeInfo(TestData.INSTRUMENTATION_SCOPE_INFO_FULL) + .setTotalRecordedLinks(0) + .setTotalRecordedEvents(0) + .setTotalAttributeCount(0) + .setEvents(Collections.emptyList()) + .setLinks(Collections.emptyList()) + .build(); + + @Test + void verifyDeserialization() { + assertSerializeDeserialize(SPAN_DATA, SPAN_DATA); + } + + @Test + void whenDecodingMalformedMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeMalformedSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Test + void whenDecodingTooShortMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeTooShortSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Override + protected SignalSerializer getSerializer() { + return SignalSerializer.ofSpans(); + } + + @Override + protected SignalDeserializer getDeserializer() { + return SignalDeserializer.ofSpans(); + } +} diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java index 2857cf8da..ceb758642 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.common; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -28,7 +28,7 @@ void verifyMapping() { List proto = mapToProto(attributes); - assertEquals(attributes, mapFromProto(proto)); + assertThat(mapFromProto(proto)).isEqualTo(attributes); } @Test @@ -45,7 +45,7 @@ void verifyArrayMapping() { List serialized = mapToProto(attributes); - assertEquals(attributes, mapFromProto(serialized)); + assertThat(mapFromProto(serialized)).isEqualTo(attributes); } private static List mapToProto(Attributes attributes) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java index e9feb8be4..9776cd068 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.common; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.contrib.disk.buffering.testutils.TestData; import io.opentelemetry.proto.resource.v1.Resource; @@ -17,7 +17,8 @@ class ResourceMapperTest { void verifyMapping() { Resource proto = mapToProto(TestData.RESOURCE_FULL); - assertEquals(TestData.RESOURCE_FULL, mapToSdk(proto, TestData.RESOURCE_FULL.getSchemaUrl())); + assertThat(mapToSdk(proto, TestData.RESOURCE_FULL.getSchemaUrl())) + .isEqualTo(TestData.RESOURCE_FULL); } private static Resource mapToProto(io.opentelemetry.sdk.resources.Resource sdkResource) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java index 0041c61bf..56710355f 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.logs; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.Value; import io.opentelemetry.api.logs.Severity; @@ -38,9 +38,8 @@ class LogRecordDataMapperTest { void verifyMapping() { LogRecord proto = mapToProto(LOG_RECORD); - assertEquals( - LOG_RECORD, - mapToSdk(proto, LOG_RECORD.getResource(), LOG_RECORD.getInstrumentationScopeInfo())); + assertThat(mapToSdk(proto, LOG_RECORD.getResource(), LOG_RECORD.getInstrumentationScopeInfo())) + .isEqualTo(LOG_RECORD); } private static LogRecord mapToProto(LogRecordData data) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java index 9a5d93cd8..7242bd65e 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.logs; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.common.Value; import io.opentelemetry.api.logs.Severity; @@ -107,9 +106,9 @@ void verifyConversionDataStructure() { ExportLogsServiceRequest result = mapToProto(signals); List resourceLogsList = result.resource_logs; - assertEquals(1, resourceLogsList.size()); - assertEquals(1, resourceLogsList.get(0).scope_logs.size()); - assertEquals(1, resourceLogsList.get(0).scope_logs.get(0).log_records.size()); + assertThat(resourceLogsList).hasSize(1); + assertThat(resourceLogsList.get(0).scope_logs).hasSize(1); + assertThat(resourceLogsList.get(0).scope_logs.get(0).log_records).hasSize(1); assertThat(mapFromProto(result)).containsExactlyInAnyOrderElementsOf(signals); } @@ -121,15 +120,15 @@ void verifyMultipleLogsWithSameResourceAndScope() { ExportLogsServiceRequest proto = mapToProto(signals); List resourceLogsList = proto.resource_logs; - assertEquals(1, resourceLogsList.size()); + assertThat(resourceLogsList).hasSize(1); List scopeLogsList = resourceLogsList.get(0).scope_logs; - assertEquals(1, scopeLogsList.size()); + assertThat(scopeLogsList).hasSize(1); List logRecords = scopeLogsList.get(0).log_records; - assertEquals(2, logRecords.size()); - assertEquals("Log body", logRecords.get(0).body.string_value); - assertEquals("Other log body", logRecords.get(1).body.string_value); + assertThat(logRecords).hasSize(2); + assertThat(logRecords.get(0).body.string_value).isEqualTo("Log body"); + assertThat(logRecords.get(1).body.string_value).isEqualTo("Other log body"); - assertEquals(2, mapFromProto(proto).size()); + assertThat(mapFromProto(proto)).hasSize(2); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -142,15 +141,15 @@ void verifyMultipleLogsWithSameResourceDifferentScope() { ExportLogsServiceRequest proto = mapToProto(signals); List resourceLogsList = proto.resource_logs; - assertEquals(1, resourceLogsList.size()); + assertThat(resourceLogsList).hasSize(1); List scopeLogsList = resourceLogsList.get(0).scope_logs; - assertEquals(2, scopeLogsList.size()); + assertThat(scopeLogsList).hasSize(2); ScopeLogs firstScope = scopeLogsList.get(0); ScopeLogs secondScope = scopeLogsList.get(1); List firstScopeLogs = firstScope.log_records; List secondScopeLogs = secondScope.log_records; - assertEquals(1, firstScopeLogs.size()); - assertEquals(1, secondScopeLogs.size()); + assertThat(firstScopeLogs).hasSize(1); + assertThat(secondScopeLogs).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -162,19 +161,19 @@ void verifyMultipleLogsWithDifferentResource() { ExportLogsServiceRequest proto = mapToProto(signals); List resourceLogsList = proto.resource_logs; - assertEquals(2, resourceLogsList.size()); + assertThat(resourceLogsList).hasSize(2); ResourceLogs firstResourceLogs = resourceLogsList.get(0); ResourceLogs secondResourceLogs = resourceLogsList.get(1); List firstScopeLogsList = firstResourceLogs.scope_logs; List secondScopeLogsList = secondResourceLogs.scope_logs; - assertEquals(1, firstScopeLogsList.size()); - assertEquals(1, secondScopeLogsList.size()); + assertThat(firstScopeLogsList).hasSize(1); + assertThat(secondScopeLogsList).hasSize(1); ScopeLogs firstScope = firstScopeLogsList.get(0); ScopeLogs secondScope = secondScopeLogsList.get(0); List firstScopeLogs = firstScope.log_records; List secondScopeLogs = secondScope.log_records; - assertEquals(1, firstScopeLogs.size()); - assertEquals(1, secondScopeLogs.size()); + assertThat(firstScopeLogs).hasSize(1); + assertThat(secondScopeLogs).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -188,7 +187,7 @@ void verifyLogWithEventName() { List resourceLogsList = result.resource_logs; LogRecord firstLog = resourceLogsList.get(0).scope_logs.get(0).log_records.get(0); - assertEquals("test.event.name", firstLog.event_name); + assertThat(firstLog.event_name).isEqualTo("test.event.name"); assertThat(mapFromProto(result)).containsExactlyInAnyOrderElementsOf(signals); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java index b4f7f64d9..b5e804e29 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java @@ -9,7 +9,6 @@ import static io.opentelemetry.contrib.disk.buffering.testutils.TestData.makeLongGauge; import static io.opentelemetry.contrib.disk.buffering.testutils.TestData.makeLongPointData; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; @@ -121,9 +120,10 @@ void verifySummaryMapping() { Metric proto = mapToProto(summaryMetric); - assertEquals( - summaryMetric, - mapToSdk(proto, summaryMetric.getResource(), summaryMetric.getInstrumentationScopeInfo())); + assertThat( + mapToSdk( + proto, summaryMetric.getResource(), summaryMetric.getInstrumentationScopeInfo())) + .isEqualTo(summaryMetric); } @Test diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java index 59d369704..f114fe04d 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.metrics; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.contrib.disk.buffering.testutils.TestData; @@ -33,9 +32,9 @@ void verifyConversionDataStructure() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(1, resourceMetrics.size()); - assertEquals(1, resourceMetrics.get(0).scope_metrics.size()); - assertEquals(1, resourceMetrics.get(0).scope_metrics.get(0).metrics.size()); + assertThat(resourceMetrics).hasSize(1); + assertThat(resourceMetrics.get(0).scope_metrics).hasSize(1); + assertThat(resourceMetrics.get(0).scope_metrics.get(0).metrics).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(expectedSignals); } @@ -52,11 +51,11 @@ void verifyMultipleMetricsWithSameResourceAndScope() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(1, resourceMetrics.size()); + assertThat(resourceMetrics).hasSize(1); List scopeMetrics = resourceMetrics.get(0).scope_metrics; - assertEquals(1, scopeMetrics.size()); + assertThat(scopeMetrics).hasSize(1); List metrics = scopeMetrics.get(0).metrics; - assertEquals(2, metrics.size()); + assertThat(metrics).hasSize(2); List result = mapFromProto(proto); @@ -81,15 +80,15 @@ void verifyMultipleMetricsWithSameResourceDifferentScope() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(1, resourceMetrics.size()); + assertThat(resourceMetrics).hasSize(1); List scopeMetrics = resourceMetrics.get(0).scope_metrics; - assertEquals(2, scopeMetrics.size()); + assertThat(scopeMetrics).hasSize(2); ScopeMetrics firstScope = scopeMetrics.get(0); ScopeMetrics secondScope = scopeMetrics.get(1); List firstScopeMetrics = firstScope.metrics; List secondScopeMetrics = secondScope.metrics; - assertEquals(1, firstScopeMetrics.size()); - assertEquals(1, secondScopeMetrics.size()); + assertThat(firstScopeMetrics).hasSize(1); + assertThat(secondScopeMetrics).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(expectedSignals); } @@ -116,19 +115,19 @@ void verifyMultipleMetricsWithDifferentResource() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(2, resourceMetrics.size()); + assertThat(resourceMetrics).hasSize(2); ResourceMetrics firstResourceMetrics = resourceMetrics.get(0); ResourceMetrics secondResourceMetrics = resourceMetrics.get(1); List firstScopeMetrics = firstResourceMetrics.scope_metrics; List secondScopeMetrics = secondResourceMetrics.scope_metrics; - assertEquals(1, firstScopeMetrics.size()); - assertEquals(1, secondScopeMetrics.size()); + assertThat(firstScopeMetrics).hasSize(1); + assertThat(secondScopeMetrics).hasSize(1); ScopeMetrics firstScope = firstScopeMetrics.get(0); ScopeMetrics secondScope = secondScopeMetrics.get(0); List firstMetrics = firstScope.metrics; List secondMetrics = secondScope.metrics; - assertEquals(1, firstMetrics.size()); - assertEquals(1, secondMetrics.size()); + assertThat(firstMetrics).hasSize(1); + assertThat(secondMetrics).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(expectedSignals); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java index ca325496b..910455463 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans.models.SpanDataImpl; @@ -119,9 +118,9 @@ void verifyConversionDataStructure() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(1, resourceSpans.size()); - assertEquals(1, resourceSpans.get(0).scope_spans.size()); - assertEquals(1, resourceSpans.get(0).scope_spans.get(0).spans.size()); + assertThat(resourceSpans).hasSize(1); + assertThat(resourceSpans.get(0).scope_spans).hasSize(1); + assertThat(resourceSpans.get(0).scope_spans.get(0).spans).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -133,11 +132,11 @@ void verifyMultipleSpansWithSameResourceAndScope() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(1, resourceSpans.size()); + assertThat(resourceSpans).hasSize(1); List scopeSpans = resourceSpans.get(0).scope_spans; - assertEquals(1, scopeSpans.size()); + assertThat(scopeSpans).hasSize(1); List spans = scopeSpans.get(0).spans; - assertEquals(2, spans.size()); + assertThat(spans).hasSize(2); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -149,15 +148,15 @@ void verifyMultipleSpansWithSameResourceDifferentScope() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(1, resourceSpans.size()); + assertThat(resourceSpans).hasSize(1); List scopeSpans = resourceSpans.get(0).scope_spans; - assertEquals(2, scopeSpans.size()); + assertThat(scopeSpans).hasSize(2); ScopeSpans firstScope = scopeSpans.get(0); ScopeSpans secondScope = scopeSpans.get(1); List firstScopeSpans = firstScope.spans; List secondScopeSpans = secondScope.spans; - assertEquals(1, firstScopeSpans.size()); - assertEquals(1, secondScopeSpans.size()); + assertThat(firstScopeSpans).hasSize(1); + assertThat(secondScopeSpans).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -169,19 +168,19 @@ void verifyMultipleSpansWithDifferentResource() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(2, resourceSpans.size()); + assertThat(resourceSpans).hasSize(2); ResourceSpans firstResourceSpans = resourceSpans.get(0); ResourceSpans secondResourceSpans = resourceSpans.get(1); List firstScopeSpans = firstResourceSpans.scope_spans; List secondScopeSpans = secondResourceSpans.scope_spans; - assertEquals(1, firstScopeSpans.size()); - assertEquals(1, secondScopeSpans.size()); + assertThat(firstScopeSpans).hasSize(1); + assertThat(secondScopeSpans).hasSize(1); ScopeSpans firstScope = firstScopeSpans.get(0); ScopeSpans secondScope = secondScopeSpans.get(0); List firstSpans = firstScope.spans; List secondSpans = secondScope.spans; - assertEquals(1, firstSpans.size()); - assertEquals(1, secondSpans.size()); + assertThat(firstSpans).hasSize(1); + assertThat(secondSpans).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java index de8f8ff78..43394431f 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans.models.SpanDataImpl; @@ -74,21 +74,20 @@ class SpanDataMapperTest { void verifyMapping() { Span proto = mapToProto(SPAN_DATA); - assertEquals( - SPAN_DATA, - mapToSdk(proto, SPAN_DATA.getResource(), SPAN_DATA.getInstrumentationScopeInfo())); + assertThat(mapToSdk(proto, SPAN_DATA.getResource(), SPAN_DATA.getInstrumentationScopeInfo())) + .isEqualTo(SPAN_DATA); } @Test void verifyMappingWithTraceState() { Span proto = mapToProto(SPAN_DATA_WITH_TRACE_STATE); - assertEquals( - SPAN_DATA_WITH_TRACE_STATE, - mapToSdk( - proto, - SPAN_DATA_WITH_TRACE_STATE.getResource(), - SPAN_DATA_WITH_TRACE_STATE.getInstrumentationScopeInfo())); + assertThat( + mapToSdk( + proto, + SPAN_DATA_WITH_TRACE_STATE.getResource(), + SPAN_DATA_WITH_TRACE_STATE.getInstrumentationScopeInfo())) + .isEqualTo(SPAN_DATA_WITH_TRACE_STATE); } private static Span mapToProto(SpanData source) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java index ad994c38d..d8a95a9cc 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java @@ -9,12 +9,8 @@ import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_SIZE; import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MIN_FILE_AGE_FOR_READ_MILLIS; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -52,7 +48,7 @@ void createWritableFile_withTimeMillisAsName() throws IOException { when(clock.now()).thenReturn(MILLISECONDS.toNanos(1000L)); WritableFile file = folderManager.createWritableFile(); - assertEquals("1000", file.getFile().getName()); + assertThat(file.getFile().getName()).isEqualTo("1000"); } @Test @@ -69,12 +65,12 @@ void createWritableFile_andRemoveOldestOne_whenTheAvailableFolderSpaceIsNotEnoug WritableFile file = folderManager.createWritableFile(); - assertNotEquals(existingFile1, file.getFile()); - assertNotEquals(existingFile2, file.getFile()); - assertNotEquals(existingFile3, file.getFile()); - assertTrue(existingFile2.exists()); - assertTrue(existingFile3.exists()); - assertFalse(existingFile1.exists()); + assertThat(file.getFile()).isNotEqualTo(existingFile1); + assertThat(file.getFile()).isNotEqualTo(existingFile2); + assertThat(file.getFile()).isNotEqualTo(existingFile3); + assertThat(existingFile2.exists()).isTrue(); + assertThat(existingFile3.exists()).isTrue(); + assertThat(existingFile1.exists()).isFalse(); } @Test @@ -91,8 +87,8 @@ void closeCurrentlyWritableFile_whenItIsReadyToBeRead_andNoOtherReadableFilesAre ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(writableFile.getFile(), readableFile.getFile()); - assertTrue(writableFile.isClosed()); + assertThat(readableFile.getFile()).isEqualTo(writableFile.getFile()); + assertThat(writableFile.isClosed()).isTrue(); } @Test @@ -109,14 +105,14 @@ void closeCurrentlyWritableFile_whenItIsReadyToBeRead_andNoOtherReadableFilesAre when(clock.now()).thenReturn(MILLISECONDS.toNanos(1000L + MIN_FILE_AGE_FOR_READ_MILLIS)); ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(existingFile1, readableFile.getFile()); + assertThat(readableFile.getFile()).isEqualTo(existingFile1); folderManager.createWritableFile(); - assertTrue(existingFile2.exists()); - assertTrue(existingFile3.exists()); - assertFalse(existingFile1.exists()); - assertTrue(readableFile.isClosed()); + assertThat(existingFile2.exists()).isTrue(); + assertThat(existingFile3.exists()).isTrue(); + assertThat(existingFile1.exists()).isFalse(); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -133,12 +129,12 @@ void createWritableFile_andDoNotRemoveOldestOne_ifAtLeastOneExpiredFileIsPurged( WritableFile file = folderManager.createWritableFile(); - assertNotEquals(existingFile1, file.getFile()); - assertNotEquals(existingFile2, file.getFile()); - assertNotEquals(existingFile3, file.getFile()); - assertTrue(existingFile2.exists()); - assertTrue(existingFile1.exists()); - assertFalse(existingFile3.exists()); + assertThat(file.getFile()).isNotEqualTo(existingFile1); + assertThat(file.getFile()).isNotEqualTo(existingFile2); + assertThat(file.getFile()).isNotEqualTo(existingFile3); + assertThat(existingFile2.exists()).isTrue(); + assertThat(existingFile1.exists()).isTrue(); + assertThat(existingFile3.exists()).isFalse(); } @Test @@ -152,9 +148,9 @@ void purgeExpiredForReadFiles_whenCreatingNewOne() throws IOException { WritableFile file = folderManager.createWritableFile(); - assertFalse(expiredReadableFile.exists()); - assertTrue(expiredWritableFile.exists()); - assertNotEquals(expiredWritableFile, file.getFile()); + assertThat(expiredReadableFile.exists()).isFalse(); + assertThat(expiredWritableFile.exists()).isTrue(); + assertThat(file.getFile()).isNotEqualTo(expiredWritableFile); } @Test @@ -167,17 +163,17 @@ void closeExpiredReadableFileInUseIfAny_whenPurgingExpiredForReadFiles_whenCreat when(clock.now()).thenReturn(MILLISECONDS.toNanos(900 + MIN_FILE_AGE_FOR_READ_MILLIS)); ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(expiredReadableFileBeingRead, readableFile.getFile()); + assertThat(readableFile.getFile()).isEqualTo(expiredReadableFileBeingRead); when(clock.now()).thenReturn(MILLISECONDS.toNanos(11_500L)); WritableFile file = folderManager.createWritableFile(); - assertFalse(expiredReadableFile.exists()); - assertFalse(expiredReadableFileBeingRead.exists()); - assertTrue(expiredWritableFile.exists()); - assertNotEquals(expiredWritableFile, file.getFile()); - assertTrue(readableFile.isClosed()); + assertThat(expiredReadableFile.exists()).isFalse(); + assertThat(expiredReadableFileBeingRead.exists()).isFalse(); + assertThat(expiredWritableFile.exists()).isTrue(); + assertThat(file.getFile()).isNotEqualTo(expiredWritableFile); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -192,7 +188,7 @@ void provideFileForRead_afterItsMinFileAgeForReadTimePassed() throws IOException ReadableFile file = folderManager.getReadableFile(); - assertEquals(readableFile, file.getFile()); + assertThat(file.getFile()).isEqualTo(readableFile); } @Test @@ -209,12 +205,12 @@ void provideOldestFileForRead_whenMultipleReadableFilesAreAvailable() throws IOE ReadableFile file = folderManager.getReadableFile(); - assertEquals(readableFileOlder, file.getFile()); + assertThat(file.getFile()).isEqualTo(readableFileOlder); } @Test void provideNullFileForRead_whenNoFilesAreAvailable() throws IOException { - assertNull(folderManager.getReadableFile()); + assertThat(folderManager.getReadableFile()).isNull(); } @Test @@ -223,7 +219,7 @@ void provideNullFileForRead_whenOnlyReadableFilesAreAvailable() throws IOExcepti File writableFile = new File(rootDir, String.valueOf(currentTime)); createFiles(writableFile); - assertNull(folderManager.getReadableFile()); + assertThat(folderManager.getReadableFile()).isNull(); } @Test @@ -234,7 +230,7 @@ void provideNullFileForRead_whenReadableFilesAreExpired() throws IOException { createFiles(expiredReadableFile1, expiredReadableFile2); when(clock.now()).thenReturn(creationReferenceTime + MAX_FILE_AGE_FOR_READ_MILLIS); - assertNull(folderManager.getReadableFile()); + assertThat(folderManager.getReadableFile()).isNull(); } private static void fillWithBytes(File file, int size) throws IOException { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java index d96b9a1bc..b33387a8c 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java @@ -6,9 +6,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.storage; import static io.opentelemetry.contrib.disk.buffering.internal.storage.responses.ReadableResult.TRY_LATER; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -58,7 +57,7 @@ void tearDown() throws IOException { void whenReadingAndProcessingSuccessfully_returnSuccess() throws IOException { when(folderManager.getReadableFile()).thenReturn(readableFile); - assertEquals(ReadableResult.SUCCEEDED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.SUCCEEDED); verify(readableFile).readAndProcess(processing); } @@ -68,7 +67,7 @@ void whenReadableFileProcessingFails_returnTryLater() throws IOException { when(folderManager.getReadableFile()).thenReturn(readableFile); when(readableFile.readAndProcess(processing)).thenReturn(TRY_LATER); - assertEquals(TRY_LATER, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(TRY_LATER); verify(readableFile).readAndProcess(processing); } @@ -78,8 +77,8 @@ void whenReadingMultipleTimes_reuseReader() throws IOException { ReadableFile anotherReadable = mock(); when(folderManager.getReadableFile()).thenReturn(readableFile).thenReturn(anotherReadable); - assertEquals(ReadableResult.SUCCEEDED, storage.readAndProcess(processing)); - assertEquals(ReadableResult.SUCCEEDED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.SUCCEEDED); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.SUCCEEDED); verify(readableFile, times(2)).readAndProcess(processing); verify(folderManager, times(1)).getReadableFile(); @@ -103,18 +102,18 @@ void whenWritingMultipleTimes_reuseWriter() throws IOException { @Test void whenAttemptingToReadAfterClosed_returnFailed() throws IOException { storage.close(); - assertEquals(ReadableResult.FAILED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.FAILED); } @Test void whenAttemptingToWriteAfterClosed_returnFalse() throws IOException { storage.close(); - assertFalse(storage.write(new ByteArraySerializer(new byte[1]))); + assertThat(storage.write(new ByteArraySerializer(new byte[1]))).isFalse(); } @Test void whenNoFileAvailableForReading_returnFailed() throws IOException { - assertEquals(ReadableResult.FAILED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.FAILED); } @Test @@ -152,7 +151,7 @@ void whenEveryNewFileFoundCannotBeRead_returnContentNotAvailable() throws IOExce when(folderManager.getReadableFile()).thenReturn(readableFile); when(readableFile.readAndProcess(processing)).thenReturn(ReadableResult.FAILED); - assertEquals(ReadableResult.FAILED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.FAILED); verify(folderManager, times(3)).getReadableFile(); } @@ -215,7 +214,7 @@ void whenEveryAttemptToWriteFails_returnFalse() throws IOException { when(folderManager.createWritableFile()).thenReturn(writableFile); when(writableFile.append(data)).thenReturn(WritableResult.FAILED); - assertFalse(storage.write(data)); + assertThat(storage.write(data)).isFalse(); verify(folderManager, times(3)).createWritableFile(); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java index a9d0eb5da..8fdc1d41e 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java @@ -8,10 +8,8 @@ import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_AGE_FOR_READ_MILLIS; import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.getConfiguration; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -120,27 +118,27 @@ private static void addFileContents(File source) throws IOException { void readSingleItemAndRemoveIt() throws IOException { readableFile.readAndProcess( bytes -> { - assertEquals(FIRST_LOG_RECORD, deserialize(bytes)); + assertThat(deserialize(bytes)).isEqualTo(FIRST_LOG_RECORD); return ProcessResult.SUCCEEDED; }); List logs = getRemainingDataAndClose(readableFile); - assertEquals(2, logs.size()); - assertEquals(SECOND_LOG_RECORD, logs.get(0)); - assertEquals(THIRD_LOG_RECORD, logs.get(1)); + assertThat(logs.size()).isEqualTo(2); + assertThat(logs.get(0)).isEqualTo(SECOND_LOG_RECORD); + assertThat(logs.get(1)).isEqualTo(THIRD_LOG_RECORD); } @Test void whenProcessingSucceeds_returnSuccessStatus() throws IOException { - assertEquals( - ReadableResult.SUCCEEDED, readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.SUCCEEDED); } @Test void whenProcessingFails_returnTryLaterStatus() throws IOException { - assertEquals( - ReadableResult.TRY_LATER, readableFile.readAndProcess(bytes -> ProcessResult.TRY_LATER)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.TRY_LATER)) + .isEqualTo(ReadableResult.TRY_LATER); } @Test @@ -158,8 +156,8 @@ void readMultipleLinesAndRemoveThem() throws IOException { List logs = getRemainingDataAndClose(readableFile); - assertEquals(1, logs.size()); - assertEquals(THIRD_LOG_RECORD, logs.get(0)); + assertThat(logs.size()).isEqualTo(1); + assertThat(logs.get(0)).isEqualTo(THIRD_LOG_RECORD); } @Test @@ -168,24 +166,24 @@ void whenConsumerReturnsFalse_doNotRemoveLineFromSource() throws IOException { List logs = getRemainingDataAndClose(readableFile); - assertEquals(3, logs.size()); + assertThat(logs.size()).isEqualTo(3); } @Test void whenReadingLastLine_deleteOriginalFile_and_close() throws IOException { getRemainingDataAndClose(readableFile); - assertFalse(source.exists()); - assertTrue(readableFile.isClosed()); + assertThat(source.exists()).isFalse(); + assertThat(readableFile.isClosed()).isTrue(); } @Test void whenTheFileContentIsInvalid_deleteOriginalFile_and_close() throws IOException { - assertEquals( - ReadableResult.FAILED, readableFile.readAndProcess(bytes -> ProcessResult.CONTENT_INVALID)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.CONTENT_INVALID)) + .isEqualTo(ReadableResult.FAILED); - assertFalse(source.exists()); - assertTrue(readableFile.isClosed()); + assertThat(source.exists()).isFalse(); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -199,11 +197,11 @@ void whenNoMoreLinesAvailableToRead_deleteOriginalFile_close_and_returnNoContent ReadableFile emptyReadableFile = new ReadableFile(emptyFile, CREATED_TIME_MILLIS, clock, getConfiguration(dir)); - assertEquals( - ReadableResult.FAILED, emptyReadableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(emptyReadableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.FAILED); - assertTrue(emptyReadableFile.isClosed()); - assertFalse(emptyFile.exists()); + assertThat(emptyReadableFile.isClosed()).isTrue(); + assertThat(emptyFile.exists()).isFalse(); } @Test @@ -214,10 +212,10 @@ void whenNoMoreLinesAvailableToRead_deleteOriginalFile_close_and_returnNoContent when(clock.now()) .thenReturn(MILLISECONDS.toNanos(CREATED_TIME_MILLIS + MAX_FILE_AGE_FOR_READ_MILLIS)); - assertEquals( - ReadableResult.FAILED, readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.FAILED); - assertTrue(readableFile.isClosed()); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -225,14 +223,14 @@ void whenReadingAfterClosed_returnFailedStatus() throws IOException { readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED); readableFile.close(); - assertEquals( - ReadableResult.FAILED, readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.FAILED); } private static void assertDeserializedData(LogRecordData expected, byte[] bytes) { try { List deserialized = DESERIALIZER.deserialize(bytes); - assertEquals(expected, deserialized.get(0)); + assertThat(deserialized.get(0)).isEqualTo(expected); } catch (DeserializationException e) { throw new RuntimeException(e); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java index cae1e9f64..91ec94f09 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java @@ -8,9 +8,7 @@ import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_AGE_FOR_WRITE_MILLIS; import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_SIZE; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -58,14 +56,14 @@ void tearDown() throws IOException { void hasNotExpired_whenWriteAgeHasNotExpired() { when(clock.now()).thenReturn(MILLISECONDS.toNanos(1500L)); - assertFalse(writableFile.hasExpired()); + assertThat(writableFile.hasExpired()).isFalse(); } @Test void hasExpired_whenWriteAgeHasExpired() { when(clock.now()).thenReturn(MILLISECONDS.toNanos(2000L)); - assertTrue(writableFile.hasExpired()); + assertThat(writableFile.hasExpired()).isTrue(); } @Test @@ -78,22 +76,22 @@ void appendDataInNewLines_andIncreaseSize() throws IOException { List lines = getWrittenLines(); - assertEquals(2, lines.size()); - assertEquals("First line", lines.get(0)); - assertEquals("Second line", lines.get(1)); - assertEquals(line1.length + line2.length, writableFile.getSize()); + assertThat(lines).hasSize(2); + assertThat(lines.get(0)).isEqualTo("First line"); + assertThat(lines.get(1)).isEqualTo("Second line"); + assertThat(writableFile.getSize()).isEqualTo(line1.length + line2.length); } @Test void whenAppendingData_andNotEnoughSpaceIsAvailable_closeAndReturnFailed() throws IOException { - assertEquals( - WritableResult.SUCCEEDED, - writableFile.append(new ByteArraySerializer(new byte[MAX_FILE_SIZE]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[MAX_FILE_SIZE]))) + .isEqualTo(WritableResult.SUCCEEDED); - assertEquals(WritableResult.FAILED, writableFile.append(new ByteArraySerializer(new byte[1]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[1]))) + .isEqualTo(WritableResult.FAILED); - assertEquals(1, getWrittenLines().size()); - assertEquals(MAX_FILE_SIZE, writableFile.getSize()); + assertThat(getWrittenLines()).hasSize(1); + assertThat(writableFile.getSize()).isEqualTo(MAX_FILE_SIZE); } @Test @@ -102,9 +100,10 @@ void whenAppendingData_andHasExpired_closeAndReturnExpiredStatus() throws IOExce when(clock.now()) .thenReturn(MILLISECONDS.toNanos(CREATED_TIME_MILLIS + MAX_FILE_AGE_FOR_WRITE_MILLIS)); - assertEquals(WritableResult.FAILED, writableFile.append(new ByteArraySerializer(new byte[1]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[1]))) + .isEqualTo(WritableResult.FAILED); - assertEquals(1, getWrittenLines().size()); + assertThat(getWrittenLines()).hasSize(1); } @Test @@ -112,7 +111,8 @@ void whenAppendingData_andIsAlreadyClosed_returnFailedStatus() throws IOExceptio writableFile.append(new ByteArraySerializer(new byte[1])); writableFile.close(); - assertEquals(WritableResult.FAILED, writableFile.append(new ByteArraySerializer(new byte[2]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[2]))) + .isEqualTo(WritableResult.FAILED); } private static byte[] getByteArrayLine(String line) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java index 1d801db7b..c2ad06f28 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java @@ -61,7 +61,7 @@ void truncateTop() throws IOException { // Truncate all available data stream.truncateTop(3); - assertThat(stream.size()).isEqualTo(0); + assertThat(stream).isEmpty(); assertThat(readString(temporaryFile)).isEqualTo(""); stream.close(); diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java index 15c32c421..ec69e8024 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java @@ -131,5 +131,24 @@ private static LongExemplarData makeLongExemplarData(TraceFlags flags) { return ImmutableLongExemplarData.create(ATTRIBUTES, 100L, context, 1L); } + @NotNull + public static byte[] makeTooShortSignalBinary() { + return new byte[] { + (byte) 0x0A, // type + (byte) 0xFF, // defining length 255, but message is shorter + (byte) 0x01 // content + }; + } + + @NotNull + public static byte[] makeMalformedSignalBinary() { + return new byte[] { + (byte) 0x0A, // type + (byte) 0x02, // length + (byte) 0x08, // field 1, wire type 0 (varint) - this should be a nested message but isn't + (byte) 0x01 // content + }; + } + private TestData() {} } diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-aws-xray.txt b/docs/apidiffs/current_vs_latest/opentelemetry-aws-xray.txt new file mode 100644 index 000000000..fb005385c --- /dev/null +++ b/docs/apidiffs/current_vs_latest/opentelemetry-aws-xray.txt @@ -0,0 +1,2 @@ +Comparing source compatibility of opentelemetry-aws-xray-1.50.0-SNAPSHOT.jar against opentelemetry-aws-xray-1.49.0.jar +No changes. \ No newline at end of file diff --git a/docs/style-guide.md b/docs/style-guide.md new file mode 100644 index 000000000..9acf641ae --- /dev/null +++ b/docs/style-guide.md @@ -0,0 +1,166 @@ +# Style Guide + +This project follows the +[Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). + +## Code Formatting + +### Auto-formatting + +The build will fail if source code is not formatted according to Google Java Style. + +Run the following command to reformat all files: + +```bash +./gradlew spotlessApply +``` + +For IntelliJ users, an `.editorconfig` file is provided that IntelliJ will automatically use to +adjust code formatting settings. However, it does not support all required rules, so you may still +need to run `./gradlew spotlessApply` periodically. + +### Static imports + +Consider statically importing the following commonly used methods and constants: + +- **Test methods** + - `io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.*` + - `org.assertj.core.api.Assertions.*` + - `org.mockito.Mockito.*` + - `org.mockito.ArgumentMatchers.*` +- **Utility methods** + - `io.opentelemetry.api.common.AttributeKey.*` + - `java.util.Arrays` - asList, stream + - `java.util.Collections` - singleton*, empty*, unmodifiable*, synchronized*, checked* + - `java.util.Objects` - requireNonNull + - `java.util.function.Function` - identity + - `java.util.stream.Collectors.*` +- **Utility constants** + - `java.util.Locale.*` + - `java.util.concurrent.TimeUnit.*` + - `java.util.logging.Level.*` + - `java.nio.charset.StandardCharsets.*` +- **OpenTelemetry semantic convention constants** + - All constants under `io.opentelemetry.semconv.**`, except for + `io.opentelemetry.semconv.SchemaUrls.*` constants. + +### Class organization + +Prefer this order: + +- Static fields (final before non-final) +- Instance fields (final before non-final) +- Constructors +- Methods +- Nested classes + +**Method ordering**: Place calling methods above the methods they call. For example, place private +methods below the non-private methods that use them. + +**Static utility classes**: Place the private constructor (used to prevent instantiation) after all +methods. + +## Java Language Conventions + +### Visibility modifiers + +Follow the principle of minimal necessary visibility. Use the most restrictive access modifier that +still allows the code to function correctly. + +### Internal packages + +Classes in `.internal` packages are not considered public API and may change without notice. These +packages contain implementation details that should not be used by external consumers. + +- Use `.internal` packages for implementation classes that need to be public within the module but + should not be used externally +- Try to avoid referencing `.internal` classes from other modules + +### `final` keyword usage + +Public non-internal non-test classes should be declared `final` where possible. + +Methods should only be declared `final` if they are in public non-internal non-test non-final classes. + +Fields should be declared `final` where possible. + +Method parameters and local variables should never be declared `final`. + +### `@Nullable` annotation usage + +**Note: This section is aspirational and may not reflect the current codebase.** + +Annotate all parameters and fields that can be `null` with `@Nullable` (specifically +`javax.annotation.Nullable`, which is included by the `otel.java-conventions` Gradle plugin as a +`compileOnly` dependency). + +`@NonNull` is unnecessary as it is the default. + +**Defensive programming**: Public APIs should still check for `null` parameters even if not +annotated with `@Nullable`. Internal APIs do not need these checks. + +### `Optional` usage + +Following the reasoning from +[Writing a Java library with better experience (slide 12)](https://speakerdeck.com/trustin/writing-a-java-library-with-better-experience?slide=12), +`java.util.Optional` usage is kept to a minimum. + +**Guidelines**: + +- `Optional` shouldn't appear in public API signatures +- Avoid `Optional` on the hot path (instrumentation code), unless the instrumented library uses it + +## Tooling conventions + +### AssertJ + +Prefer AssertJ assertions over JUnit assertions (assertEquals, assertTrue, etc.) for better error +messages. + +### JUnit + +Test classes and test methods should generally be package-protected (no explicit visibility +modifier) rather than `public`. This follows the principle of minimal necessary visibility and is +sufficient for JUnit to discover and execute tests. + +### Gradle + +- Use Kotlin instead of Groovy for build scripts +- Plugin versions should be specified in `settings.gradle.kts`, not in individual modules +- All modules should use `plugins { id("otel.java-conventions") }` +- Set module names with `otelJava.moduleName.set("io.opentelemetry.contrib.mymodule")` + +## Configuration + +- Use `otel.` prefix for all configuration property keys +- Read configuration via the `ConfigProperties` interface +- Provide sensible defaults and document all options +- Validate configuration early with clear error messages + +## Performance + +Avoid allocations on the hot path (instrumentation code) whenever possible. This includes `Iterator` +allocations from collections; note that `for (SomeType t : plainJavaArray)` does not allocate an +iterator object. + +Non-allocating Stream API usage on the hot path is acceptable but may not fit the surrounding code +style; this is a judgment call. Some Stream APIs make efficient allocation difficult (e.g., +`collect` with pre-sized sink data structures involves convoluted `Supplier` code, or lambdas passed +to `forEach` may be capturing/allocating lambdas). + +## Documentation + +### Component README files + +- Include a component owners section in each module's README +- Document configuration options with examples + +### Deprecation and breaking changes + +Breaking changes are allowed in unstable modules (published with `-alpha` version suffix). + +1. Mark APIs with `@Deprecated` and a removal timeline (there must be at least one release with the + API marked as deprecated before removing it) +2. Document the replacement in Javadoc with `@deprecated` tag +3. Note the migration path for breaking changes under a "Migration notes" section of CHANGELOG.md + (create this section at the top of the Unreleased section if not already present) diff --git a/example/README.md b/example/README.md deleted file mode 100644 index 43333d2c2..000000000 --- a/example/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Example Library - -This is an example library intended to be used as a template for easy additions to the OpenTelemetry Java Contrib project. diff --git a/example/build.gradle.kts b/example/build.gradle.kts deleted file mode 100644 index 898191643..000000000 --- a/example/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -plugins { - id("otel.java-conventions") -} - -description = "An example OpenTelemetry Java Contrib library" - -tasks { - jar { - manifest { - attributes["Main-Class"] = "io.opentelemetry.contrib.example.Library" - } - } -} diff --git a/example/src/main/java/io/opentelemetry/contrib/example/Library.java b/example/src/main/java/io/opentelemetry/contrib/example/Library.java deleted file mode 100644 index 289f72ea8..000000000 --- a/example/src/main/java/io/opentelemetry/contrib/example/Library.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.example; - -public class Library { - - public boolean myMethod() { - return true; - } - - @SuppressWarnings("SystemOut") - public static void main(String... args) { - System.out.println("ExampleLibrary.main"); - } -} diff --git a/example/src/test/java/io/opentelemetry/contrib/example/LibraryTest.java b/example/src/test/java/io/opentelemetry/contrib/example/LibraryTest.java deleted file mode 100644 index a9c897576..000000000 --- a/example/src/test/java/io/opentelemetry/contrib/example/LibraryTest.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.example; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -class LibraryTest { - - @Test - void myMethod() { - Library library = new Library(); - assertThat(library.myMethod()).isTrue(); - } -} diff --git a/gcp-auth-extension/build.gradle.kts b/gcp-auth-extension/build.gradle.kts index 21b816f0c..77625afde 100644 --- a/gcp-auth-extension/build.gradle.kts +++ b/gcp-auth-extension/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-exporter-otlp") // Only dependencies added to `implementation` configuration will be picked up by Shadow plugin - implementation("com.google.auth:google-auth-library-oauth2-http:1.37.1") + implementation("com.google.auth:google-auth-library-oauth2-http:1.39.0") // Test dependencies testCompileOnly("com.google.auto.service:auto-service-annotations") @@ -46,7 +46,7 @@ dependencies { testImplementation("org.mockito:mockito-inline") testImplementation("org.mockito:mockito-junit-jupiter") testImplementation("org.mock-server:mockserver-netty:5.15.0") - testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") testImplementation("org.springframework.boot:spring-boot-starter-web:2.7.18") testImplementation("org.springframework.boot:spring-boot-starter:2.7.18") testImplementation("org.springframework.boot:spring-boot-starter-test:2.7.18") @@ -107,6 +107,9 @@ tasks.register("copyAgent") { } tasks.register("IntegrationTestUserCreds") { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + dependsOn(tasks.shadowJar) dependsOn(tasks.named("copyAgent")) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java index 572baa8b8..c1f3826de 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java @@ -5,9 +5,10 @@ package io.opentelemetry.contrib.gcp.auth; +import static java.util.Locale.ROOT; + import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import java.util.Locale; import java.util.function.BiFunction; import javax.annotation.Nullable; @@ -60,8 +61,7 @@ enum ConfigurableOption { ConfigurableOption(String userReadableName) { this.userReadableName = userReadableName; this.environmentVariableName = this.name(); - this.systemPropertyName = - this.environmentVariableName.toLowerCase(Locale.ROOT).replace('_', '.'); + this.systemPropertyName = this.environmentVariableName.toLowerCase(ROOT).replace('_', '.'); } /** diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index 5b3cc925d..6141a32e1 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -5,6 +5,11 @@ package io.opentelemetry.contrib.gcp.auth; +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toMap; + import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; import com.google.common.annotations.VisibleForTesting; @@ -33,7 +38,6 @@ import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; import javax.annotation.Nonnull; /** @@ -227,17 +231,16 @@ static Map getRequiredHeaderMap( } catch (IOException e) { throw new GoogleAuthException(Reason.FAILED_ADC_REFRESH, e); } - // flatten list Map flattenedHeaders = gcpHeaders.entrySet().stream() .collect( - Collectors.toMap( + toMap( Map.Entry::getKey, entry -> entry.getValue().stream() .filter(Objects::nonNull) // Filter nulls .filter(s -> !s.isEmpty()) // Filter empty strings - .collect(Collectors.joining(",")))); + .collect(joining(",")))); // Add quota user project header if not detected by the auth library and user provided it via // system properties. if (!flattenedHeaders.containsKey(QUOTA_USER_PROJECT_HEADER)) { @@ -260,7 +263,7 @@ private static Resource customizeResource(Resource resource, ConfigProperties co Resource res = Resource.create( Attributes.of( - AttributeKey.stringKey(GCP_USER_PROJECT_ID_KEY), getProjectId(configProperties))); + stringKey(GCP_USER_PROJECT_ID_KEY), getProjectId(configProperties))); return resource.merge(res); } diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java index 4fb687925..d7a4f07fd 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java @@ -11,9 +11,10 @@ import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_METRICS; import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_TRACES; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; @@ -127,7 +128,7 @@ public void setup() { // TODO: Use parameterized test for testing traces customizer for http & grpc. @Test - public void testTraceCustomizerOtlpHttp() { + void testTraceCustomizerOtlpHttp() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -135,15 +136,15 @@ public void testTraceCustomizerOtlpHttp() { ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty(), SIGNAL_TYPE_TRACES); // Prepare mocks prepareMockBehaviorForGoogleCredentials(); - OtlpHttpSpanExporter mockOtlpHttpSpanExporter = Mockito.mock(OtlpHttpSpanExporter.class); + OtlpHttpSpanExporter mockOtlpHttpSpanExporter = mock(OtlpHttpSpanExporter.class); OtlpHttpSpanExporterBuilder otlpSpanExporterBuilder = OtlpHttpSpanExporter.builder(); OtlpHttpSpanExporterBuilder spyOtlpHttpSpanExporterBuilder = Mockito.spy(otlpSpanExporterBuilder); - Mockito.when(spyOtlpHttpSpanExporterBuilder.build()).thenReturn(mockOtlpHttpSpanExporter); + when(spyOtlpHttpSpanExporterBuilder.build()).thenReturn(mockOtlpHttpSpanExporter); - Mockito.when(mockOtlpHttpSpanExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + when(mockOtlpHttpSpanExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); List exportedSpans = new ArrayList<>(); - Mockito.when(mockOtlpHttpSpanExporter.export(Mockito.anyCollection())) + when(mockOtlpHttpSpanExporter.export(any())) .thenAnswer( invocationOnMock -> { exportedSpans.addAll(invocationOnMock.getArgument(0)); @@ -162,12 +163,12 @@ public void testTraceCustomizerOtlpHttp() { generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpHttpSpanExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpHttpSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); - assertEquals(2, traceHeaderSupplierCaptor.getValue().get().size()); + assertThat(traceHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(traceHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -189,7 +190,7 @@ public void testTraceCustomizerOtlpHttp() { } @Test - public void testTraceCustomizerOtlpGrpc() { + void testTraceCustomizerOtlpGrpc() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -215,12 +216,12 @@ public void testTraceCustomizerOtlpGrpc() { generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpGrpcSpanExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpGrpcSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); - assertEquals(2, traceHeaderSupplierCaptor.getValue().get().size()); + assertThat(traceHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(traceHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -243,7 +244,7 @@ public void testTraceCustomizerOtlpGrpc() { // TODO: Use parameterized test for testing metrics customizer for http & grpc. @Test - public void testMetricCustomizerOtlpHttp() { + void testMetricCustomizerOtlpHttp() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -271,12 +272,12 @@ public void testMetricCustomizerOtlpHttp() { generateTestMetric(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpHttpMetricExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpHttpMetricExporterBuilder, Mockito.times(1)) .setHeaders(metricHeaderSupplierCaptor.capture()); - assertEquals(2, metricHeaderSupplierCaptor.getValue().get().size()); + assertThat(metricHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(metricHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -304,7 +305,7 @@ public void testMetricCustomizerOtlpHttp() { } @Test - public void testMetricCustomizerOtlpGrpc() { + void testMetricCustomizerOtlpGrpc() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -332,12 +333,12 @@ public void testMetricCustomizerOtlpGrpc() { generateTestMetric(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpGrpcMetricExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpGrpcMetricExporterBuilder, Mockito.times(1)) .setHeaders(metricHeaderSupplierCaptor.capture()); - assertEquals(2, metricHeaderSupplierCaptor.getValue().get().size()); + assertThat(metricHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(metricHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -365,7 +366,7 @@ public void testMetricCustomizerOtlpGrpc() { } @Test - public void testCustomizerFailWithMissingResourceProject() { + void testCustomizerFailWithMissingResourceProject() { System.setProperty( ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty(), SIGNAL_TYPE_ALL); OtlpGrpcSpanExporter mockOtlpGrpcSpanExporter = Mockito.mock(OtlpGrpcSpanExporter.class); @@ -375,16 +376,15 @@ public void testCustomizerFailWithMissingResourceProject() { .when(GoogleCredentials::getApplicationDefault) .thenReturn(mockedGoogleCredentials); - assertThrows( - ConfigurationException.class, - () -> buildOpenTelemetrySdkWithExporter(mockOtlpGrpcSpanExporter)); + assertThatThrownBy(() -> buildOpenTelemetrySdkWithExporter(mockOtlpGrpcSpanExporter)) + .isInstanceOf(ConfigurationException.class); } } @ParameterizedTest @MethodSource("provideQuotaBehaviorTestCases") @SuppressWarnings("CannotMockMethod") - public void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws IOException { + void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws IOException { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -437,7 +437,7 @@ public void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(spyOtlpGrpcSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); @@ -458,7 +458,7 @@ public void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws @ParameterizedTest @MethodSource("provideTargetSignalBehaviorTestCases") - public void testTargetSignalsBehavior(TargetSignalBehavior testCase) { + void testTargetSignalsBehavior(TargetSignalBehavior testCase) { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -506,14 +506,14 @@ public void testTargetSignalsBehavior(TargetSignalBehavior testCase) { generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); // Check Traces modification conditions if (testCase.getExpectedIsTraceSignalModified()) { // If traces signal is expected to be modified, auth headers must be present Mockito.verify(spyOtlpGrpcSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); - assertEquals(2, traceHeaderSupplierCaptor.getValue().get().size()); + assertThat(traceHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(traceHeaderSupplierCaptor.getValue().get())) .isTrue(); } else { @@ -527,7 +527,7 @@ public void testTargetSignalsBehavior(TargetSignalBehavior testCase) { // If metrics signal is expected to be modified, auth headers must be present Mockito.verify(spyOtlpGrpcMetricExporterBuilder, Mockito.times(1)) .setHeaders(metricHeaderSupplierCaptor.capture()); - assertEquals(2, metricHeaderSupplierCaptor.getValue().get().size()); + assertThat(metricHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(metricHeaderSupplierCaptor.getValue().get())) .isTrue(); } else { diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java index e04baed93..f87762474 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java @@ -7,9 +7,8 @@ import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.GCP_USER_PROJECT_ID_KEY; import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.QUOTA_USER_PROJECT_HEADER; +import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; import static org.mockserver.stop.Stop.stopQuietly; @@ -51,7 +50,7 @@ @SpringBootTest( classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) -public class GcpAuthExtensionEndToEndTest { +class GcpAuthExtensionEndToEndTest { @LocalServerPort private int testApplicationPort; // port at which the spring app is running @@ -115,7 +114,7 @@ public static void teardown() { } @Test - public void authExtensionSmokeTest() { + void authExtensionSmokeTest() { template.getForEntity( URI.create("http://localhost:" + testApplicationPort + "/ping"), String.class); @@ -160,24 +159,22 @@ public X509Certificate[] getAcceptedIssuers() { private static void verifyResourceAttributes(List extractedResourceSpans) { extractedResourceSpans.forEach( resourceSpan -> - assertTrue( - resourceSpan - .getResource() - .getAttributesList() - .contains( - KeyValue.newBuilder() - .setKey(GCP_USER_PROJECT_ID_KEY) - .setValue(AnyValue.newBuilder().setStringValue(DUMMY_GCP_PROJECT)) - .build()))); + assertThat(resourceSpan.getResource().getAttributesList()) + .contains( + KeyValue.newBuilder() + .setKey(GCP_USER_PROJECT_ID_KEY) + .setValue(AnyValue.newBuilder().setStringValue(DUMMY_GCP_PROJECT)) + .build())); } private static void verifyRequestHeaders(List extractedHeaders) { - assertFalse(extractedHeaders.isEmpty()); + assertThat(extractedHeaders).isNotEmpty(); // verify if extension added the required headers extractedHeaders.forEach( headers -> { - assertTrue(headers.containsEntry(QUOTA_USER_PROJECT_HEADER, DUMMY_GCP_QUOTA_PROJECT)); - assertTrue(headers.containsEntry("Authorization", "Bearer fake.access_token")); + assertThat(headers.containsEntry(QUOTA_USER_PROJECT_HEADER, DUMMY_GCP_QUOTA_PROJECT)) + .isTrue(); + assertThat(headers.containsEntry("Authorization", "Bearer fake.access_token")).isTrue(); }); } diff --git a/gcp-resources/README.md b/gcp-resources/README.md index 6a80e1baf..9f670e088 100644 --- a/gcp-resources/README.md +++ b/gcp-resources/README.md @@ -47,7 +47,7 @@ env: ## Usage with Manual Instrumentation -It is recommended to use this resource detector with the [OpenTelemetry Autoconfiguration SPI](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#resource-provider-spi). The GCP resource detector automatically provides the detected resources via the [autoconfigure-spi](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure-spi) SDK extension. +It is recommended to use this resource detector with the [OpenTelemetry SDK autoconfiguration](https://opentelemetry.io/docs/languages/java/configuration/#zero-code-sdk-autoconfigure). The GCP resource detector automatically provides the detected resources via the [autoconfigure-spi](https://opentelemetry.io/docs/languages/java/configuration/#spi-service-provider-interface) SDK extension. For a reference example showcasing the detected resource attributes and usage with `autoconfigure-spi`, see the [Resource detection example](https://github.com/open-telemetry/opentelemetry-java-examples/tree/main/resource-detection-gcp). diff --git a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java index b7e49c1a9..4b92ade57 100644 --- a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java +++ b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java @@ -65,6 +65,7 @@ public class GCPResourceProvider implements ConditionalResourceProvider { private static final Logger LOGGER = Logger.getLogger(GCPResourceProvider.class.getSimpleName()); + private final GCPPlatformDetector detector; // for testing only diff --git a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java index 745d440fd..2f0f937f0 100644 --- a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java +++ b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java @@ -13,8 +13,6 @@ */ class IncubatingAttributes { - private IncubatingAttributes() {} - public static final AttributeKey CLOUD_ACCOUNT_ID = AttributeKey.stringKey("cloud.account.id"); public static final AttributeKey CLOUD_AVAILABILITY_ZONE = @@ -26,7 +24,6 @@ private IncubatingAttributes() {} public static final AttributeKey CLOUD_REGION = AttributeKey.stringKey("cloud.region"); public static final class CloudPlatformIncubatingValues { - private CloudPlatformIncubatingValues() {} public static final String GCP_COMPUTE_ENGINE = "gcp_compute_engine"; public static final String GCP_CLOUD_RUN = "gcp_cloud_run"; @@ -34,6 +31,8 @@ private CloudPlatformIncubatingValues() {} public static final String GCP_CLOUD_FUNCTIONS = "gcp_cloud_functions"; public static final String GCP_APP_ENGINE = "gcp_app_engine"; public static final String GCP = "gcp"; + + private CloudPlatformIncubatingValues() {} } public static final AttributeKey FAAS_INSTANCE = AttributeKey.stringKey("faas.instance"); @@ -56,4 +55,6 @@ private CloudPlatformIncubatingValues() {} public static final AttributeKey K8S_CLUSTER_NAME = AttributeKey.stringKey("k8s.cluster.name"); + + private IncubatingAttributes() {} } diff --git a/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java b/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java index 9b17b22d2..9314a1b67 100644 --- a/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java +++ b/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java @@ -52,7 +52,7 @@ import static io.opentelemetry.semconv.incubating.HostIncubatingAttributes.HOST_NAME; import static io.opentelemetry.semconv.incubating.HostIncubatingAttributes.HOST_TYPE; import static io.opentelemetry.semconv.incubating.K8sIncubatingAttributes.K8S_CLUSTER_NAME; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.verify; import com.google.cloud.opentelemetry.detection.DetectedPlatform; @@ -186,7 +186,7 @@ private static DetectedPlatform generateMockUnknownPlatform() { } @Test - public void testGceResourceAttributesMapping() { + void testGceResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGcePlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -210,7 +210,7 @@ public void testGceResourceAttributesMapping() { } @Test - public void testGkeResourceAttributesMapping_LocationTypeRegion() { + void testGkeResourceAttributesMapping_LocationTypeRegion() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGkePlatform(GKE_LOCATION_TYPE_REGION); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -227,7 +227,7 @@ public void testGkeResourceAttributesMapping_LocationTypeRegion() { } @Test - public void testGkeResourceAttributesMapping_LocationTypeZone() { + void testGkeResourceAttributesMapping_LocationTypeZone() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGkePlatform(GKE_LOCATION_TYPE_ZONE); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -245,7 +245,7 @@ public void testGkeResourceAttributesMapping_LocationTypeZone() { } @Test - public void testGkeResourceAttributesMapping_LocationTypeInvalid() { + void testGkeResourceAttributesMapping_LocationTypeInvalid() { Map mockGKEAttributes = new HashMap<>(mockGKECommonAttributes); mockGKEAttributes.put(GKE_CLUSTER_LOCATION_TYPE, "INVALID"); mockGKEAttributes.put(GKE_CLUSTER_LOCATION, "some-location"); @@ -270,7 +270,7 @@ public void testGkeResourceAttributesMapping_LocationTypeInvalid() { } @Test - public void testGkeResourceAttributesMapping_LocationMissing() { + void testGkeResourceAttributesMapping_LocationMissing() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGkePlatform(""); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -295,7 +295,7 @@ private static void verifyGkeMapping(Resource gotResource, DetectedPlatform dete } @Test - public void testGcrServiceResourceAttributesMapping() { + void testGcrServiceResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockServerlessPlatform(GCPPlatformDetector.SupportedPlatform.GOOGLE_CLOUD_RUN); @@ -312,7 +312,7 @@ public void testGcrServiceResourceAttributesMapping() { } @Test - public void testGcfResourceAttributeMapping() { + void testGcfResourceAttributeMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockServerlessPlatform( @@ -343,7 +343,7 @@ private static void verifyServerlessMapping( } @Test - public void testGcrJobResourceAttributesMapping() { + void testGcrJobResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGcrJobPlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -368,7 +368,7 @@ public void testGcrJobResourceAttributesMapping() { } @Test - public void testGaeResourceAttributeMapping() { + void testGaeResourceAttributeMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGaePlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -390,7 +390,7 @@ public void testGaeResourceAttributeMapping() { } @Test - public void testUnknownPlatformResourceAttributesMapping() { + void testUnknownPlatformResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockUnknownPlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -400,7 +400,7 @@ public void testUnknownPlatformResourceAttributesMapping() { } @Test - public void findsWithServiceLoader() { + void findsWithServiceLoader() { ServiceLoader services = ServiceLoader.load(ResourceProvider.class, getClass().getClassLoader()); while (services.iterator().hasNext()) { diff --git a/gradle.properties b/gradle.properties index 0b5e135ed..bc596d5e4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,7 @@ org.gradle.parallel=true org.gradle.caching=true +org.gradle.configuration-cache=true +org.gradle.configuration-cache.parallel=true org.gradle.priority=low diff --git a/ibm-mq-metrics/build.gradle.kts b/ibm-mq-metrics/build.gradle.kts index 7e3afe148..2370f2893 100644 --- a/ibm-mq-metrics/build.gradle.kts +++ b/ibm-mq-metrics/build.gradle.kts @@ -31,10 +31,10 @@ val ibmClientJar: Configuration by configurations.creating { dependencies { api("com.google.code.findbugs:jsr305:3.0.2") api("io.swagger:swagger-annotations:1.6.16") - api("org.jetbrains:annotations:26.0.2") - api("com.ibm.mq:com.ibm.mq.allclient:9.4.3.0") - api("org.yaml:snakeyaml:2.4") - api("com.fasterxml.jackson.core:jackson-databind:2.19.2") + api("org.jetbrains:annotations:26.0.2-1") + api("com.ibm.mq:com.ibm.mq.allclient:9.4.3.1") + api("org.yaml:snakeyaml:2.5") + api("com.fasterxml.jackson.core:jackson-databind:2.20.0") api("io.opentelemetry:opentelemetry-sdk") api("io.opentelemetry:opentelemetry-exporter-otlp") api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") @@ -45,11 +45,11 @@ dependencies { integrationTestImplementation("org.assertj:assertj-core:3.27.4") integrationTestImplementation("org.junit.jupiter:junit-jupiter-api:5.13.4") integrationTestImplementation("io.opentelemetry:opentelemetry-sdk-testing") - integrationTestImplementation("com.ibm.mq:com.ibm.mq.jakarta.client:9.4.3.0") + integrationTestImplementation("com.ibm.mq:com.ibm.mq.jakarta.client:9.4.3.1") integrationTestImplementation("jakarta.jms:jakarta.jms-api:3.1.0") integrationTestImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.4") integrationTestRuntimeOnly("org.junit.platform:junit-platform-launcher:1.13.4") - ibmClientJar("com.ibm.mq:com.ibm.mq.allclient:9.4.3.0") { + ibmClientJar("com.ibm.mq:com.ibm.mq.allclient:9.4.3.1") { artifact { name = "com.ibm.mq.allclient" extension = "jar" @@ -60,7 +60,7 @@ dependencies { tasks.shadowJar { dependencies { - exclude(dependency("com.ibm.mq:com.ibm.mq.allclient:9.4.3.0")) + exclude(dependency("com.ibm.mq:com.ibm.mq.allclient:9.4.3.1")) } } diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java index 6ded88547..b3fafadb6 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java @@ -17,7 +17,7 @@ * authorization.
    * It also validates the arguments passed for various scenarios. */ -public class WmqContext { +public final class WmqContext { private static final String TRANSPORT_TYPE_CLIENT = "Client"; private static final String TRANSPORT_TYPE_BINDINGS = "Bindings"; diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java index 832527fb3..9611604cb 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java @@ -43,7 +43,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class WmqMonitor { +public final class WmqMonitor { private static final Logger logger = LoggerFactory.getLogger(WmqMonitor.class); diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java index f02f05cc0..862edd30a 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java @@ -12,7 +12,7 @@ import java.util.Set; /** A jackson databind class used for config. */ -public class ExcludeFilters { +public final class ExcludeFilters { private String type = "UNKNOWN"; private Set values = new HashSet<>(); diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java index 685840977..11769832f 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java @@ -10,7 +10,7 @@ /** This is a jackson databind class used purely for config. */ @JsonIgnoreProperties(ignoreUnknown = true) -public class QueueManager { +public final class QueueManager { @Nullable private String host; private int port = -1; diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java index 72a3a9f42..86a30360e 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java @@ -8,7 +8,7 @@ import java.util.HashSet; import java.util.Set; -public class ResourceFilters { +public final class ResourceFilters { private Set include = new HashSet<>(); private Set exclude = new HashSet<>(); diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java index 6ed74dad9..688f9541d 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java @@ -12,7 +12,7 @@ import com.ibm.mq.headers.pcf.PCFMessage; import java.time.Instant; -public class MessageBuddy { +public final class MessageBuddy { private MessageBuddy() {} diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java index cefa9e5d9..cf633b953 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java @@ -16,7 +16,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class WmqUtil { +public final class WmqUtil { private static final Logger logger = LoggerFactory.getLogger(WmqUtil.class); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java index a0e06e336..b9964537f 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java @@ -54,7 +54,7 @@ public void setup() throws Exception { } @Test - public void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { + void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { when(pcfMessageAgent.send(any(PCFMessage.class))) .thenReturn(createPCFResponseForInquireChannelCmd()); classUnderTest = new InquireChannelCmdCollector(meter); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java index 6170e31f4..ea46450d3 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java @@ -47,7 +47,7 @@ public void setup() throws Exception { } @Test - public void testPublishMetrics() throws Exception { + void testPublishMetrics() throws Exception { when(pcfMessageAgent.send(any(PCFMessage.class))) .thenReturn(createPCFResponseForInquireListenerStatusCmd()); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java index 25d173d3d..e6ddfae17 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java @@ -5,9 +5,10 @@ package io.opentelemetry.ibm.mq.metricscollector; +import static org.assertj.core.api.Assertions.assertThat; + import io.opentelemetry.sdk.metrics.data.LongPointData; import io.opentelemetry.sdk.metrics.data.MetricData; -import org.assertj.core.api.Assertions; public class MetricAssert { @@ -24,12 +25,12 @@ static MetricAssert assertThatMetric(MetricData metric, int pointOffset) { } MetricAssert hasName(String name) { - Assertions.assertThat(metric.getName()).isEqualTo(name); + assertThat(metric.getName()).isEqualTo(name); return this; } MetricAssert hasValue(long value) { - Assertions.assertThat( + assertThat( ((LongPointData) metric.getLongGaugeData().getPoints().toArray()[this.pointOffset]) .getValue()) .isEqualTo(value); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java index bd0c1ef97..5d18d73da 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java @@ -33,7 +33,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class QueueCollectionBuddyTest { +class QueueCollectionBuddyTest { @RegisterExtension static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java index dde400b02..3c6ef1503 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java @@ -51,7 +51,7 @@ public void setup() throws Exception { } @Test - public void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { + void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { when(pcfMessageAgent.send(any(PCFMessage.class))) .thenReturn(createPCFResponseForInquireQMgrStatusCmd()); classUnderTest = diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java index 865501573..646d4ee98 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java @@ -34,7 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class TopicMetricsCollectorTest { +class TopicMetricsCollectorTest { @RegisterExtension static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpans.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpans.java new file mode 100644 index 000000000..76f55db83 --- /dev/null +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpans.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.inferredspans; + +import java.time.Duration; +import javax.annotation.Nullable; + +/** + * A global accessor for the {@link InferredSpansProcessor} instance. + * + *

    This class is for internal use only and may be removed in a future release. + */ +public final class InferredSpans { + + @Nullable private static volatile InferredSpansProcessor instance; + + private InferredSpans() {} + + /** + * Sets the {@link InferredSpansProcessor} instance. + * + * @param processor the processor instance + */ + public static void setInstance(@Nullable InferredSpansProcessor processor) { + instance = processor; + } + + /** + * Returns whether inferred spans are enabled. + * + * @return whether inferred spans are enabled + */ + public static boolean isEnabled() { + return instance != null; + } + + /** + * Sets the profiler interval. + * + * @param interval the new profiler interval + */ + public static void setProfilerInterval(Duration interval) { + InferredSpansProcessor p = instance; + if (p != null) { + p.setProfilerInterval(interval); + } + } +} diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java index 9c8118ec5..7ee78943e 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.stream.Collectors.toList; + import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; @@ -17,7 +19,6 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.logging.Logger; -import java.util.stream.Collectors; import javax.annotation.Nullable; @AutoService(AutoConfigurationCustomizerProvider.class) @@ -117,7 +118,7 @@ void applyWildcards(String configKey, Consumer> fu Arrays.stream(wildcardListString.split(",")) .filter(str -> !str.isEmpty()) .map(WildcardMatcher::valueOf) - .collect(Collectors.toList()); + .collect(toList()); if (!values.isEmpty()) { funcToApply.accept(values); } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java index 22f59ba53..19baf3174 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.Objects.requireNonNull; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.api.trace.TracerProvider; @@ -19,7 +21,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.Objects; +import java.time.Duration; import java.util.Properties; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -33,14 +35,13 @@ public class InferredSpansProcessor implements SpanProcessor { private static final Logger logger = Logger.getLogger(InferredSpansProcessor.class.getName()); public static final String TRACER_NAME = "inferred-spans"; - public static final String TRACER_VERSION = readInferredSpansVersion(); // Visible for testing final SamplingProfiler profiler; + private final InferredSpansConfiguration config; private Supplier tracerProvider = GlobalOpenTelemetry::getTracerProvider; - @Nullable private volatile Tracer tracer; InferredSpansProcessor( @@ -49,12 +50,18 @@ public class InferredSpansProcessor implements SpanProcessor { boolean startScheduledProfiling, @Nullable File activationEventsFile, @Nullable File jfrFile) { + this.config = config; profiler = new SamplingProfiler(config, clock, this::getTracer, activationEventsFile, jfrFile); if (startScheduledProfiling) { profiler.start(); } } + public void setProfilerInterval(Duration interval) { + config.setProfilerInterval(interval); + profiler.reschedule(); + } + public static InferredSpansProcessorBuilder builder() { return new InferredSpansProcessorBuilder(); } @@ -134,7 +141,7 @@ private static String readInferredSpansVersion() { Properties properties = new Properties(); properties.load(is); String version = (String) properties.get("contrib.version"); - Objects.requireNonNull(version); + requireNonNull(version); return version; } catch (IOException e) { throw new IllegalStateException(e); diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java index b464f0f42..e8f52ed68 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.Arrays.asList; + import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.contrib.inferredspans.internal.CallTree; @@ -12,7 +14,6 @@ import io.opentelemetry.contrib.inferredspans.internal.SpanAnchoredClock; import java.io.File; import java.time.Duration; -import java.util.Arrays; import java.util.List; import java.util.function.BiConsumer; import javax.annotation.Nullable; @@ -27,7 +28,7 @@ public class InferredSpansProcessorBuilder { private Duration inferredSpansMinDuration = Duration.ZERO; private List includedClasses = WildcardMatcher.matchAllList(); private List excludedClasses = - Arrays.asList( + asList( WildcardMatcher.caseSensitiveMatcher("java.*"), WildcardMatcher.caseSensitiveMatcher("javax.*"), WildcardMatcher.caseSensitiveMatcher("sun.*"), @@ -43,13 +44,11 @@ public class InferredSpansProcessorBuilder { WildcardMatcher.caseSensitiveMatcher("io.undertow.*")); private Duration profilerInterval = Duration.ofSeconds(5); private Duration profilingDuration = Duration.ofSeconds(5); - @Nullable private String profilerLibDirectory = null; // The following options are only intended to be modified in tests private SpanAnchoredClock clock = new SpanAnchoredClock(); private boolean startScheduledProfiling = true; - @Nullable private File activationEventsFile = null; @Nullable private File jfrFile = null; private BiConsumer parentOverrideHandler = @@ -72,8 +71,11 @@ public InferredSpansProcessor build() { profilingDuration, profilerLibDirectory, parentOverrideHandler); - return new InferredSpansProcessor( - config, clock, startScheduledProfiling, activationEventsFile, jfrFile); + InferredSpansProcessor processor = + new InferredSpansProcessor( + config, clock, startScheduledProfiling, activationEventsFile, jfrFile); + InferredSpans.setInstance(processor); + return processor; } /** diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java index b6b788c55..7e82a0ec1 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java @@ -5,8 +5,9 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.Collections.singletonList; + import java.util.ArrayList; -import java.util.Collections; import java.util.List; import javax.annotation.Nullable; @@ -32,7 +33,7 @@ public abstract class WildcardMatcher { private static final String CASE_SENSITIVE_PREFIX = "(?-i)"; private static final String WILDCARD = "*"; private static final WildcardMatcher MATCH_ALL = valueOf(WILDCARD); - private static final List MATCH_ALL_LIST = Collections.singletonList(MATCH_ALL); + private static final List MATCH_ALL_LIST = singletonList(MATCH_ALL); public static WildcardMatcher caseSensitiveMatcher(String matcher) { return valueOf(CASE_SENSITIVE_PREFIX + matcher); diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java index 5091a36a5..819a5b8cf 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java @@ -23,7 +23,7 @@ public class InferredSpansConfiguration { private final Duration inferredSpansMinDuration; private final List includedClasses; private final List excludedClasses; - private final Duration profilerInterval; + private volatile Duration profilerInterval; private final Duration profilingDuration; @Nullable private final String profilerLibDirectory; private final BiConsumer parentOverrideHandler; @@ -84,6 +84,10 @@ public Duration getProfilingInterval() { return profilerInterval; } + public void setProfilerInterval(Duration profilerInterval) { + this.profilerInterval = profilerInterval; + } + public Duration getProfilingDuration() { return profilingDuration; } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java index 61e5f75a7..27d0e5305 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java @@ -39,6 +39,7 @@ import java.util.Locale; import java.util.Objects; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; @@ -151,6 +152,7 @@ public class SamplingProfiler implements Runnable { private final Supplier tracerProvider; private final AsyncProfiler profiler; + @Nullable private volatile Future profilingTask; /** * Creates a sampling profiler, optionally relying on existing files. @@ -385,7 +387,7 @@ public void run() { if (!interrupted && !scheduler.isShutdown()) { long delay = config.getProfilingInterval().toMillis() - profilingDuration.toMillis(); - scheduler.schedule(this, delay, TimeUnit.MILLISECONDS); + profilingTask = scheduler.schedule(this, delay, TimeUnit.MILLISECONDS); } } @@ -723,7 +725,19 @@ public void copyFromFiles(Path activationEvents, Path traces) throws IOException @SuppressWarnings("FutureReturnValueIgnored") public void start() { - scheduler.submit(this); + profilingTask = scheduler.submit(this); + } + + @SuppressWarnings({"FutureReturnValueIgnored", "Interruption"}) + public void reschedule() { + Future future = this.profilingTask; + if (future != null) { + if (future.cancel(true)) { + Duration profilingDuration = config.getProfilingDuration(); + long delay = config.getProfilingInterval().toMillis() - profilingDuration.toMillis(); + profilingTask = scheduler.schedule(this, delay, TimeUnit.MILLISECONDS); + } + } } public void stop() throws InterruptedException, IOException { diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java index 76a6333ba..b5ce0c650 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java @@ -35,7 +35,7 @@ import org.junit.jupiter.api.io.TempDir; @DisabledOnOs(WINDOWS) // Uses async-profiler, which is not supported on Windows -public class InferredSpansAutoConfigTest { +class InferredSpansAutoConfigTest { @BeforeEach @AfterEach @@ -99,7 +99,7 @@ public void checkAllOptions(@TempDir Path tmpDir) { } @Test - public void checkDisabledbyDefault() { + void checkDisabledbyDefault() { try (AutoConfigTestProperties props = new AutoConfigTestProperties()) { OpenTelemetry otel = GlobalOpenTelemetry.get(); List processors = OtelReflectionUtils.getSpanProcessors(otel); @@ -109,7 +109,7 @@ public void checkDisabledbyDefault() { @DisabledOnOpenJ9 @Test - public void checkProfilerWorking() { + void checkProfilerWorking() { try (AutoConfigTestProperties props = new AutoConfigTestProperties() .put(InferredSpansAutoConfig.ENABLED_OPTION, "true") diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansTest.java new file mode 100644 index 000000000..e0de5997e --- /dev/null +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansTest.java @@ -0,0 +1,88 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.inferredspans; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +import io.opentelemetry.contrib.inferredspans.internal.SamplingProfiler; +import io.opentelemetry.contrib.inferredspans.internal.util.DisabledOnOpenJ9; +import java.time.Duration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; + +@DisabledOnOs(OS.WINDOWS) +@DisabledOnOpenJ9 +class InferredSpansTest { + + private ProfilerTestSetup setup; + + @BeforeEach + void setUp() { + InferredSpans.setInstance(null); + } + + @AfterEach + void tearDown() { + if (setup != null) { + setup.close(); + } + InferredSpans.setInstance(null); + } + + @Test + void testIsEnabled() { + assertThat(InferredSpans.isEnabled()).isFalse(); + + setup = ProfilerTestSetup.create(c -> {}); + + assertThat(InferredSpans.isEnabled()).isTrue(); + + setup.close(); + setup = null; + + // In a real-world scenario, the close() method would lead to the processor being garbage + // collected, but to make it deterministic, we manually set the instance to null + InferredSpans.setInstance(null); + assertThat(InferredSpans.isEnabled()).isFalse(); + } + + @Test + void testSetProfilerIntervalWhenDisabled() { + InferredSpans.setProfilerInterval(Duration.ofMillis(10)); + + setup = + ProfilerTestSetup.create( + c -> + c.profilerInterval(Duration.ofSeconds(10)) + .profilingDuration(Duration.ofMillis(500))); + + // assert that the interval set before the profiler was initialized is ignored + assertThat(setup.profiler.getConfig().getProfilingInterval()).isEqualTo(Duration.ofSeconds(10)); + } + + @Test + void testSetProfilerInterval() { + setup = + ProfilerTestSetup.create( + c -> + c.profilerInterval(Duration.ofSeconds(10)) + .profilingDuration(Duration.ofMillis(500))); + + SamplingProfiler profiler = setup.profiler; + await() + .untilAsserted(() -> assertThat(profiler.getProfilingSessions()).isGreaterThanOrEqualTo(1)); + + InferredSpans.setProfilerInterval(Duration.ofMillis(100)); + + await() + .timeout(Duration.ofSeconds(2)) + .untilAsserted(() -> assertThat(profiler.getProfilingSessions()).isGreaterThanOrEqualTo(2)); + } +} diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java index 614f75e72..bcf56691b 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; -public class SamplingProfilerQueueTest { +class SamplingProfilerQueueTest { @Test @DisabledOnOs(OS.WINDOWS) diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java index 8cf7f06e1..280c06909 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java @@ -5,9 +5,9 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; @@ -33,32 +33,32 @@ void assertCommercialFeaturesUnlocked() throws Exception { @Test void assertCommercialFeaturesLockedThrows() throws Exception { - assertThrows( - JfrConnectionException.class, - () -> { - ObjectName objectName = mock(ObjectName.class); - MBeanServerConnection mBeanServerConnection = mockMbeanServer(objectName, "locked"); - FlightRecorderDiagnosticCommandConnection.assertCommercialFeaturesUnlocked( - mBeanServerConnection, objectName); - }); + assertThatThrownBy( + () -> { + ObjectName objectName = mock(ObjectName.class); + MBeanServerConnection mBeanServerConnection = mockMbeanServer(objectName, "locked"); + FlightRecorderDiagnosticCommandConnection.assertCommercialFeaturesUnlocked( + mBeanServerConnection, objectName); + }) + .isInstanceOf(JfrConnectionException.class); } @Test void closeRecording() throws Exception { - assertThrows(UnsupportedOperationException.class, () -> createconnection().closeRecording(1)); + assertThatThrownBy(() -> createconnection().closeRecording(1)) + .isInstanceOf(UnsupportedOperationException.class); } @Test void testGetStream() throws Exception { - assertThrows( - UnsupportedOperationException.class, - () -> createconnection().getStream(1L, null, null, 0L)); + assertThatThrownBy(() -> createconnection().getStream(1L, null, null, 0L)) + .isInstanceOf(UnsupportedOperationException.class); } @Test void testCloneRecording() throws Exception { - assertThrows( - UnsupportedOperationException.class, () -> createconnection().cloneRecording(1, false)); + assertThatThrownBy(() -> createconnection().cloneRecording(1, false)) + .isInstanceOf(UnsupportedOperationException.class); } @Test @@ -73,7 +73,7 @@ void startRecordingParsesIdCorrectly() throws Exception { long id = connection.startRecording( new RecordingOptions.Builder().build(), RecordingConfiguration.PROFILE_CONFIGURATION); - assertEquals(id, 99); + assertThat(id).isEqualTo(99); } @Test diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java index 9059980c3..041232b54 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.lang.management.ManagementFactory; import java.util.HashMap; @@ -49,6 +49,6 @@ void makeOpenData() throws Exception { mBeanServerConnection.invoke( objectInstance.getObjectName(), "getRecordingSettings", args, argTypes); - assertEquals(expected, actual); + assertThat(actual).isEqualTo(expected); } } diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java index d34bb3f45..091a6ca5f 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java @@ -5,10 +5,9 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.fail; import java.io.IOException; import java.nio.file.Files; @@ -44,18 +43,20 @@ void tearDown() { @Test void nullConfigThrows() { - assertThrows(IllegalArgumentException.class, () -> new JfcFileConfiguration(null)); + assertThatThrownBy(() -> new JfcFileConfiguration(null)) + .isInstanceOf(IllegalArgumentException.class); } @Test void brokenJfcConfigFileThrowsError() { - assertThrows(RuntimeMBeanException.class, () -> executeRecording("brokenJfcFile.jfc")); + assertThatThrownBy(() -> executeRecording("brokenJfcFile.jfc")) + .isInstanceOf(RuntimeMBeanException.class); } @Test void jfcFileFromInputStreamCanBeRead() { IItemCollection recordingContent = executeRecording("sampleJfcFile.jfc"); - assertTrue(containsEvent(recordingContent, "jdk.ThreadAllocationStatistics")); + assertThat(containsEvent(recordingContent, "jdk.ThreadAllocationStatistics")).isTrue(); } @Test @@ -68,9 +69,9 @@ void mapConfiguration() { RecordingConfiguration recordingConfiguration = new MapConfiguration(recordingConfigAsMap); IItemCollection recordingContent = excecuteRecordingWithConfig(recordingConfiguration); - assertNotNull(recordingContent, "excecuteRecordingWithConfig returned null"); - assertTrue(containsEvent(recordingContent, "jdk.ObjectAllocationInNewTLAB")); - assertTrue(containsEvent(recordingContent, "jdk.ObjectAllocationOutsideTLAB")); + assertThat(recordingContent).isNotNull(); + assertThat(containsEvent(recordingContent, "jdk.ObjectAllocationInNewTLAB")).isTrue(); + assertThat(containsEvent(recordingContent, "jdk.ObjectAllocationOutsideTLAB")).isTrue(); } private static boolean containsEvent(IItemCollection recordingContent, String eventName) { @@ -110,7 +111,7 @@ private IItemCollection excecuteRecordingWithConfig(RecordingConfiguration confi } recording.stop(); recording.dump(dumpFile.toString()); - assertTrue(Files.exists(dumpFile)); + assertThat(dumpFile).exists(); try { return JfrLoaderToolkit.loadEvents(dumpFile.toFile()); diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java index 9291fb7f2..2ca0135ba 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java @@ -5,8 +5,8 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.errorprone.annotations.Keep; import java.util.HashMap; @@ -33,14 +33,14 @@ private static Stream testGetName() { @MethodSource void testGetName(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().name(testValue).build(); - assertEquals(expected, opts.getName()); + assertThat(opts.getName()).isEqualTo(expected); } @Test void testGetNameDefault() { String expected = ""; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getName()); + assertThat(opts.getName()).isEqualTo(expected); } @Keep @@ -64,14 +64,14 @@ static Stream testGetMaxAge() { @MethodSource void testGetMaxAge(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().maxAge(testValue).build(); - assertEquals(expected, opts.getMaxAge()); + assertThat(opts.getMaxAge()).isEqualTo(expected); } @Test void testGetMaxAgeDefault() { String expected = "0"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getMaxAge()); + assertThat(opts.getMaxAge()).isEqualTo(expected); } @Keep @@ -91,9 +91,8 @@ private static Stream testGetMaxAgeNegative() { @ParameterizedTest @MethodSource void testGetMaxAgeNegative(String badValue) { - assertThrows( - IllegalArgumentException.class, - () -> new RecordingOptions.Builder().maxAge(badValue).build()); + assertThatThrownBy(() -> new RecordingOptions.Builder().maxAge(badValue).build()) + .isInstanceOf(IllegalArgumentException.class); } @Keep @@ -113,14 +112,14 @@ private static Stream testGetMaxSize() { @MethodSource void testGetMaxSize(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().maxSize(testValue).build(); - assertEquals(expected, opts.getMaxSize()); + assertThat(opts.getMaxSize()).isEqualTo(expected); } @Test void testGetMaxSizeDefault() { String expected = "0"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getMaxSize()); + assertThat(opts.getMaxSize()).isEqualTo(expected); } @Keep @@ -135,30 +134,29 @@ private static Stream testGetMaxSizeNegative() { @ParameterizedTest @MethodSource void testGetMaxSizeNegative(String badValue) { - assertThrows( - IllegalArgumentException.class, - () -> new RecordingOptions.Builder().maxSize(badValue).build()); + assertThatThrownBy(() -> new RecordingOptions.Builder().maxSize(badValue).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test void testGetDumpOnExit() { String expected = "true"; RecordingOptions opts = new RecordingOptions.Builder().dumpOnExit(expected).build(); - assertEquals(expected, opts.getDumpOnExit()); + assertThat(opts.getDumpOnExit()).isEqualTo(expected); } @Test void testGetDumpOnExitDefault() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDumpOnExit()); + assertThat(opts.getDumpOnExit()).isEqualTo(expected); } @Test void testGetDumpOnExitBadValue() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().dumpOnExit("BAD_VALUE").build(); - assertEquals(expected, opts.getDumpOnExit()); + assertThat(opts.getDumpOnExit()).isEqualTo(expected); } @Keep @@ -175,35 +173,35 @@ private static Stream testGetDestination() { @MethodSource void testGetDestination(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().destination(testValue).build(); - assertEquals(expected, opts.getDestination()); + assertThat(opts.getDestination()).isEqualTo(expected); } @Test void testGetDestinationDefault() { String expected = ""; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDestination()); + assertThat(opts.getDestination()).isEqualTo(expected); } @Test void testGetDisk() { String expected = "true"; RecordingOptions opts = new RecordingOptions.Builder().disk(expected).build(); - assertEquals(expected, opts.getDisk()); + assertThat(opts.getDisk()).isEqualTo(expected); } @Test void testGetDiskDefault() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDisk()); + assertThat(opts.getDisk()).isEqualTo(expected); } @Test void testGetDiskBadValue() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().disk("BAD_VALUE").build(); - assertEquals(expected, opts.getDisk()); + assertThat(opts.getDisk()).isEqualTo(expected); } @Keep @@ -227,14 +225,14 @@ private static Stream testGetDuration() { @MethodSource void testGetDuration(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().duration(testValue).build(); - assertEquals(expected, opts.getDuration()); + assertThat(opts.getDuration()).isEqualTo(expected); } @Test void testGetDurationDefault() { String expected = "0"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDuration()); + assertThat(opts.getDuration()).isEqualTo(expected); } @Keep @@ -254,9 +252,8 @@ private static Stream testGetDurationNegative() { @ParameterizedTest @MethodSource void testGetDurationNegative(String badValue) { - assertThrows( - IllegalArgumentException.class, - () -> new RecordingOptions.Builder().duration(badValue).build()); + assertThatThrownBy(() -> new RecordingOptions.Builder().duration(badValue).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -279,7 +276,7 @@ void testGetRecordingOptions() { .disk("true") .duration("120 s") .build(); - assertEquals(expected, opts.getRecordingOptions()); + assertThat(opts.getRecordingOptions()).isEqualTo(expected); } @Test @@ -289,6 +286,6 @@ void testGetRecordingOptionsDefaults() { // to insure consistent behaviour. expected.put("disk", "false"); RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getRecordingOptions()); + assertThat(opts.getRecordingOptions()).isEqualTo(expected); } } diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java index ac5c781ee..715d25bcb 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java @@ -5,12 +5,8 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import com.google.errorprone.annotations.Keep; import java.io.FileInputStream; @@ -109,8 +105,8 @@ void tearDown() { @Test void assertNewRecordingInitialValues() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { - assertEquals(Recording.State.NEW, recording.getState()); - assertEquals(-1, recording.getId()); + assertThat(recording.getState()).isEqualTo(Recording.State.NEW); + assertThat(recording.getId()).isEqualTo(-1); } catch (IOException | IllegalStateException | JfrConnectionException exception) { fail("assertNewRecordingInitialValues caught exception", exception); } @@ -120,8 +116,8 @@ void assertNewRecordingInitialValues() { void assertRecordingStartIdAndState() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { long id = recording.start(); - assertEquals(id, recording.getId()); - assertEquals(Recording.State.RECORDING, recording.getState()); + assertThat(recording.getId()).isEqualTo(id); + assertThat(recording.getState()).isEqualTo(Recording.State.RECORDING); } catch (IOException | IllegalStateException | JfrConnectionException e) { fail("assertRecordingStartIdAndState caught exception", e); } @@ -131,9 +127,9 @@ void assertRecordingStartIdAndState() { void assertRecordingStopState() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { long id = recording.start(); - assertEquals(id, recording.getId()); + assertThat(recording.getId()).isEqualTo(id); recording.stop(); - assertEquals(Recording.State.STOPPED, recording.getState()); + assertThat(recording.getState()).isEqualTo(Recording.State.STOPPED); } catch (IOException | IllegalStateException | JfrConnectionException e) { fail("assertRecordingStopState caught exception", e); } @@ -143,9 +139,9 @@ void assertRecordingStopState() { void assertRecordingCloseState() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { long id = recording.start(); - assertEquals(id, recording.getId()); + assertThat(recording.getId()).isEqualTo(id); recording.close(); - assertEquals(Recording.State.CLOSED, recording.getState()); + assertThat(recording.getState()).isEqualTo(Recording.State.CLOSED); } catch (IOException | IllegalStateException | JfrConnectionException e) { fail("assertRecordingCloseState caught exception", e); } @@ -255,7 +251,7 @@ void assertInvalidStateChangeThrowsIllegalStateException( try (Recording recording = flightRecorderConnection.newRecording(null, null)) { reflectivelyInvokeMethods(recording, args); } catch (InvocationTargetException invocationTargetException) { - assertTrue(invocationTargetException.getCause() instanceof IllegalStateException); + assertThat(invocationTargetException.getCause()).isInstanceOf(IllegalStateException.class); } catch (Exception e) { fail("Bad test code", e); } @@ -322,7 +318,7 @@ void assertRecordingOptionsAreSetInFlightRecorderMXBean( "getRecordingOptions", new Object[] {id}, new String[] {long.class.getName()}); - assertFalse(flightRecorderMXBeanOptions.isEmpty()); + assertThat(flightRecorderMXBeanOptions.isEmpty()).isFalse(); ((Collection) flightRecorderMXBeanOptions.values()) .forEach( compositeData -> { @@ -344,7 +340,7 @@ void assertRecordingOptionsAreSetInFlightRecorderMXBean( // and for destination since FlightRecorderMXBean returns null as default if (!("name".equals(key) && "".equals(actual)) && !("destination".equals(key) && "".equals(actual))) { - assertEquals(expected, actual, getter); + assertThat(actual).as(getter).isEqualTo(expected); } } catch (NoSuchMethodException | IllegalArgumentException @@ -393,7 +389,7 @@ void assertFileExistsAfterRecordingDump() { recording.stop(); Path dumpFile = Paths.get(System.getProperty("user.dir"), "testRecordingDump_dumped.jfr"); recording.dump(dumpFile.toString()); - assertTrue(Files.exists(dumpFile)); + assertThat(dumpFile).exists(); } catch (IllegalArgumentException badData) { fail("Issue in test data: " + badData.getMessage()); } catch (IOException ioe) { @@ -428,7 +424,7 @@ void assertFileExistsAfterRecordingStream() { fail(e.getMessage(), e); } - assertTrue(Files.exists(streamedFile)); + assertThat(streamedFile).exists(); } catch (IllegalArgumentException badData) { fail("Issue in test data: " + badData.getMessage()); @@ -502,9 +498,9 @@ void assertRecordingCloneState() { try (Recording recording = flightRecorderConnection.newRecording(recordingOptions, null)) { recording.start(); Recording clone = recording.clone(true); - assertSame(recording.getState(), Recording.State.RECORDING); - assertSame(clone.getState(), Recording.State.STOPPED); - assertNotEquals(recording.getId(), clone.getId()); + assertThat(recording.getState()).isEqualTo(Recording.State.RECORDING); + assertThat(clone.getState()).isEqualTo(Recording.State.STOPPED); + assertThat(recording.getId()).isNotEqualTo(clone.getId()); recording.stop(); } catch (IOException ioe) { // possible that this can be thrown, but should not happen in this context diff --git a/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java b/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java index 939a60af6..7225e72fa 100644 --- a/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java +++ b/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.jfrevent; -import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; @@ -52,7 +52,7 @@ void tearDown() { * @throws java.io.IOException on io error */ @Test - public void basicSpan() throws IOException { + void basicSpan() throws IOException { Path output = Files.createTempFile("test-basic-span", ".jfr"); try { @@ -89,7 +89,7 @@ public void basicSpan() throws IOException { * @throws java.lang.InterruptedException interrupted sleep */ @Test - public void basicSpanWithScope() throws IOException, InterruptedException { + void basicSpanWithScope() throws IOException, InterruptedException { Path output = Files.createTempFile("test-basic-span-with-scope", ".jfr"); try { diff --git a/jmx-metrics/build.gradle.kts b/jmx-metrics/build.gradle.kts index d5376e670..bc895cfc5 100644 --- a/jmx-metrics/build.gradle.kts +++ b/jmx-metrics/build.gradle.kts @@ -47,7 +47,7 @@ testing { dependencies { implementation("com.linecorp.armeria:armeria-grpc") implementation("com.linecorp.armeria:armeria-junit5") - implementation("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + implementation("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") implementation("org.testcontainers:junit-jupiter") implementation("org.slf4j:slf4j-simple") } diff --git a/jmx-metrics/docs/target-systems/jetty.md b/jmx-metrics/docs/target-systems/jetty.md index 46724daf3..eb74f4f51 100644 --- a/jmx-metrics/docs/target-systems/jetty.md +++ b/jmx-metrics/docs/target-systems/jetty.md @@ -1,7 +1,7 @@ # Jetty Metrics The JMX Metric Gatherer provides built in Jetty metric gathering capabilities. -Details about using JMX with WildFly can be found here: https://www.eclipse.org/jetty/documentation/jetty-11/operations-guide/index.html#og-jmx +Details about using JMX with WildFly can be found here: https://jetty.org/docs/jetty/11/operations-guide/jmx/index.html ### Metrics * Name: `jetty.select.count` diff --git a/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java b/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java index 4c2c9293c..4dddd975a 100644 --- a/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java +++ b/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java @@ -44,7 +44,7 @@ protected KafkaIntegrationTest(String configName) { @Container GenericContainer kafka = - new GenericContainer<>("bitnami/kafka:2.8.1") + new GenericContainer<>("bitnamilegacy/kafka:2.8.1") .withNetwork(Network.SHARED) .withEnv("KAFKA_CFG_ZOOKEEPER_CONNECT", "zookeeper:2181") .withEnv("ALLOW_PLAINTEXT_LISTENER", "yes") @@ -80,7 +80,7 @@ public Set getDependencies() { }; protected GenericContainer kafkaProducerContainer() { - return new GenericContainer<>("bitnami/kafka:2.8.1") + return new GenericContainer<>("bitnamilegacy/kafka:2.8.1") .withNetwork(Network.SHARED) .withEnv("KAFKA_CFG_ZOOKEEPER_CONNECT", "zookeeper:2181") .withEnv("ALLOW_PLAINTEXT_LISTENER", "yes") @@ -207,7 +207,7 @@ static class KafkaConsumerIntegrationTest extends KafkaIntegrationTest { @Container GenericContainer consumer = - new GenericContainer<>("bitnami/kafka:2.8.1") + new GenericContainer<>("bitnamilegacy/kafka:2.8.1") .withNetwork(Network.SHARED) .withEnv("KAFKA_CFG_ZOOKEEPER_CONNECT", "zookeeper:2181") .withEnv("ALLOW_PLAINTEXT_LISTENER", "yes") diff --git a/jmx-scraper/README.md b/jmx-scraper/README.md index a2f98f5b1..a69736e15 100644 --- a/jmx-scraper/README.md +++ b/jmx-scraper/README.md @@ -9,13 +9,18 @@ This is an alternative to the [JMX Gatherer](../jmx-metrics/README.md) utility. ## Release This project is released as part of the [OpenTelemetry Java Contrib](https://github.com/open-telemetry/opentelemetry-java-contrib) project. -The latest release is available from [Maven Central](https://central.sonatype.com/artifact/io.opentelemetry.contrib/opentelemetry-jmx-scraper) -or can be browsed via [MVN Repository](https://mvnrepository.com/artifact/io.opentelemetry.contrib/opentelemetry-jmx-scraper). +The latest release is available from: + +- [GitHub Release assets](https://github.com/open-telemetry/opentelemetry-java-contrib/releases/latest/download/opentelemetry-jmx-scraper.jar) +- [Maven Central](https://central.sonatype.com/artifact/io.opentelemetry.contrib/opentelemetry-jmx-scraper) ## Usage The general command to invoke JMX scraper is `java -jar scraper.jar `, where `scraper.jar` -is the `build/libs/opentelemetry-jmx-scraper-.jar` packaged binary when building this module. +is the packaged binary: + +- `build/libs/opentelemetry-jmx-scraper-.jar` when building from sources +- `.jar` file downloaded from Maven central or Release assets Minimal configuration required diff --git a/jmx-scraper/build.gradle.kts b/jmx-scraper/build.gradle.kts index 9e2878549..687b30612 100644 --- a/jmx-scraper/build.gradle.kts +++ b/jmx-scraper/build.gradle.kts @@ -39,7 +39,7 @@ testing { implementation("org.slf4j:slf4j-simple") implementation("com.linecorp.armeria:armeria-junit5") implementation("com.linecorp.armeria:armeria-grpc") - implementation("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + implementation("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") implementation("org.bouncycastle:bcprov-jdk18on:1.81") implementation("org.bouncycastle:bcpkix-jdk18on:1.81") } diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java index d1431647b..c984724e3 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java @@ -28,7 +28,7 @@ * JmxConnectionBuilder and relies on containers to minimize the JMX/RMI network complications which * are not NAT-friendly. */ -public class JmxConnectionTest { +class JmxConnectionTest { // OTLP endpoint is not used in test mode, but still has to be provided private static final String DUMMY_OTLP_ENDPOINT = "http://dummy-otlp-endpoint:8080/"; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java index 4f909fdc5..19d98bf38 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; -public class ActiveMqIntegrationTest extends TargetSystemIntegrationTest { +class ActiveMqIntegrationTest extends TargetSystemIntegrationTest { private static final int ACTIVEMQ_PORT = 61616; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java index 90f1fca73..5ff8f2dcc 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class CassandraIntegrationTest extends TargetSystemIntegrationTest { +class CassandraIntegrationTest extends TargetSystemIntegrationTest { private static final int CASSANDRA_PORT = 9042; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java index dcecc8f5f..d238e8a72 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java @@ -11,7 +11,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class CustomIntegrationTest extends TargetSystemIntegrationTest { +class CustomIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java index 803137539..4bab7e574 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class HBaseIntegrationTest extends TargetSystemIntegrationTest { +class HBaseIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { return new GenericContainer<>("dajobe/hbase") diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java index b89225629..bc44ea36c 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java @@ -16,7 +16,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.MountableFile; -public class HadoopIntegrationTest extends TargetSystemIntegrationTest { +class HadoopIntegrationTest extends TargetSystemIntegrationTest { private static final int HADOOP_PORT = 50070; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java index 86097cbaa..8c91e0c85 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java @@ -16,7 +16,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; -public class JettyIntegrationTest extends TargetSystemIntegrationTest { +class JettyIntegrationTest extends TargetSystemIntegrationTest { private static final int JETTY_PORT = 8080; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java index e29021a93..be8a04a53 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class JvmIntegrationTest extends TargetSystemIntegrationTest { +class JvmIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java index fbec81e2e..9cba55701 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java @@ -18,7 +18,7 @@ import org.testcontainers.containers.Network; import org.testcontainers.containers.wait.strategy.Wait; -public class SolrIntegrationTest extends TargetSystemIntegrationTest { +class SolrIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java index bec9453f8..b01f4485f 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java @@ -16,7 +16,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; -public class TomcatIntegrationTest extends TargetSystemIntegrationTest { +class TomcatIntegrationTest extends TargetSystemIntegrationTest { private static final int TOMCAT_PORT = 8080; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java index 73e546b85..bb2787b0a 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java @@ -22,7 +22,7 @@ import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.utility.MountableFile; -public class WildflyIntegrationTest extends TargetSystemIntegrationTest { +class WildflyIntegrationTest extends TargetSystemIntegrationTest { private static final int WILDFLY_SERVICE_PORT = 8080; private static final int WILDFLY_MANAGEMENT_PORT = 9990; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java index ed61aabbb..9319baf65 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java @@ -25,7 +25,7 @@ import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.Wait; -public class KafkaConsumerIntegrationTest extends TargetSystemIntegrationTest { +class KafkaConsumerIntegrationTest extends TargetSystemIntegrationTest { @Override protected Collection> createPrerequisiteContainers() { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java index 8eb9432a5..e46ed07b6 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java @@ -12,7 +12,7 @@ public class KafkaContainerFactory { private static final int KAFKA_PORT = 9092; private static final String KAFKA_BROKER = "kafka:" + KAFKA_PORT; - private static final String KAFKA_DOCKER_IMAGE = "bitnami/kafka:2.8.1"; + private static final String KAFKA_DOCKER_IMAGE = "bitnamilegacy/kafka:2.8.1"; private KafkaContainerFactory() {} diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java index f59040509..17d38d995 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java @@ -21,7 +21,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; -public class KafkaIntegrationTest extends TargetSystemIntegrationTest { +class KafkaIntegrationTest extends TargetSystemIntegrationTest { @Override protected Collection> createPrerequisiteContainers() { GenericContainer zookeeper = diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java index 155cb9fc5..37b141b01 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java @@ -24,7 +24,7 @@ import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.Wait; -public class KafkaProducerIntegrationTest extends TargetSystemIntegrationTest { +class KafkaProducerIntegrationTest extends TargetSystemIntegrationTest { @Override protected Collection> createPrerequisiteContainers() { diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java index bdfb93272..d3358741f 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java @@ -9,7 +9,7 @@ * Exception indicating something is wrong with the provided arguments or reading the configuration * from them */ -public class InvalidArgumentException extends Exception { +public final class InvalidArgumentException extends Exception { private static final long serialVersionUID = 0L; diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java index ceba4b2fe..92ff4f387 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.jmxscraper; +import static java.util.logging.Level.WARNING; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.IOException; import java.net.MalformedURLException; @@ -17,7 +19,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; import javax.management.remote.JMXConnector; @@ -33,7 +34,7 @@ import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.RealmCallback; -public class JmxConnectorBuilder { +public final class JmxConnectorBuilder { private static final Logger logger = Logger.getLogger(JmxConnectorBuilder.class.getName()); @@ -146,7 +147,7 @@ private Map buildEnv() { } }); } catch (ReflectiveOperationException e) { - logger.log(Level.WARNING, "SASL unsupported in current environment: " + e.getMessage()); + logger.log(WARNING, "SASL unsupported in current environment: " + e.getMessage()); } return env; } diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java index 85c47ba0e..0835d9d92 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java @@ -5,6 +5,12 @@ package io.opentelemetry.contrib.jmxscraper; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static java.util.Optional.ofNullable; +import static java.util.logging.Level.INFO; +import static java.util.logging.Level.SEVERE; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.contrib.jmxscraper.config.JmxScraperConfig; import io.opentelemetry.contrib.jmxscraper.config.PropertiesCustomizer; @@ -21,19 +27,15 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Level; import java.util.logging.Logger; import javax.management.MBeanServerConnection; import javax.management.remote.JMXConnector; -public class JmxScraper { +public final class JmxScraper { private static final Logger logger = Logger.getLogger(JmxScraper.class.getName()); private static final String CONFIG_ARG = "-config"; private static final String TEST_ARG = "-test"; @@ -55,7 +57,7 @@ public static void main(String[] args) { // set log format System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tF %1$tT %4$s %5$s%n"); - List effectiveArgs = new ArrayList<>(Arrays.asList(args)); + List effectiveArgs = new ArrayList<>(asList(args)); boolean testMode = effectiveArgs.remove(TEST_ARG); try { @@ -73,7 +75,7 @@ public static void main(String[] args) { JmxScraperConfig scraperConfig = configCustomizer.getScraperConfig(); long exportSeconds = scraperConfig.getSamplingInterval().toMillis() / 1000; - logger.log(Level.INFO, "metrics export interval (seconds) = " + exportSeconds); + logger.log(INFO, "metrics export interval (seconds) = " + exportSeconds); JmxMetricInsight service = JmxMetricInsight.createService( @@ -81,8 +83,8 @@ public static void main(String[] args) { JmxConnectorBuilder connectorBuilder = JmxConnectorBuilder.createNew(scraperConfig.getServiceUrl()); - Optional.ofNullable(scraperConfig.getUsername()).ifPresent(connectorBuilder::withUser); - Optional.ofNullable(scraperConfig.getPassword()).ifPresent(connectorBuilder::withPassword); + ofNullable(scraperConfig.getUsername()).ifPresent(connectorBuilder::withUser); + ofNullable(scraperConfig.getPassword()).ifPresent(connectorBuilder::withPassword); if (scraperConfig.isRegistrySsl()) { connectorBuilder.withSslRegistry(); @@ -95,20 +97,20 @@ public static void main(String[] args) { jmxScraper.start(); } } catch (ConfigurationException e) { - logger.log(Level.SEVERE, "invalid configuration: " + e.getMessage(), e); + logger.log(SEVERE, "invalid configuration: " + e.getMessage(), e); System.exit(1); } catch (InvalidArgumentException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + logger.log(SEVERE, e.getMessage(), e); logger.info("Usage: java -jar [-test] [-config ]"); logger.info(" -test test JMX connection with provided configuration and exit"); logger.info( " -config provide configuration, where is - for stdin, or "); System.exit(1); } catch (IOException e) { - logger.log(Level.SEVERE, "Unable to connect ", e); + logger.log(SEVERE, "Unable to connect ", e); System.exit(2); } catch (RuntimeException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + logger.log(SEVERE, e.getMessage(), e); System.exit(3); } } @@ -119,14 +121,14 @@ private static boolean testConnection(JmxConnectorBuilder connectorBuilder) { MBeanServerConnection connection = connector.getMBeanServerConnection(); Integer mbeanCount = connection.getMBeanCount(); if (mbeanCount > 0) { - logger.log(Level.INFO, "JMX connection test OK"); + logger.log(INFO, "JMX connection test OK"); return true; } else { - logger.log(Level.SEVERE, "JMX connection test ERROR"); + logger.log(SEVERE, "JMX connection test ERROR"); return false; } } catch (IOException e) { - logger.log(Level.SEVERE, "JMX connection test ERROR", e); + logger.log(SEVERE, "JMX connection test ERROR", e); return false; } } @@ -210,7 +212,7 @@ private void start() throws IOException { try (JMXConnector connector = client.build()) { MBeanServerConnection connection = connector.getMBeanServerConnection(); - service.startRemote(getMetricConfig(config), () -> Collections.singletonList(connection)); + service.startRemote(getMetricConfig(config), () -> singletonList(connection)); running.set(true); logger.info("JMX scraping started"); diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java index 09a97eb83..53c19096b 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java @@ -5,21 +5,25 @@ package io.opentelemetry.contrib.jmxscraper.config; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableSet; +import static java.util.Locale.ROOT; + import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.io.InputStream; import java.time.Duration; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Set; import java.util.logging.Logger; import javax.annotation.Nullable; /** This class keeps application settings */ -public class JmxScraperConfig { +public final class JmxScraperConfig { private static final Logger logger = Logger.getLogger(JmxScraperConfig.class.getName()); @@ -49,9 +53,9 @@ public class JmxScraperConfig { private String serviceUrl = ""; - private List jmxConfig = Collections.emptyList(); + private List jmxConfig = emptyList(); - private Set targetSystems = Collections.emptySet(); + private Set targetSystems = emptySet(); private TargetSystemSource targetSystemSource = TargetSystemSource.AUTO; @@ -73,7 +77,7 @@ public enum TargetSystemSource { static TargetSystemSource fromString(String source) { try { - return TargetSystemSource.valueOf(source.toUpperCase(Locale.ROOT)); + return TargetSystemSource.valueOf(source.toUpperCase(ROOT)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid target system source: " + source, e); } @@ -217,8 +221,8 @@ public static JmxScraperConfig fromConfig(ConfigProperties config) { "at least one of '" + JMX_TARGET_SYSTEM + "' or '" + JMX_CONFIG + "' must be set"); } - scraperConfig.jmxConfig = Collections.unmodifiableList(jmxConfig); - scraperConfig.targetSystems = Collections.unmodifiableSet(new HashSet<>(targetSystem)); + scraperConfig.jmxConfig = unmodifiableList(jmxConfig); + scraperConfig.targetSystems = unmodifiableSet(new HashSet<>(targetSystem)); scraperConfig.username = config.getString("otel.jmx.username"); scraperConfig.password = config.getString("otel.jmx.password"); diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java index 9d6812146..141ad025f 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java @@ -16,7 +16,7 @@ import javax.annotation.Nullable; /** Customizer of default SDK configuration and provider of effective scraper config */ -public class PropertiesCustomizer implements Function> { +public final class PropertiesCustomizer implements Function> { private static final Logger logger = Logger.getLogger(PropertiesCustomizer.class.getName()); diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java index 071e2b8fa..f4ad68faa 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java @@ -11,7 +11,7 @@ import java.util.function.Supplier; /** Configuration supplier for java properties */ -public class PropertiesSupplier implements Supplier> { +public final class PropertiesSupplier implements Supplier> { private final Properties properties; diff --git a/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java b/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java index b51144360..430476d51 100644 --- a/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java +++ b/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.jmxscraper; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -12,8 +14,6 @@ import io.opentelemetry.contrib.jmxscraper.config.TestUtil; import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Properties; import org.junit.jupiter.api.Test; @@ -32,7 +32,7 @@ void shouldThrowExceptionWhenInvalidCommandLineArgsProvided() { @Test void emptyArgumentsAllowed() throws InvalidArgumentException { - assertThat(JmxScraper.argsToConfig(Collections.emptyList())) + assertThat(JmxScraper.argsToConfig(emptyList())) .describedAs("empty config allowed to use JVM properties") .isEmpty(); } @@ -43,7 +43,7 @@ void shouldThrowExceptionWhenMissingProperties() { } private static void testInvalidArguments(String... args) { - assertThatThrownBy(() -> JmxScraper.argsToConfig(Arrays.asList(args))) + assertThatThrownBy(() -> JmxScraper.argsToConfig(asList(args))) .isInstanceOf(InvalidArgumentException.class); } @@ -54,7 +54,7 @@ void shouldCreateConfig_propertiesLoadedFromFile() throws InvalidArgumentExcepti // Windows returns /C:/path/to/file, which is not a valid path for Path.get() in Java. String filePath = ClassLoader.getSystemClassLoader().getResource("validConfig.properties").getPath(); - List args = Arrays.asList("-config", filePath); + List args = asList("-config", filePath); // When Properties parsedConfig = JmxScraper.argsToConfig(args); @@ -73,7 +73,7 @@ void shouldCreateConfig_propertiesLoadedFromStdIn() throws InvalidArgumentExcept ClassLoader.getSystemClassLoader().getResourceAsStream("validConfig.properties")) { // Given System.setIn(stream); - List args = Arrays.asList("-config", "-"); + List args = asList("-config", "-"); // When Properties parsedConfig = JmxScraper.argsToConfig(args); diff --git a/kafka-exporter/build.gradle.kts b/kafka-exporter/build.gradle.kts index d4aed3f54..5f189f97a 100644 --- a/kafka-exporter/build.gradle.kts +++ b/kafka-exporter/build.gradle.kts @@ -14,7 +14,7 @@ otelJava { dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") api("io.opentelemetry:opentelemetry-sdk-common") - api("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + api("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") api("org.apache.kafka:kafka-clients") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java index b5559832e..28e123fe8 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java @@ -26,7 +26,7 @@ @ThreadSafe @SuppressWarnings("FutureReturnValueIgnored") -public class KafkaSpanExporter implements SpanExporter { +public final class KafkaSpanExporter implements SpanExporter { private static final Logger logger = LoggerFactory.getLogger(KafkaSpanExporter.class); private final String topicName; private final Producer> producer; @@ -59,20 +59,28 @@ public CompletableResultCode export(@Nonnull Collection spans) { CompletableResultCode result = new CompletableResultCode(); CompletableFuture.runAsync( - () -> - producer.send( - producerRecord, - (metadata, exception) -> { - if (exception == null) { - result.succeed(); - } else { - logger.error( - String.format("Error while sending spans to Kafka topic %s", topicName), - exception); - result.fail(); - } - }), - executorService); + () -> + producer.send( + producerRecord, + (metadata, exception) -> { + if (exception == null) { + result.succeed(); + } else { + logger.error( + String.format("Error while sending spans to Kafka topic %s", topicName), + exception); + result.fail(); + } + }), + executorService) + .whenComplete( + (ignore, exception) -> { + if (exception != null) { + logger.error( + "Executor task failed while sending to Kafka topic {}", topicName, exception); + result.fail(); + } + }); return result; } diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java index e6b49d6dc..d7f1d3c17 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java @@ -20,7 +20,7 @@ import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.common.serialization.Serializer; -public class KafkaSpanExporterBuilder { +public final class KafkaSpanExporterBuilder { private static final long DEFAULT_TIMEOUT_IN_SECONDS = 5L; private String topicName; private Producer> producer; diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java index 4c5ff7112..9da3f266f 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java @@ -11,7 +11,7 @@ import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.serialization.Deserializer; -public class SpanDataDeserializer implements Deserializer { +public final class SpanDataDeserializer implements Deserializer { @SuppressWarnings("NullAway") @Override public ExportTraceServiceRequest deserialize(String topic, byte[] data) { diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java index 4c689f16a..8f31eb412 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java @@ -20,7 +20,7 @@ import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.serialization.Serializer; -public class SpanDataSerializer implements Serializer> { +public final class SpanDataSerializer implements Serializer> { @Override public byte[] serialize(String topic, Collection data) { if (Objects.isNull(data)) { diff --git a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java index a7a5239ee..8c520514e 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java @@ -9,8 +9,8 @@ import static org.apache.kafka.clients.CommonClientConfigs.CLIENT_ID_CONFIG; import static org.apache.kafka.clients.producer.ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG; import static org.apache.kafka.clients.producer.ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.trace.data.SpanData; @@ -49,7 +49,7 @@ void buildWithSerializersInSetters() { .build()) .build(); - assertNotNull(actual); + assertThat(actual).isNotNull(); actual.close(); } @@ -74,7 +74,7 @@ void buildWithSerializersInConfig() { .build()) .build(); - assertNotNull(actual); + assertThat(actual).isNotNull(); actual.close(); } @@ -91,33 +91,32 @@ void buildWithMissingTopic() { VALUE_SERIALIZER_CLASS_CONFIG, valueSerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test void buildWithMissingProducer() { - assertThrows( - IllegalArgumentException.class, - () -> new KafkaSpanExporterBuilder().setTopicName("a-topic").build()); + assertThatThrownBy(() -> new KafkaSpanExporterBuilder().setTopicName("a-topic").build()) + .isInstanceOf(IllegalArgumentException.class); } @Test void buildWithMissingProducerConfig() { - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer(KafkaSpanExporterBuilder.ProducerBuilder.newInstance().build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer(KafkaSpanExporterBuilder.ProducerBuilder.newInstance().build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -129,16 +128,16 @@ void buildWithMissingSerializers() { ProducerConfig.CLIENT_ID_CONFIG, "some clientId"); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -152,17 +151,17 @@ void buildWithKeySerializerInConfigAndValueSerializerInSetter() { KEY_SERIALIZER_CLASS_CONFIG, keySerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .setValueSerializer(valueSerializerMock) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .setValueSerializer(valueSerializerMock) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -176,17 +175,17 @@ void buildWithValueSerializerInConfigAndKeySerializerInSetter() { VALUE_SERIALIZER_CLASS_CONFIG, valueSerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .setKeySerializer(keySerializerMock) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .setKeySerializer(keySerializerMock) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -202,17 +201,17 @@ void buildWithSerializersInConfigAndSetters() { VALUE_SERIALIZER_CLASS_CONFIG, valueSerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .setKeySerializer(keySerializerMock) - .setValueSerializer(valueSerializerMock) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .setKeySerializer(keySerializerMock) + .setValueSerializer(valueSerializerMock) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } } diff --git a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterIntegrationTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterIntegrationTest.java index 4514efdcf..f8c010f89 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterIntegrationTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterIntegrationTest.java @@ -19,6 +19,7 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.data.SpanData; import java.time.Duration; +import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -29,7 +30,9 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.MockProducer; import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.errors.ApiException; import org.apache.kafka.common.serialization.StringDeserializer; import org.apache.kafka.common.serialization.StringSerializer; @@ -46,7 +49,7 @@ @TestInstance(TestInstance.Lifecycle.PER_CLASS) class KafkaSpanExporterIntegrationTest { private static final DockerImageName KAFKA_TEST_IMAGE = - DockerImageName.parse("apache/kafka:3.8.1"); + DockerImageName.parse("apache/kafka:3.9.1"); private static final String TOPIC = "span_topic"; private KafkaContainer kafka; private KafkaConsumer consumer; @@ -155,6 +158,28 @@ void exportWhenProducerInError() { testSubject.shutdown(); } + @Test + void exportWhenProducerFailsToSend() { + var mockProducer = new MockProducer>(); + mockProducer.sendException = new KafkaException("Simulated kafka exception"); + var testSubjectWithMockProducer = + KafkaSpanExporter.newBuilder().setTopicName(TOPIC).setProducer(mockProducer).build(); + + ImmutableList spans = + ImmutableList.of(makeBasicSpan("span-1"), makeBasicSpan("span-2")); + + CompletableResultCode actual = testSubjectWithMockProducer.export(spans); + + await() + .untilAsserted( + () -> { + assertThat(actual.isSuccess()).isFalse(); + assertThat(actual.isDone()).isTrue(); + }); + + testSubjectWithMockProducer.shutdown(); + } + @Test void flush() { CompletableResultCode actual = testSubject.flush(); diff --git a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java index 395fd357d..46636a247 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java @@ -5,9 +5,7 @@ package io.opentelemetry.contrib.kafka; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest; import io.opentelemetry.proto.resource.v1.Resource; @@ -38,16 +36,16 @@ void deserialize() { ExportTraceServiceRequest actual = testSubject.deserialize("test-topic", data); - assertEquals(request, actual); + assertThat(actual).isEqualTo(request); } @Test void deserializeNullData() { - assertNull(testSubject.deserialize("test-topic", null)); + assertThat(testSubject.deserialize("test-topic", null)).isNull(); } @Test void deserializeEmptyData() { - assertNotNull(testSubject.deserialize("test-topic", new byte[0])); + assertThat(testSubject.deserialize("test-topic", new byte[0])).isNotNull(); } } diff --git a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java index 517610724..06c3df63e 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java @@ -6,8 +6,7 @@ package io.opentelemetry.contrib.kafka; import static io.opentelemetry.contrib.kafka.TestUtil.makeBasicSpan; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.assertj.core.api.Assertions.assertThat; import com.google.common.collect.ImmutableList; import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest; @@ -28,14 +27,14 @@ void serialize() { byte[] actual = testSubject.serialize("test-topic", spans); - assertNotNull(actual); + assertThat(actual).isNotNull(); } @Test void serializeEmptyData() { byte[] actual = testSubject.serialize("test-topic", Collections.emptySet()); - assertEquals(0, actual.length); + assertThat(actual).isEmpty(); } @Test @@ -46,16 +45,18 @@ void convertSpansToRequest() { ExportTraceServiceRequest actual = testSubject.convertSpansToRequest(spans); - assertNotNull(actual); - assertEquals("span-1", actual.getResourceSpans(0).getScopeSpans(0).getSpans(0).getName()); - assertEquals("span-2", actual.getResourceSpans(0).getScopeSpans(0).getSpans(1).getName()); + assertThat(actual).isNotNull(); + assertThat(actual.getResourceSpans(0).getScopeSpans(0).getSpans(0).getName()) + .isEqualTo("span-1"); + assertThat(actual.getResourceSpans(0).getScopeSpans(0).getSpans(1).getName()) + .isEqualTo("span-2"); } @Test void convertSpansToRequestForEmptySpans() { ExportTraceServiceRequest actual = testSubject.convertSpansToRequest(Collections.emptySet()); - assertNotNull(actual); - assertEquals(ExportTraceServiceRequest.getDefaultInstance(), actual); + assertThat(actual).isNotNull(); + assertThat(actual).isEqualTo(ExportTraceServiceRequest.getDefaultInstance()); } } diff --git a/maven-extension/README.md b/maven-extension/README.md index 91ec71744..fd0150355 100644 --- a/maven-extension/README.md +++ b/maven-extension/README.md @@ -12,7 +12,7 @@ The Maven OpenTelemetry Extension is configured using environment variables or J * (since Maven 3.3.1) configuring the extension in `.mvn/extensions.xml`. In the code snippets below, replace `OPENTELEMETRY_MAVEN_VERSION` with the [latest -release](https://search.maven.org/search?q=g:io.opentelemetry.contrib%20AND%20a:opentelemetry-maven-extension). +release](https://central.sonatype.com/artifact/io.opentelemetry.contrib/opentelemetry-maven-extension). ### Adding the extension to the classpath @@ -109,8 +109,8 @@ In addition to the span attributes captured on every Maven plugin goal executio |----------------------------------------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------| | `http.method` | string | `POST` | | `http.url` | string | Base URL of the uploaded artifact `${maven.build.repository.url}/${groupId}/${artifactId}/${version}` where the `.` of `${groupId}` are replaced by `/` | -| `maven.build.repository.id` | string | ID of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#repository) | -| `maven.build.repository.url` | string | URL of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#repository) | +| `maven.build.repository.id` | string | ID of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#Repository) | +| `maven.build.repository.url` | string | URL of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#Repository) | | `peer.service` | string | Maven repository hostname deduced from the Repository URL | The `span.kind` is set to `client` @@ -200,7 +200,7 @@ Steps to instrument a Maven Mojo: * Add the OpenTelemetry API dependency in the `pom.xml` of the Maven plugin. Replace `OPENTELEMETRY_VERSION` with the [latest - release](https://search.maven.org/search?q=g:io.opentelemetry%20AND%20a:opentelemetry-api). + release](https://central.sonatype.com/artifact/io.opentelemetry/opentelemetry-api). ```xml diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java index e2cc37a28..0b94dce54 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java @@ -17,11 +17,11 @@ * Note: if otel-java-contrib bumps to Java 11+, we could use junit-pioneer's * {@code @SetSystemProperty} and {@code @ClearSystemProperty} but no bump is planned for now. */ -public class OpenTelemetrySdkServiceTest { +class OpenTelemetrySdkServiceTest { /** Verify default config */ @Test - public void testDefaultConfiguration() { + void testDefaultConfiguration() { System.clearProperty("otel.exporter.otlp.endpoint"); System.clearProperty("otel.service.name"); System.clearProperty("otel.resource.attributes"); @@ -40,7 +40,7 @@ public void testDefaultConfiguration() { /** Verify overwritten `service.name`,`key1` and `key2` */ @Test - public void testOverwrittenResourceAttributes() { + void testOverwrittenResourceAttributes() { System.setProperty("otel.service.name", "my-maven"); System.setProperty("otel.resource.attributes", "key1=val1,key2=val2"); @@ -59,7 +59,7 @@ public void testOverwrittenResourceAttributes() { /** Verify defining `otel.exporter.otlp.endpoint` works */ @Test - public void testOverwrittenExporterConfiguration_1() { + void testOverwrittenExporterConfiguration_1() { System.setProperty("otel.exporter.otlp.endpoint", "https://example.com:4317"); try (OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService()) { @@ -78,7 +78,7 @@ public void testOverwrittenExporterConfiguration_1() { /** Verify defining `otel.exporter.otlp.traces.endpoint` works */ @Test - public void testOverwrittenExporterConfiguration_2() { + void testOverwrittenExporterConfiguration_2() { System.clearProperty("otel.exporter.otlp.endpoint"); System.clearProperty("otel.traces.exporter"); System.setProperty("otel.exporter.otlp.traces.endpoint", "https://example.com:4317/"); @@ -102,7 +102,7 @@ public void testOverwrittenExporterConfiguration_2() { /** Verify defining `otel.exporter.otlp.traces.endpoint` and `otel.traces.exporter` works */ @Test - public void testOverwrittenExporterConfiguration_3() { + void testOverwrittenExporterConfiguration_3() { System.clearProperty("otel.exporter.otlp.endpoint"); System.setProperty("otel.traces.exporter", "otlp"); System.setProperty("otel.exporter.otlp.traces.endpoint", "https://example.com:4317/"); diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java index 864ce8df8..2a01a1754 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java @@ -12,11 +12,11 @@ import io.opentelemetry.api.trace.Tracer; import org.junit.jupiter.api.Test; -public class SpanRegistryTest { +class SpanRegistryTest { /** MVND reuses the same Maven process and thus the Span Registry is reused. */ @Test - public void testSpanRegistryReuseWhenUsingMvnDaemon() { + void testSpanRegistryReuseWhenUsingMvnDaemon() { SpanRegistry spanRegistry = new SpanRegistry(); Tracer tracer = OpenTelemetry.noop().getTracer("test"); diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java index 21748cebb..46877575a 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java @@ -12,10 +12,9 @@ import java.util.Map; import org.junit.jupiter.api.Test; -public class MojoGoalExecutionHandlerConfigurationTest { - +class MojoGoalExecutionHandlerConfigurationTest { @Test - public void mojoGoalExecutionHandlers() { + void mojoGoalExecutionHandlers() { Map actual = MojoGoalExecutionHandlerConfiguration.loadMojoGoalExecutionHandler( OtelExecutionListener.class.getClassLoader()); diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java index b193ccdb5..645ecfa0d 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java @@ -47,10 +47,10 @@ * https://github.com/takari/takari-lifecycle/blob/master/takari-lifecycle-plugin/src/test/java/io/takari/maven/plugins/plugin/PluginDescriptorMojoTest.java */ @SuppressWarnings({"DeduplicateConstants", "deprecation"}) -public class MojoGoalExecutionHandlerTest { +class MojoGoalExecutionHandlerTest { @Test - public void testMavenDeploy() throws Exception { + void testMavenDeploy() throws Exception { String pomXmlPath = "projects/jar/pom.xml"; String mojoGroupId = "org.apache.maven.plugins"; @@ -92,7 +92,7 @@ public void testMavenDeploy() throws Exception { } @Test - public void testSpringBootBuildImage_springboot_1() throws Exception { + void testSpringBootBuildImage_springboot_1() throws Exception { String pomXmlPath = "projects/springboot_1/pom.xml"; String mojoGroupId = "org.springframework.boot"; @@ -136,7 +136,7 @@ public void testSpringBootBuildImage_springboot_1() throws Exception { } @Test - public void testSpringBootBuildImage_springboot_2() throws Exception { + void testSpringBootBuildImage_springboot_2() throws Exception { String pomXmlPath = "projects/springboot_2/pom.xml"; String mojoGroupId = "org.springframework.boot"; @@ -180,7 +180,7 @@ public void testSpringBootBuildImage_springboot_2() throws Exception { } @Test - public void testGoogleJibBuild_jib_1() throws Exception { + void testGoogleJibBuild_jib_1() throws Exception { String pomXmlPath = "projects/jib_1/pom.xml"; String mojoGroupId = "com.google.cloud.tools"; @@ -221,7 +221,7 @@ public void testGoogleJibBuild_jib_1() throws Exception { } @Test - public void testGoogleJibBuild_jib_2() throws Exception { + void testGoogleJibBuild_jib_2() throws Exception { String pomXmlPath = "projects/jib_2/pom.xml"; String mojoGroupId = "com.google.cloud.tools"; @@ -262,7 +262,7 @@ public void testGoogleJibBuild_jib_2() throws Exception { } @Test - public void testSnykTest_snyk_1() throws Exception { + void testSnykTest_snyk_1() throws Exception { String pomXmlPath = "projects/snyk_1/pom.xml"; String mojoGroupId = "io.snyk"; @@ -298,7 +298,7 @@ public void testSnykTest_snyk_1() throws Exception { } @Test - public void testSnykMonitor_snyk_1() throws Exception { + void testSnykMonitor_snyk_1() throws Exception { String pomXmlPath = "projects/snyk_1/pom.xml"; String mojoGroupId = "io.snyk"; diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index 6d585cca5..27e61bf1f 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -20,14 +20,14 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - testImplementation("io.micrometer:micrometer-core:1.15.3") + testImplementation("io.micrometer:micrometer-core:1.15.4") } testing { suites { val integrationTest by registering(JvmTestSuite::class) { dependencies { - implementation("io.micrometer:micrometer-registry-prometheus:1.15.3") + implementation("io.micrometer:micrometer-registry-prometheus:1.15.4") } } } diff --git a/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java b/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java index 12be80e01..defefe634 100644 --- a/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java +++ b/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java @@ -48,7 +48,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class PrometheusIntegrationTest { +class PrometheusIntegrationTest { private static final AttributeKey KEY1 = AttributeKey.stringKey("key1"); private static final AttributeKey KEY2 = AttributeKey.stringKey("key2"); private static final String VALUE1 = "value1"; diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java index e8a6b827c..2a080c8e8 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import io.opentelemetry.api.metrics.DoubleGaugeBuilder; import io.opentelemetry.api.metrics.DoubleHistogramBuilder; import io.opentelemetry.api.metrics.LongCounterBuilder; @@ -15,7 +17,6 @@ import io.opentelemetry.contrib.metrics.micrometer.internal.instruments.MicrometerLongCounter; import io.opentelemetry.contrib.metrics.micrometer.internal.instruments.MicrometerLongUpDownCounter; import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterSharedState; -import java.util.Objects; final class MicrometerMeter implements Meter { final MeterSharedState meterSharedState; @@ -26,25 +27,25 @@ final class MicrometerMeter implements Meter { @Override public LongCounterBuilder counterBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerLongCounter.builder(meterSharedState, name); } @Override public LongUpDownCounterBuilder upDownCounterBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerLongUpDownCounter.builder(meterSharedState, name); } @Override public DoubleHistogramBuilder histogramBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerDoubleHistogram.builder(meterSharedState, name); } @Override public DoubleGaugeBuilder gaugeBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerDoubleGauge.builder(meterSharedState, name); } } diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java index d76e19a34..2817754e2 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java @@ -5,12 +5,13 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import io.micrometer.core.instrument.MeterRegistry; import io.opentelemetry.api.metrics.MeterBuilder; import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.contrib.metrics.micrometer.internal.MemoizingSupplier; import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterProviderSharedState; -import java.util.Objects; import java.util.function.Supplier; /** @@ -44,13 +45,13 @@ public void close() { /** {@inheritDoc} */ @Override public MeterBuilder meterBuilder(String instrumentationScopeName) { - Objects.requireNonNull(instrumentationScopeName, "instrumentationScopeName"); + requireNonNull(instrumentationScopeName, "instrumentationScopeName"); return new MicrometerMeterBuilder(meterProviderSharedState, instrumentationScopeName); } /** Returns a new builder instance for this provider with the specified {@link MeterRegistry}. */ public static MicrometerMeterProviderBuilder builder(MeterRegistry meterRegistry) { - Objects.requireNonNull(meterRegistry, "meterRegistry"); + requireNonNull(meterRegistry, "meterRegistry"); return new MicrometerMeterProviderBuilder(() -> meterRegistry); } @@ -62,7 +63,7 @@ public static MicrometerMeterProviderBuilder builder(MeterRegistry meterRegistry */ public static MicrometerMeterProviderBuilder builder( Supplier meterRegistrySupplier) { - Objects.requireNonNull(meterRegistrySupplier, "meterRegistrySupplier"); + requireNonNull(meterRegistrySupplier, "meterRegistrySupplier"); return new MicrometerMeterProviderBuilder(new MemoizingSupplier<>(meterRegistrySupplier)); } } diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java index 655c8cd32..25bd8b4d3 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java @@ -12,7 +12,7 @@ import javax.annotation.Nullable; /** Builder utility class for creating instances of {@link MicrometerMeterProvider}. */ -public class MicrometerMeterProviderBuilder { +public final class MicrometerMeterProviderBuilder { private final Supplier meterRegistrySupplier; @Nullable private CallbackRegistrar callbackRegistrar; diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java index d9021a234..e3c34b2bb 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java @@ -5,8 +5,9 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import java.util.List; -import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -39,7 +40,7 @@ public final class ScheduledCallbackRegistrar implements CallbackRegistrar { public static ScheduledCallbackRegistrarBuilder builder( ScheduledExecutorService scheduledExecutorService) { - Objects.requireNonNull(scheduledExecutorService, "scheduledExecutorService"); + requireNonNull(scheduledExecutorService, "scheduledExecutorService"); return new ScheduledCallbackRegistrarBuilder(scheduledExecutorService); } diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java index de0da54f7..fb7ff0326 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java @@ -5,9 +5,10 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.time.Duration; -import java.util.Objects; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -27,7 +28,7 @@ public final class ScheduledCallbackRegistrarBuilder { /** Sets the period between successive executions of each registered callback */ @CanIgnoreReturnValue public ScheduledCallbackRegistrarBuilder setPeriod(long period, TimeUnit unit) { - Objects.requireNonNull(unit, "unit"); + requireNonNull(unit, "unit"); this.period = period; this.timeUnit = unit; return this; @@ -36,7 +37,7 @@ public ScheduledCallbackRegistrarBuilder setPeriod(long period, TimeUnit unit) { /** Sets the period between successive executions of each registered callback */ @CanIgnoreReturnValue public ScheduledCallbackRegistrarBuilder setPeriod(Duration period) { - Objects.requireNonNull(period, "period"); + requireNonNull(period, "period"); this.period = period.toMillis(); this.timeUnit = TimeUnit.MILLISECONDS; return this; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java index f323fbaba..4f1743cbc 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerMeterProviderTest { +class MicrometerMeterProviderTest { SimpleMeterRegistry meterRegistry; CallbackRegistrar callbackRegistrar; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java index 56b173e29..c23ef99dc 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java @@ -31,7 +31,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class MicrometerMeterTest { +class MicrometerMeterTest { SimpleMeterRegistry meterRegistry; List callbacks; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java index fd7585605..5b755da5f 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleCounterTest { +class MicrometerDoubleCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java index df358a1b9..393479db7 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java @@ -26,7 +26,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleGaugeTest { +class MicrometerDoubleGaugeTest { SimpleMeterRegistry meterRegistry; List callbacks; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java index bc88fccc7..dc62b91ee 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleHistogramTest { +class MicrometerDoubleHistogramTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java index 57cf8922e..536f18d91 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleUpDownCounterTest { +class MicrometerDoubleUpDownCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java index 803cc0952..34423fb14 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongCounterTest { +class MicrometerLongCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java index f55087dcf..96b56b1a9 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java @@ -27,7 +27,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongGaugeTest { +class MicrometerLongGaugeTest { SimpleMeterRegistry meterRegistry; List callbacks; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java index 880e7d766..a2651d4b6 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongHistogramTest { +class MicrometerLongHistogramTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java index e4bce0d99..bc73dcb5d 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongUpDownCounterTest { +class MicrometerLongUpDownCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/mise.toml b/mise.toml new file mode 100644 index 000000000..e00ac63b2 --- /dev/null +++ b/mise.toml @@ -0,0 +1,12 @@ +[tools] +lychee = "0.18.1" + +[tasks.lint-local-links] +run = 'lychee --verbose --scheme file --include-fragments {{arg(name="files", default=".")}}' + +[tasks.lint-links] +run = 'lychee --verbose --config .github/config/lychee.toml {{arg(name="files", var=true, default=".")}}' + +[settings] +# Only install tools explicitly defined in the [tools] section above +idiomatic_version_file_enable_tools = [] diff --git a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java index 32a33dde2..358730308 100644 --- a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java +++ b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java @@ -15,7 +15,7 @@ /** * A {@link ContextStorageProvider} that returns a {@link ContextStorage} which is completely no-op. */ -public class NoopContextStorageProvider implements ContextStorageProvider { +public final class NoopContextStorageProvider implements ContextStorageProvider { /** Returns a no-op context storage. */ @Override diff --git a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java index b84fef8b1..41da9ca7e 100644 --- a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java +++ b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java @@ -42,7 +42,7 @@ *

    The above will succeed both with the {@linkplain OpenTelemetry#noop() default implementation} * and this one, but with this implementation there will be no overhead at all. */ -public class NoopOpenTelemetry implements OpenTelemetry { +public final class NoopOpenTelemetry implements OpenTelemetry { private static final OpenTelemetry INSTANCE = new NoopOpenTelemetry(); diff --git a/opamp-client/build.gradle.kts b/opamp-client/build.gradle.kts index 1aeed0c40..8abbbee65 100644 --- a/opamp-client/build.gradle.kts +++ b/opamp-client/build.gradle.kts @@ -1,13 +1,12 @@ -import de.undercouch.gradle.tasks.download.DownloadExtension -import java.net.HttpURLConnection +import java.io.FileOutputStream +import java.io.InputStream import java.net.URL plugins { id("otel.java-conventions") id("otel.publish-conventions") id("otel.animalsniffer-conventions") - id("de.undercouch.download") version "5.6.0" - id("com.squareup.wire") version "5.3.11" + id("com.squareup.wire") version "5.4.0" } description = "Client implementation of the OpAMP spec." @@ -25,11 +24,11 @@ dependencies { testImplementation("com.squareup.okhttp3:mockwebserver3-junit5") } -val opampProtos = tasks.register("opampProtoDownload", download) -opampProtos.configure { +val opampProtos = tasks.register("opampProtoDownload") { group = "opamp" outputProtosDir.set(project.layout.buildDirectory.dir("opamp/protos")) - downloadedZipFile.set(project.layout.buildDirectory.file("intermediate/$name/release.zip")) + downloadedZipFile.set(project.layout.buildDirectory.file("intermediate/opampProtoDownload/release.zip")) + zipUrl.set("https://github.com/open-telemetry/opamp-spec/zipball/v0.14.0") } wire { @@ -39,8 +38,7 @@ wire { } } -abstract class DownloadOpampProtos @Inject constructor( - private val download: DownloadExtension, +abstract class DownloadAndExtractOpampProtos @Inject constructor( private val archiveOps: ArchiveOperations, private val fileOps: FileSystemOperations, ) : DefaultTask() { @@ -51,26 +49,20 @@ abstract class DownloadOpampProtos @Inject constructor( @get:Internal abstract val downloadedZipFile: RegularFileProperty + @get:Input + abstract val zipUrl: Property + @TaskAction fun execute() { - // Get the latest release tag by following the redirect from GitHub's latest release URL - val latestReleaseUrl = "https://github.com/open-telemetry/opamp-spec/releases/latest" - val connection = URL(latestReleaseUrl).openConnection() as HttpURLConnection - connection.instanceFollowRedirects = false - connection.requestMethod = "HEAD" - - val redirectLocation = connection.getHeaderField("Location") - connection.disconnect() + val url = URL(zipUrl.get()) + downloadedZipFile.get().asFile.parentFile.mkdirs() - // Extract tag from URL like: https://github.com/open-telemetry/opamp-spec/releases/tag/v0.12.0 - val latestTag = redirectLocation.substringAfterLast("/") - // Download the source code for the latest release - val zipUrl = "https://github.com/open-telemetry/opamp-spec/zipball/$latestTag" - - download.run { - src(zipUrl) - dest(downloadedZipFile) + url.openStream().use { input: InputStream -> + downloadedZipFile.get().asFile.outputStream().use { output: FileOutputStream -> + input.copyTo(output) + } } + val protos = archiveOps.zipTree(downloadedZipFile).matching { setIncludes(listOf("**/*.proto")) } diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClient.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClient.java similarity index 98% rename from opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClient.java rename to opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClient.java index 5889642d8..19d63eb11 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClient.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClient.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.opamp.client.internal; +package io.opentelemetry.opamp.client; import io.opentelemetry.opamp.client.internal.response.MessageData; import java.io.Closeable; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClientBuilder.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java similarity index 98% rename from opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClientBuilder.java rename to opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java index 3e4d0f4aa..d6af850fa 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClientBuilder.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.opamp.client.internal; +package io.opentelemetry.opamp.client; import com.github.f4b6a3.uuid.UuidCreator; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -11,9 +11,9 @@ import io.opentelemetry.opamp.client.internal.impl.OpampClientImpl; import io.opentelemetry.opamp.client.internal.impl.OpampClientState; import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; -import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.request.service.WebSocketRequestService; import io.opentelemetry.opamp.client.internal.state.State; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; @@ -28,12 +28,7 @@ import opamp.proto.KeyValue; import opamp.proto.RemoteConfigStatus; -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - * - *

    Builds an {@link OpampClient} instance. - */ +/** Builds an {@link OpampClient} instance. */ public final class OpampClientBuilder { private final Map identifyingAttributes = new HashMap<>(); private final Map nonIdentifyingAttributes = new HashMap<>(); diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java index ec453bf6f..8ff386251 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java @@ -5,7 +5,8 @@ package io.opentelemetry.opamp.client.internal.connectivity.websocket; -import java.util.Objects; +import static java.util.Objects.requireNonNull; + import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -65,7 +66,7 @@ public void close(int code, @Nullable String reason) { } private okhttp3.WebSocket getWebSocket() { - return Objects.requireNonNull(webSocket.get()); + return requireNonNull(webSocket.get()); } private class ListenerAdapter extends WebSocketListener { diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java index 7ada06c42..e224135ff 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java @@ -5,7 +5,7 @@ package io.opentelemetry.opamp.client.internal.impl; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.impl.recipe.AgentToServerAppenders; import io.opentelemetry.opamp.client.internal.impl.recipe.RecipeManager; import io.opentelemetry.opamp.client.internal.impl.recipe.RequestRecipe; @@ -19,12 +19,12 @@ import io.opentelemetry.opamp.client.internal.impl.recipe.appenders.SequenceNumberAppender; import io.opentelemetry.opamp.client.internal.request.Field; import io.opentelemetry.opamp.client.internal.request.Request; -import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.response.MessageData; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; import io.opentelemetry.opamp.client.internal.state.ObservableState; import io.opentelemetry.opamp.client.internal.state.State; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java index 569447342..e9f79c254 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java @@ -14,6 +14,7 @@ import io.opentelemetry.opamp.client.internal.request.delay.RetryPeriodicDelay; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.IOException; import java.time.Duration; import java.util.Objects; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java index 13ef9b117..280725884 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java @@ -13,6 +13,7 @@ import io.opentelemetry.opamp.client.internal.request.delay.RetryPeriodicDelay; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Duration; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java index df9fb8ba1..af47027ef 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java @@ -6,7 +6,7 @@ package io.opentelemetry.opamp.client.internal.response; import com.google.auto.value.AutoValue; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import javax.annotation.Nullable; import opamp.proto.AgentRemoteConfig; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java index 89ba8b1cb..be2d34215 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java @@ -5,7 +5,8 @@ package io.opentelemetry.opamp.client.internal.state; -import java.util.Objects; +import static java.util.Objects.requireNonNull; + import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nonnull; @@ -33,6 +34,6 @@ public void set(T value) { @Nonnull @Override public T get() { - return Objects.requireNonNull(state.get()); + return requireNonNull(state.get()); } } diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java similarity index 91% rename from opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java rename to opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java index ee47e4249..76d1650e3 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java @@ -3,10 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.opamp.client.internal.request.service; +package io.opentelemetry.opamp.client.request.service; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.request.Request; +import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; +import io.opentelemetry.opamp.client.internal.request.service.WebSocketRequestService; import io.opentelemetry.opamp.client.internal.response.Response; import java.util.function.Supplier; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java index 9a076f757..dd5c0b956 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java @@ -12,13 +12,13 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.connectivity.http.OkHttpSender; import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; -import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.response.MessageData; import io.opentelemetry.opamp.client.internal.state.State; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.IOException; import java.time.Duration; import java.util.ArrayList; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java index c0107673b..9c5ea516d 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java @@ -6,7 +6,7 @@ package io.opentelemetry.opamp.client.internal.request.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; @@ -21,6 +21,7 @@ import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.request.delay.PeriodicDelay; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayInputStream; import java.time.Duration; import java.util.ArrayList; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java index c00cc0cc0..6e96554ea 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java @@ -6,7 +6,7 @@ package io.opentelemetry.opamp.client.internal.request.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.inOrder; @@ -23,6 +23,7 @@ import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Duration; diff --git a/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java b/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java index a213ec21a..61347388a 100644 --- a/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java +++ b/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java @@ -11,10 +11,10 @@ import io.opentelemetry.sdk.logs.data.LogRecordData; import java.util.function.Predicate; -public class FilteringLogRecordProcessor implements LogRecordProcessor { +public final class FilteringLogRecordProcessor implements LogRecordProcessor { - public final LogRecordProcessor delegate; - public final Predicate predicate; + private final LogRecordProcessor delegate; + private final Predicate predicate; public FilteringLogRecordProcessor( LogRecordProcessor delegate, Predicate predicate) { diff --git a/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java b/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java index 55746e61d..1e503a51c 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java @@ -18,7 +18,7 @@ class EventToSpanBridgeComponentProviderTest { @Test void endToEnd() { String yaml = - "file_format: 0.4\n" + "file_format: 1.0-rc.1\n" + "logger_provider:\n" + " processors:\n" + " - event_to_span_event_bridge:\n"; diff --git a/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java b/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java index 50405d454..05bee8aa8 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.filter; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.logs.Logger; import io.opentelemetry.api.trace.Span; @@ -31,7 +31,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class FilteringLogRecordProcessorTest { +class FilteringLogRecordProcessorTest { private final InMemoryLogRecordExporter memoryLogRecordExporter = InMemoryLogRecordExporter.create(); @@ -79,7 +79,7 @@ public SdkLoggerProviderBuilder apply( logRecordData -> { SpanContext spanContext = logRecordData.getSpanContext(); return spanContext.isSampled(); - }) {}) + })) .build() .get("TestScope"); } @@ -93,14 +93,14 @@ void verifyLogFilteringExistSpanContext() { sdk.getLogsBridge().get("test").logRecordBuilder().setBody("One Log").emit(); List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(1, finishedLogRecordItems.size()); + assertThat(finishedLogRecordItems.size()).isEqualTo(1); try (Scope scope = span.makeCurrent()) { } finally { span.end(); } List finishedSpans = spansExporter.getFinishedSpanItems(); - assertEquals(1, finishedSpans.size()); + assertThat(finishedSpans.size()).isEqualTo(1); } } @@ -109,6 +109,6 @@ void verifyFilteringNotExitSpanContext() { logger.logRecordBuilder().setBody("One Log").emit(); List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(0, finishedLogRecordItems.size()); + assertThat(finishedLogRecordItems.size()).isEqualTo(0); } } diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java index 3b81ce277..0096caa66 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.interceptor; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -62,13 +62,13 @@ void verifyLogModification() { List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(1, finishedLogRecordItems.size()); + assertThat(finishedLogRecordItems.size()).isEqualTo(1); LogRecordData logRecordData = finishedLogRecordItems.get(0); - assertEquals(2, logRecordData.getAttributes().size()); - assertEquals( - "from interceptor", - logRecordData.getAttributes().get(AttributeKey.stringKey("global.attr"))); - assertEquals("local", logRecordData.getAttributes().get(AttributeKey.stringKey("local.attr"))); + assertThat(logRecordData.getAttributes().size()).isEqualTo(2); + assertThat(logRecordData.getAttributes().get(AttributeKey.stringKey("global.attr"))) + .isEqualTo("from interceptor"); + assertThat(logRecordData.getAttributes().get(AttributeKey.stringKey("local.attr"))) + .isEqualTo("local"); } @Test @@ -87,9 +87,9 @@ void verifyLogFiltering() { List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(2, finishedLogRecordItems.size()); - assertEquals(Value.of("One log"), finishedLogRecordItems.get(0).getBodyValue()); - assertEquals(Value.of("Another log"), finishedLogRecordItems.get(1).getBodyValue()); + assertThat(finishedLogRecordItems.size()).isEqualTo(2); + assertThat(finishedLogRecordItems.get(0).getBodyValue()).isEqualTo(Value.of("One log")); + assertThat(finishedLogRecordItems.get(1).getBodyValue()).isEqualTo(Value.of("Another log")); } private static class ModifiableLogRecordData implements LogRecordData { diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java index 6b12d5f1a..f321b8a7b 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.interceptor; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.contrib.interceptor.common.ComposableInterceptor; @@ -55,8 +54,8 @@ void verifyMetricModification() { meterProvider.forceFlush(); List finishedMetricItems = memoryMetricExporter.getFinishedMetricItems(); - assertEquals(1, finishedMetricItems.size()); - assertEquals("ModifiedName", finishedMetricItems.get(0).getName()); + assertThat(finishedMetricItems.size()).isEqualTo(1); + assertThat(finishedMetricItems.get(0).getName()).isEqualTo("ModifiedName"); } @Test @@ -75,7 +74,7 @@ void verifyMetricFiltering() { meterProvider.forceFlush(); List finishedMetricItems = memoryMetricExporter.getFinishedMetricItems(); - assertEquals(2, finishedMetricItems.size()); + assertThat(finishedMetricItems.size()).isEqualTo(2); List names = new ArrayList<>(); for (MetricData item : finishedMetricItems) { names.add(item.getName()); diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java index a6c177181..26242174f 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.interceptor; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -51,12 +51,12 @@ void verifySpanModification() { tracer.spanBuilder("Test span").setAttribute("local.attr", 10).startSpan().end(); List finishedSpanItems = memorySpanExporter.getFinishedSpanItems(); - assertEquals(1, finishedSpanItems.size()); + assertThat(finishedSpanItems.size()).isEqualTo(1); SpanData spanData = finishedSpanItems.get(0); - assertEquals(2, spanData.getAttributes().size()); - assertEquals( - "from interceptor", spanData.getAttributes().get(AttributeKey.stringKey("global.attr"))); - assertEquals(10, spanData.getAttributes().get(AttributeKey.longKey("local.attr"))); + assertThat(spanData.getAttributes().size()).isEqualTo(2); + assertThat(spanData.getAttributes().get(AttributeKey.stringKey("global.attr"))) + .isEqualTo("from interceptor"); + assertThat(spanData.getAttributes().get(AttributeKey.longKey("local.attr"))).isEqualTo(10L); } @Test @@ -74,9 +74,9 @@ void verifySpanFiltering() { tracer.spanBuilder("Another span").startSpan().end(); List finishedSpanItems = memorySpanExporter.getFinishedSpanItems(); - assertEquals(2, finishedSpanItems.size()); - assertEquals("One span", finishedSpanItems.get(0).getName()); - assertEquals("Another span", finishedSpanItems.get(1).getName()); + assertThat(finishedSpanItems.size()).isEqualTo(2); + assertThat(finishedSpanItems.get(0).getName()).isEqualTo("One span"); + assertThat(finishedSpanItems.get(1).getName()).isEqualTo("Another span"); } private static class ModifiableSpanData extends DelegatingSpanData { diff --git a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java index c0b381e7d..e71331964 100644 --- a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java +++ b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java @@ -6,6 +6,8 @@ package io.opentelemetry.contrib.metrics.prometheus.clientbridge; import static io.prometheus.client.Collector.doubleToGoString; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanContext; @@ -28,7 +30,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.Function; import javax.annotation.Nullable; @@ -54,6 +55,8 @@ final class MetricAdapter { static final String LABEL_NAME_QUANTILE = "quantile"; static final String LABEL_NAME_LE = "le"; + static final Function sanitizer = new NameSanitizer(); + // Converts a MetricData to a Prometheus MetricFamilySamples. static MetricFamilySamples toMetricFamilySamples(MetricData metricData) { String cleanMetricName = cleanMetricName(metricData.getName()); @@ -99,8 +102,6 @@ static Collector.Type toMetricFamilyType(MetricData metricData) { return Collector.Type.UNKNOWN; } - static final Function sanitizer = new NameSanitizer(); - // Converts a list of points from MetricData to a list of Prometheus Samples. static List toSamples( String name, MetricDataType type, Collection points) { @@ -291,7 +292,7 @@ private static Sample createSample( labelValues, value, toPrometheusExemplar(exemplar), - TimeUnit.MILLISECONDS.convert(timestampNanos, TimeUnit.NANOSECONDS)); + MILLISECONDS.convert(timestampNanos, NANOSECONDS)); } return new Sample( name, @@ -299,7 +300,7 @@ private static Sample createSample( labelValues, value, null, - TimeUnit.MILLISECONDS.convert(timestampNanos, TimeUnit.NANOSECONDS)); + MILLISECONDS.convert(timestampNanos, NANOSECONDS)); } private static io.prometheus.client.exemplars.Exemplar toPrometheusExemplar( @@ -309,7 +310,7 @@ private static io.prometheus.client.exemplars.Exemplar toPrometheusExemplar( return new io.prometheus.client.exemplars.Exemplar( getExemplarValue(exemplar), // Convert to ms for prometheus, truncate nanosecond precision. - TimeUnit.NANOSECONDS.toMillis(exemplar.getEpochNanos()), + NANOSECONDS.toMillis(exemplar.getEpochNanos()), "trace_id", spanContext.getTraceId(), "span_id", diff --git a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java index 3acc1096a..e9c574f92 100644 --- a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java +++ b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.metrics.prometheus.clientbridge; +import static java.util.Collections.unmodifiableList; + import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; @@ -15,7 +17,6 @@ import io.prometheus.client.CollectorRegistry; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.function.Supplier; @@ -79,7 +80,7 @@ public List collect() { for (MetricData metricData : allMetrics) { allSamples.add(MetricAdapter.toMetricFamilySamples(metricData)); } - return Collections.unmodifiableList(allSamples); + return unmodifiableList(allSamples); } } } diff --git a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java index d696a14b7..d79892a27 100644 --- a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java +++ b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java @@ -21,11 +21,12 @@ package io.opentelemetry.contrib.metrics.prometheus.clientbridge; +import static java.util.Collections.emptyList; + import io.opentelemetry.sdk.metrics.data.HistogramPointData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; import java.util.Collection; -import java.util.Collections; import java.util.List; /** Serializes metrics into Prometheus exposition formats. */ @@ -71,7 +72,7 @@ static Collection getPoints(MetricData metricData) { case EXPONENTIAL_HISTOGRAM: return metricData.getExponentialHistogramData().getPoints(); } - return Collections.emptyList(); + return emptyList(); } private Serializer() {} diff --git a/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java b/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java index 7d5d399c4..d97785cca 100644 --- a/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java +++ b/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java @@ -12,7 +12,7 @@ @SuppressWarnings("rawtypes") @AutoService(ComponentProvider.class) -public class AppServerResourceDetector implements ComponentProvider { +public final class AppServerResourceDetector implements ComponentProvider { @Override public Class getType() { diff --git a/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java b/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java index b48f4685a..75d5664a2 100644 --- a/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java +++ b/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java @@ -6,8 +6,7 @@ package io.opentelemetry.contrib.resourceproviders; import static io.opentelemetry.contrib.resourceproviders.JettyAppServer.parseJettyBase; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.nio.file.Files; @@ -15,21 +14,21 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -public class JettyServiceNameDetectorTest { +class JettyServiceNameDetectorTest { @Test void testJettyBase(@TempDir Path tempDir) throws IOException { - assertNull(parseJettyBase(null)); - assertNull(parseJettyBase("")); - assertNull(parseJettyBase("jetty.base=")); - assertEquals(tempDir.toString(), parseJettyBase("jetty.base=" + tempDir).toString()); - assertEquals( - tempDir.toString(), parseJettyBase("foo jetty.base=" + tempDir + " bar").toString()); + assertThat(parseJettyBase(null)).isNull(); + assertThat(parseJettyBase("")).isNull(); + assertThat(parseJettyBase("jetty.base=")).isNull(); + assertThat(parseJettyBase("jetty.base=" + tempDir).toString()).isEqualTo(tempDir.toString()); + assertThat(parseJettyBase("foo jetty.base=" + tempDir + " bar").toString()) + .isEqualTo(tempDir.toString()); Path otherDir = tempDir.resolve("jetty test"); Files.createDirectory(otherDir); - assertEquals(otherDir.toString(), parseJettyBase("jetty.base=" + otherDir).toString()); - assertEquals( - otherDir.toString(), parseJettyBase("foo jetty.base=" + otherDir + " bar").toString()); + assertThat(parseJettyBase("jetty.base=" + otherDir).toString()).isEqualTo(otherDir.toString()); + assertThat(parseJettyBase("foo jetty.base=" + otherDir + " bar").toString()) + .isEqualTo(otherDir.toString()); } } diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java index 43d89b2ef..611dde652 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java @@ -8,7 +8,7 @@ import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.trace.Span; import org.junit.jupiter.api.BeforeAll; -public class AbstractAttachmentTest { +class AbstractAttachmentTest { @BeforeAll static void disableMainThreadCheck() { diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java index 41571a2e4..91a67d3cd 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.annotations.WithSpan; import org.junit.jupiter.api.Test; -public class AgentDisabledByEnvironmentVariableTest extends AbstractAttachmentTest { +class AgentDisabledByEnvironmentVariableTest extends AbstractAttachmentTest { @Test void shouldNotAttachWhenAgentDisabledWithEnvVariable() { diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java index a24c81296..39d941ff3 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.annotations.WithSpan; import org.junit.jupiter.api.Test; -public class AgentDisabledBySystemPropertyTest extends AbstractAttachmentTest { +class AgentDisabledBySystemPropertyTest extends AbstractAttachmentTest { @Test void shouldNotAttachWhenAgentDisabledWithProperty() { diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java index 5d8f201ae..65eabcf02 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.annotations.WithSpan; import org.junit.jupiter.api.Test; -public class RunTimeAttachBasicTest extends AbstractAttachmentTest { +class RunTimeAttachBasicTest extends AbstractAttachmentTest { @Test void shouldAttach() { diff --git a/samplers/README.md b/samplers/README.md index 854d44e61..aee9dee5f 100644 --- a/samplers/README.md +++ b/samplers/README.md @@ -9,7 +9,7 @@ The following samplers support [declarative configuration](https://opentelemetry To use: * Add a dependency on `io.opentelemetry.contrib:opentelemetry-samplers:` -* Follow the [instructions](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/incubator/README.md#file-configuration) to configure OpenTelemetry with declarative configuration. +* Follow the [instructions](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/incubator/README.md#declarative-configuration) to configure OpenTelemetry with declarative configuration. * Configure the `.tracer_provider.sampler` to include the `rule_based_routing` sampler. NOTE: Not yet available for use with the OTEL java agent, but should be in the near future. Please check back for updates. diff --git a/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java b/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java index 45f341897..8024ab590 100644 --- a/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java +++ b/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider; import io.opentelemetry.sdk.trace.samplers.Sampler; -public class LinksParentAlwaysOnSamplerProvider implements ConfigurableSamplerProvider { +public final class LinksParentAlwaysOnSamplerProvider implements ConfigurableSamplerProvider { @Override public Sampler createSampler(ConfigProperties config) { return LinksBasedSampler.create(Sampler.parentBased(Sampler.alwaysOn())); diff --git a/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java b/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java index 02611c9d5..c39603352 100644 --- a/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java +++ b/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java @@ -38,7 +38,7 @@ class RuleBasedRoutingSamplerComponentProviderTest { @Test void endToEnd() { String yaml = - "file_format: 0.4\n" + "file_format: 1.0-rc.1\n" + "tracer_provider:\n" + " sampler:\n" + " parent_based:\n" diff --git a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java index 05a4301e6..62b1bee31 100644 --- a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java +++ b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java @@ -63,7 +63,7 @@ public void setup() { } @Test - public void testThatThrowsOnNullParameter() { + void testThatThrowsOnNullParameter() { assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> new RuleBasedRoutingSampler(patterns, SPAN_KIND, null)); @@ -98,7 +98,7 @@ public void testThatThrowsOnNullParameter() { } @Test - public void testThatDelegatesIfNoRulesGiven() { + void testThatDelegatesIfNoRulesGiven() { RuleBasedRoutingSampler sampler = RuleBasedRoutingSampler.builder(SPAN_KIND, delegate).build(); // no http.url attribute @@ -117,7 +117,7 @@ public void testThatDelegatesIfNoRulesGiven() { } @Test - public void testDropOnExactMatch() { + void testDropOnExactMatch() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); assertThat(shouldSample(sampler, "https://example.com/healthcheck").getDecision()) @@ -125,7 +125,7 @@ public void testDropOnExactMatch() { } @Test - public void testDelegateOnDifferentKind() { + void testDelegateOnDifferentKind() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SpanKind.CLIENT, delegate)).build(); assertThat(shouldSample(sampler, "https://example.com/healthcheck").getDecision()) @@ -134,7 +134,7 @@ public void testDelegateOnDifferentKind() { } @Test - public void testDelegateOnNoMatch() { + void testDelegateOnNoMatch() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); assertThat(shouldSample(sampler, "https://example.com/customers").getDecision()) @@ -143,7 +143,7 @@ public void testDelegateOnNoMatch() { } @Test - public void testDelegateOnMalformedUrl() { + void testDelegateOnMalformedUrl() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); assertThat(shouldSample(sampler, "abracadabra").getDecision()) @@ -158,7 +158,7 @@ public void testDelegateOnMalformedUrl() { } @Test - public void testVerifiesAllGivenAttributes() { + void testVerifiesAllGivenAttributes() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); Attributes attributes = Attributes.of(URL_PATH, "/actuator/info"); diff --git a/settings.gradle.kts b/settings.gradle.kts index 5502252e7..13de5fd7e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,6 @@ pluginManagement { plugins { - id("com.gradleup.shadow") version "9.0.2" + id("com.gradleup.shadow") version "9.1.0" id("io.github.gradle-nexus.publish-plugin") version "2.0.0" id("com.gradle.develocity") version "4.1.1" } @@ -29,12 +29,17 @@ develocity { publishing.onlyIf { System.getenv("CI") != null } termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use") termsOfUseAgree.set("yes") + + buildScanPublished { + File("build-scan.txt").printWriter().use { writer -> + writer.println(buildScanUri) + } + } } } rootProject.name = "opentelemetry-java-contrib" -include(":all") include(":aws-resources") include(":aws-xray") include(":aws-xray-propagator") @@ -45,7 +50,6 @@ include(":cloudfoundry-resources") include(":consistent-sampling") include(":dependencyManagement") include(":disk-buffering") -include(":example") include(":ibm-mq-metrics") include(":jfr-events") include(":jfr-connection") diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java index 189934689..8a5a4b643 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.stacktrace; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.SEVERE; + import com.google.auto.service.AutoService; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; @@ -51,7 +54,7 @@ static long getMinDuration(ConfigProperties properties) { log.fine("Stack traces capture is disabled"); } else { log.log( - Level.FINE, + FINE, "Stack traces will be added to spans with a minimum duration of {0} nanos", minDuration); } @@ -71,7 +74,7 @@ static Predicate getFilterPredicate(ConfigProperties properties) { if (filter == null) { // if value is set, lack of filtering is likely an error and must be reported - Level disabledLogLevel = filterClass != null ? Level.SEVERE : Level.FINE; + Level disabledLogLevel = filterClass != null ? SEVERE : FINE; log.log(disabledLogLevel, "Span stacktrace filtering disabled"); return span -> true; } else { diff --git a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java index 4b8f999f4..ca1517480 100644 --- a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java +++ b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java @@ -15,7 +15,7 @@ import java.util.function.Predicate; import org.junit.jupiter.api.Test; -public class StackTraceAutoConfigTest { +class StackTraceAutoConfigTest { @Test void defaultConfig() { diff --git a/version.gradle.kts b/version.gradle.kts index e4f74f0e1..9ea6b805e 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,5 +1,5 @@ -val stableVersion = "1.49.0-SNAPSHOT" -val alphaVersion = "1.49.0-alpha-SNAPSHOT" +val stableVersion = "1.50.0-SNAPSHOT" +val alphaVersion = "1.50.0-alpha-SNAPSHOT" allprojects { if (findProperty("otel.stable") != "true") { From 1337b7803715109015c58123bb00a7b89109c622 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 15 Sep 2025 11:37:33 +0200 Subject: [PATCH 44/44] update --- dependencyManagement/build.gradle.kts | 2 +- gcp-auth-extension/build.gradle.kts | 12 ++----- ...thAutoConfigurationCustomizerProvider.java | 10 ++---- ...rativeConfigurationCustomizerProvider.java | 4 +-- span-stacktrace/build.gradle.kts | 13 ------- .../stacktrace/StackTraceAutoConfig.java | 17 +++++----- .../StackTraceComponentProvider.java | 34 ------------------- .../StackTraceComponentProviderTest.java | 32 ----------------- 8 files changed, 16 insertions(+), 108 deletions(-) delete mode 100644 span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java delete mode 100644 span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 637f8fbac..015c3b773 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -2,7 +2,7 @@ plugins { `java-platform` } -val otelInstrumentationVersion = "2.19.0-alpha" +val otelInstrumentationVersion = "2.20.0-alpha" val semconvVersion = "1.37.0" javaPlatform { diff --git a/gcp-auth-extension/build.gradle.kts b/gcp-auth-extension/build.gradle.kts index 77625afde..ed97129fc 100644 --- a/gcp-auth-extension/build.gradle.kts +++ b/gcp-auth-extension/build.gradle.kts @@ -22,7 +22,7 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-api") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") - compileOnly("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") + compileOnly("io.opentelemetry.instrumentation:opentelemetry-declarative-config-bridge") compileOnly("io.opentelemetry:opentelemetry-exporter-otlp") // Only dependencies added to `implementation` configuration will be picked up by Shadow plugin @@ -40,7 +40,7 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations") - testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") + testImplementation("io.opentelemetry.instrumentation:opentelemetry-declarative-config-bridge") testImplementation("org.awaitility:awaitility") testImplementation("org.mockito:mockito-inline") @@ -137,11 +137,3 @@ tasks.register("IntegrationTestUserCreds") { "-Dmockserver.logLevel=trace" ) } - -// todo remove when https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/14497 is merged -configurations.all { - resolutionStrategy { - force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.20.0-alpha-SNAPSHOT") - force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.19.0") - } -} diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index 6141a32e1..ae904c6bc 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -6,14 +6,13 @@ package io.opentelemetry.contrib.gcp.auth; import static io.opentelemetry.api.common.AttributeKey.stringKey; -import static java.util.Arrays.stream; +import static java.util.Collections.singletonList; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toMap; import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; import com.google.common.annotations.VisibleForTesting; -import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.contrib.gcp.auth.GoogleAuthException.Reason; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; @@ -31,7 +30,6 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.export.SpanExporter; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -182,8 +180,7 @@ static List targetSignals(ConfigProperties configProperties) { return Objects.requireNonNull( ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValue( configProperties, - (properties, name) -> - properties.getList(name, Collections.singletonList(SIGNAL_TYPE_ALL)))); + (properties, name) -> properties.getList(name, singletonList(SIGNAL_TYPE_ALL)))); } // Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and @@ -262,8 +259,7 @@ static Optional getQuotaProjectId(ConfigProperties configProperties) { private static Resource customizeResource(Resource resource, ConfigProperties configProperties) { Resource res = Resource.create( - Attributes.of( - stringKey(GCP_USER_PROJECT_ID_KEY), getProjectId(configProperties))); + Attributes.of(stringKey(GCP_USER_PROJECT_ID_KEY), getProjectId(configProperties))); return resource.merge(res); } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java index 8ac60431f..786df2739 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java @@ -12,8 +12,8 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; import com.google.common.annotations.VisibleForTesting; -import io.opentelemetry.instrumentation.api.incubator.config.bridge.ConfigPropertiesUtil; -import io.opentelemetry.instrumentation.api.incubator.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; +import io.opentelemetry.instrumentation.config.bridge.ConfigPropertiesUtil; +import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; diff --git a/span-stacktrace/build.gradle.kts b/span-stacktrace/build.gradle.kts index 2a32b8b50..4033b0177 100644 --- a/span-stacktrace/build.gradle.kts +++ b/span-stacktrace/build.gradle.kts @@ -15,13 +15,8 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") - compileOnly("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") - testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator") compileOnly("io.opentelemetry.semconv:opentelemetry-semconv") testImplementation("io.opentelemetry.semconv:opentelemetry-semconv") @@ -31,11 +26,3 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-exporter-logging") } - -// todo remove when https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/14497 is merged -configurations.all { - resolutionStrategy { - force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.20.0-alpha-SNAPSHOT") - force("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.19.0") - } -} diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java index 8a5a4b643..3a427b7e3 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java @@ -26,26 +26,25 @@ public class StackTraceAutoConfig implements AutoConfigurationCustomizerProvider private static final Logger log = Logger.getLogger(StackTraceAutoConfig.class.getName()); - static final String PREFIX = "otel.java.experimental.span-stacktrace."; - private static final String CONFIG_MIN_DURATION = PREFIX + "min.duration"; + private static final String CONFIG_MIN_DURATION = + "otel.java.experimental.span-stacktrace.min.duration"; private static final Duration CONFIG_MIN_DURATION_DEFAULT = Duration.ofMillis(5); - private static final String CONFIG_FILTER = PREFIX + "filter"; + + private static final String CONFIG_FILTER = "otel.java.experimental.span-stacktrace.filter"; @Override public void customize(AutoConfigurationCustomizer config) { config.addTracerProviderCustomizer( (providerBuilder, properties) -> { - if (getMinDuration(properties) >= 0) { - providerBuilder.addSpanProcessor(create(properties)); + long minDuration = getMinDuration(properties); + if (minDuration >= 0) { + Predicate filter = getFilterPredicate(properties); + providerBuilder.addSpanProcessor(new StackTraceSpanProcessor(minDuration, filter)); } return providerBuilder; }); } - static StackTraceSpanProcessor create(ConfigProperties properties) { - return new StackTraceSpanProcessor(getMinDuration(properties), getFilterPredicate(properties)); - } - // package-private for testing static long getMinDuration(ConfigProperties properties) { long minDuration = diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java deleted file mode 100644 index a71275ead..000000000 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProvider.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.stacktrace; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; -import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; -import io.opentelemetry.sdk.trace.SpanProcessor; - -@SuppressWarnings("rawtypes") -@AutoService(ComponentProvider.class) -public class StackTraceComponentProvider implements ComponentProvider { - @Override - public String getName() { - return "experimental-stacktrace"; - } - - @Override - public SpanProcessor create(DeclarativeConfigProperties config) { - return StackTraceAutoConfig.create( - new DeclarativeConfigPropertiesBridgeBuilder() - .addMapping(StackTraceAutoConfig.PREFIX, "") - .build(config)); - } - - @Override - public Class getType() { - return SpanProcessor.class; - } -} diff --git a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java deleted file mode 100644 index a2b4c4212..000000000 --- a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceComponentProviderTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.stacktrace; - -import static org.assertj.core.api.Assertions.assertThat; - -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import org.junit.jupiter.api.Test; - -class StackTraceComponentProviderTest { - @Test - void endToEnd() { - String yaml = - "file_format: 0.4\n" - + "tracer_provider:\n" - + " processors:\n" - + " - experimental-stacktrace:\n"; - - OpenTelemetrySdk openTelemetrySdk = - DeclarativeConfiguration.parseAndCreate( - new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); - - assertThat(openTelemetrySdk.getSdkTracerProvider().toString()) - .contains("StackTraceSpanProcessor"); - } -}