diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AfterAgentListener.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AfterAgentListener.java index c1e3112520..58b73c1de4 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AfterAgentListener.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AfterAgentListener.java @@ -5,6 +5,7 @@ import com.google.auto.service.AutoService; import com.microsoft.applicationinsights.agent.internal.configuration.Configuration; +import com.microsoft.applicationinsights.agent.internal.configuration.SnippetConfiguration; import com.microsoft.applicationinsights.agent.internal.httpclient.LazyHttpClient; import com.microsoft.applicationinsights.agent.internal.profiler.ProfilingInitializer; import com.microsoft.applicationinsights.agent.internal.telemetry.TelemetryClient; @@ -44,5 +45,14 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetr logger.warn("Failed to initialize profiler", e); } } + + // Initialize browser SDK loader snippet after GlobalOpenTelemetry is set + if (telemetryClient != null && telemetryClient.getConnectionString() != null) { + Configuration.BrowserSdkLoader sdkLoaderConfig = configuration.preview.browserSdkLoader; + if (sdkLoaderConfig.enabled) { + String connStr = configuration.connectionString; + SnippetConfiguration.initializeSnippet(connStr); + } + } } } diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AiConfigCustomizer.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AiConfigCustomizer.java index 5d17bb98b6..f823ab1356 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AiConfigCustomizer.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AiConfigCustomizer.java @@ -22,9 +22,11 @@ public Map apply(ConfigProperties otelConfig) { Map properties = new HashMap<>(); - properties.put( - "applicationinsights.internal.micrometer.step.millis", - Long.toString(SECONDS.toMillis(configuration.metricIntervalSeconds))); + String micrometerStepMillis = + Long.toString(SECONDS.toMillis(configuration.metricIntervalSeconds)); + properties.put("applicationinsights.internal.micrometer.step.millis", micrometerStepMillis); + // Also set as system property so AzureMonitorRegistryConfig can access it + System.setProperty("applicationinsights.internal.micrometer.step.millis", micrometerStepMillis); properties.put( "otel.metric.export.interval", @@ -101,7 +103,10 @@ public Map apply(ConfigProperties otelConfig) { sb.append(customInstrumentation.methodName); sb.append(']'); } - properties.put("applicationinsights.internal.methods.include", sb.toString()); + String customInstrConfig = sb.toString(); + properties.put("applicationinsights.internal.methods.include", customInstrConfig); + // Also set as system property so MethodInstrumentationModule can access it + System.setProperty("applicationinsights.internal.methods.include", customInstrConfig); } properties.put("otel.propagators", DelegatingPropagatorProvider.NAME); diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/FirstEntryPoint.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/FirstEntryPoint.java index 39cbfa39bd..8e0b4b12a2 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/FirstEntryPoint.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/FirstEntryPoint.java @@ -23,7 +23,6 @@ import io.opentelemetry.javaagent.bootstrap.InternalLogger; import io.opentelemetry.javaagent.bootstrap.JavaagentFileHolder; import io.opentelemetry.javaagent.tooling.LoggingCustomizer; -import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; @@ -77,7 +76,7 @@ public String name() { } @Override - public void init(EarlyInitAgentConfig earlyConfig) { + public void init() { try { if (DEBUG_SIGNED_JAR_ACCESS) { JarVerifierClassFileTransformer transformer = new JarVerifierClassFileTransformer(); diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java index 6cc887b40a..77b6fd409d 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java @@ -34,7 +34,6 @@ import com.microsoft.applicationinsights.agent.internal.configuration.Configuration.SamplingTelemetryType; import com.microsoft.applicationinsights.agent.internal.configuration.ConfigurationBuilder; import com.microsoft.applicationinsights.agent.internal.configuration.RpConfiguration; -import com.microsoft.applicationinsights.agent.internal.configuration.SnippetConfiguration; import com.microsoft.applicationinsights.agent.internal.exporter.AgentLogExporter; import com.microsoft.applicationinsights.agent.internal.exporter.AgentMetricExporter; import com.microsoft.applicationinsights.agent.internal.exporter.AgentSpanExporter; @@ -215,9 +214,8 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) { } if (telemetryClient.getConnectionString() != null) { - if (configuration.preview.browserSdkLoader.enabled) { - SnippetConfiguration.initializeSnippet(configuration.connectionString); - } + // Snippet initialization moved to AfterAgentListener to avoid early GlobalOpenTelemetry.get() + // call } // TODO (trask) add this method to AutoConfigurationCustomizer upstream? @@ -760,15 +758,27 @@ private static List getLogProcessorConfigs(Configuration config || processor.type == Configuration.ProcessorType.LOG) .collect(Collectors.toCollection(ArrayList::new)); } + + // SDK internal metrics that should not be exported to customers + private static final String[] SDK_INTERNAL_METRICS_TO_DROP = { + "otel.sdk.span.live", + "otel.sdk.span.started", + "otel.sdk.log.created" + }; private static SdkMeterProviderBuilder configureMetrics( SdkMeterProviderBuilder builder, Configuration configuration) { - // drop internal OpenTelemetry SDK metrics + // drop internal OpenTelemetry SDK metrics (legacy format) drop(builder, "io.opentelemetry.sdk.trace", "queueSize"); drop(builder, "io.opentelemetry.sdk.trace", "processedSpans"); drop(builder, "io.opentelemetry.sdk.logs", "queueSize"); drop(builder, "io.opentelemetry.sdk.logs", "processedLogs"); + + // drop SDK internal metrics added in OpenTelemetry 2.24.0 + for (String metricName : SDK_INTERNAL_METRICS_TO_DROP) { + dropByName(builder, metricName); + } if (configuration.internal.preAggregatedStandardMetrics.enabled) { AiViewRegistry.registerViews(builder); @@ -777,9 +787,15 @@ private static SdkMeterProviderBuilder configureMetrics( } private static void drop( - SdkMeterProviderBuilder builder, String meterName, String processedSpans) { + SdkMeterProviderBuilder builder, String meterName, String metricName) { + builder.registerView( + InstrumentSelector.builder().setMeterName(meterName).setName(metricName).build(), + View.builder().setAggregation(Aggregation.drop()).build()); + } + + private static void dropByName(SdkMeterProviderBuilder builder, String metricName) { builder.registerView( - InstrumentSelector.builder().setMeterName(meterName).setName(processedSpans).build(), + InstrumentSelector.builder().setName(metricName).build(), View.builder().setAggregation(Aggregation.drop()).build()); } diff --git a/agent/agent/build.gradle.kts b/agent/agent/build.gradle.kts index a8f6051973..752f970b21 100644 --- a/agent/agent/build.gradle.kts +++ b/agent/agent/build.gradle.kts @@ -84,6 +84,7 @@ tasks { exclude(dependency("io.opentelemetry:opentelemetry-api")) exclude(dependency("io.opentelemetry:opentelemetry-context")) exclude(dependency("io.opentelemetry:opentelemetry-api-incubator")) + exclude(dependency("io.opentelemetry:opentelemetry-common")) } } diff --git a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java index 40ebaa951a..97b08c2f22 100644 --- a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java +++ b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java @@ -13,10 +13,10 @@ import com.microsoft.applicationinsights.agent.bootstrap.BytecodeUtil; import com.microsoft.azure.functions.rpc.messages.InvocationRequest; import com.microsoft.azure.functions.rpc.messages.RpcTraceContext; -import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; @@ -61,9 +61,7 @@ public static Scope methodEnter(@Advice.Argument(0) InvocationRequest request) { RpcTraceContext traceContext = request.getTraceContext(); Context extractedContext = - GlobalOpenTelemetry.getPropagators() - .getTextMapPropagator() - .extract(Context.root(), traceContext, GETTER); + W3CTraceContextPropagator.getInstance().extract(Context.root(), traceContext, GETTER); SpanContext spanContext = Span.fromContext(extractedContext).getSpanContext(); // recreate SpanContext to override the trace flags since the host currently always sends "00" diff --git a/agent/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/ai/MethodInstrumentationModule.java b/agent/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/ai/MethodInstrumentationModule.java index 036a1f33b0..e06196ae5a 100644 --- a/agent/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/ai/MethodInstrumentationModule.java +++ b/agent/instrumentation/methods/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/ai/MethodInstrumentationModule.java @@ -11,9 +11,9 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; +import static java.util.Collections.emptyMap; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; @@ -32,9 +32,11 @@ public class MethodInstrumentationModule extends InstrumentationModule { public MethodInstrumentationModule() { super("ai-methods"); + // Read configuration from system property (set by AiConfigCustomizer) + String methodsConfig = System.getProperty(TRACE_METHODS_CONFIG); + Map> classMethodsToTrace = - MethodsConfigurationParser.parse( - AgentInstrumentationConfig.get().getString(TRACE_METHODS_CONFIG)); + methodsConfig != null ? MethodsConfigurationParser.parse(methodsConfig) : emptyMap(); typeInstrumentations = classMethodsToTrace.entrySet().stream() diff --git a/agent/instrumentation/micrometer-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/ai/AzureMonitorRegistryConfig.java b/agent/instrumentation/micrometer-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/ai/AzureMonitorRegistryConfig.java index b3865ecd99..dd3cc7820a 100644 --- a/agent/instrumentation/micrometer-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/ai/AzureMonitorRegistryConfig.java +++ b/agent/instrumentation/micrometer-1.0/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/ai/AzureMonitorRegistryConfig.java @@ -4,25 +4,40 @@ package io.opentelemetry.javaagent.instrumentation.micrometer.ai; import io.micrometer.core.instrument.step.StepRegistryConfig; -import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.time.Duration; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.annotation.Nullable; public class AzureMonitorRegistryConfig implements StepRegistryConfig { + private static final Logger logger = Logger.getLogger(AzureMonitorRegistryConfig.class.getName()); + private static final Duration DEFAULT_STEP = Duration.ofSeconds(60); + private final Duration step; @Nullable private final String namespace; public static final AzureMonitorRegistryConfig INSTANCE = new AzureMonitorRegistryConfig(); private AzureMonitorRegistryConfig() { - step = - AgentInstrumentationConfig.get() - .getDuration( - "applicationinsights.internal.micrometer.step.millis", Duration.ofSeconds(60)); - namespace = - AgentInstrumentationConfig.get() - .getString("applicationinsights.internal.micrometer.namespace"); + // Read configuration from system property (set by AiConfigCustomizer) + String stepConfigValue = + System.getProperty("applicationinsights.internal.micrometer.step.millis"); + + Duration configuredStep = DEFAULT_STEP; + if (stepConfigValue != null) { + try { + configuredStep = Duration.ofMillis(Long.parseLong(stepConfigValue)); + } catch (NumberFormatException ex) { + logger.log( + Level.WARNING, + "Invalid value for applicationinsights.internal.micrometer.step.millis: {0}, using default of {1}", + new Object[] {stepConfigValue, DEFAULT_STEP}); + } + } + step = configuredStep; + + namespace = System.getProperty("applicationinsights.internal.micrometer.namespace"); } @Override diff --git a/buildSrc/src/main/kotlin/ai.shadow-conventions.gradle.kts b/buildSrc/src/main/kotlin/ai.shadow-conventions.gradle.kts index 35f12ccf56..ada1585f62 100644 --- a/buildSrc/src/main/kotlin/ai.shadow-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/ai.shadow-conventions.gradle.kts @@ -22,13 +22,27 @@ tasks.withType().configureEach { // Exclude resource providers since they live in the agent class loader exclude("io.opentelemetry.instrumentation.resources.*") exclude("io.opentelemetry.instrumentation.spring.resources.*") + // Exclude already-shaded classes from upstream agent to prevent double relocation + exclude("io.opentelemetry.javaagent.shaded.instrumentation.*") } // relocate(OpenTelemetry API) since these classes live in the bootstrap class loader - relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api") - relocate("io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv") - relocate("io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context") - relocate("io.opentelemetry.common", "io.opentelemetry.javaagent.shaded.io.opentelemetry.common") + relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api") { + // Exclude already-shaded classes from upstream agent to prevent double relocation + exclude("io.opentelemetry.javaagent.shaded.io.opentelemetry.api.*") + } + relocate("io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv") { + // Exclude already-shaded classes from upstream agent to prevent double relocation + exclude("io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv.*") + } + relocate("io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context") { + // Exclude already-shaded classes from upstream agent to prevent double relocation + exclude("io.opentelemetry.javaagent.shaded.io.opentelemetry.context.*") + } + relocate("io.opentelemetry.common", "io.opentelemetry.javaagent.shaded.io.opentelemetry.common") { + // Exclude already-shaded classes from upstream agent to prevent double relocation + exclude("io.opentelemetry.javaagent.shaded.io.opentelemetry.common.*") + } // relocate(the OpenTelemetry extensions that are used by instrumentation modules) // these extensions live in the AgentClassLoader, and are injected into the user's class loader diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 417076b7de..96ecc42e1b 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -7,9 +7,9 @@ data class DependencySet(val group: String, val version: String, val modules: Li val dependencyVersions = hashMapOf() rootProject.extra["versions"] = dependencyVersions -val otelSdkVersion = "1.55.0" -val otelInstrumentationAlphaVersion = "2.21.0-alpha" -val otelInstrumentationVersion = "2.21.0" +val otelSdkVersion = "1.58.0" +val otelInstrumentationAlphaVersion = "2.24.0-alpha" +val otelInstrumentationVersion = "2.24.0" val otelContribVersion = "1.48.0" rootProject.extra["otelInstrumentationVersion"] = otelInstrumentationVersion