From 5171b943e765a93c13ade56361bbfe2e67347c42 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:50:00 +0000 Subject: [PATCH 01/15] Initial plan From de178c017d7e3b99a53dbfe45dbcb490abb981db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 19:58:46 +0000 Subject: [PATCH 02/15] Update OpenTelemetry versions to 1.58.0 / 2.24.0 (with compilation errors) Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- dependencyManagement/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 From a4d6d074d45ed542965fb554ecde9870a8fe6c02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 20:07:25 +0000 Subject: [PATCH 03/15] Fix compilation errors after OpenTelemetry upgrade Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../agent/internal/init/FirstEntryPoint.java | 3 +- .../ai/MethodInstrumentationModule.java | 12 ++++++-- .../ai/AzureMonitorRegistryConfig.java | 29 ++++++++++++++----- 3 files changed, 31 insertions(+), 13 deletions(-) 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/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..b65f01df39 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,12 @@ 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.api.GlobalOpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; @@ -32,9 +35,12 @@ public class MethodInstrumentationModule extends InstrumentationModule { public MethodInstrumentationModule() { super("ai-methods"); + DeclarativeConfigProperties config = + DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "ai-methods"); + String include = config.getString(TRACE_METHODS_CONFIG); + Map> classMethodsToTrace = - MethodsConfigurationParser.parse( - AgentInstrumentationConfig.get().getString(TRACE_METHODS_CONFIG)); + include != null ? MethodsConfigurationParser.parse(include) : 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..e6c2bc90aa 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,7 +4,9 @@ package io.opentelemetry.javaagent.instrumentation.micrometer.ai; import io.micrometer.core.instrument.step.StepRegistryConfig; -import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import java.time.Duration; import javax.annotation.Nullable; @@ -16,13 +18,24 @@ public class AzureMonitorRegistryConfig implements StepRegistryConfig { 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"); + DeclarativeConfigProperties config = + DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "micrometer"); + + // Get step duration in milliseconds, default to 60 seconds + String stepMillisStr = config.getString("applicationinsights.internal.micrometer.step.millis"); + Duration stepValue; + if (stepMillisStr != null) { + try { + stepValue = Duration.ofMillis(Long.parseLong(stepMillisStr)); + } catch (NumberFormatException e) { + stepValue = Duration.ofSeconds(60); + } + } else { + stepValue = Duration.ofSeconds(60); + } + step = stepValue; + + namespace = config.getString("applicationinsights.internal.micrometer.namespace"); } @Override From 82dca7bdf6689b14edb48713fd841428f31e0a40 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 20:16:45 +0000 Subject: [PATCH 04/15] Address code review feedback: Add logging for config errors Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../ai/AzureMonitorRegistryConfig.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) 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 e6c2bc90aa..b6b24d1b75 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 @@ -8,10 +8,15 @@ import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; 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; @@ -23,17 +28,18 @@ private AzureMonitorRegistryConfig() { // Get step duration in milliseconds, default to 60 seconds String stepMillisStr = config.getString("applicationinsights.internal.micrometer.step.millis"); - Duration stepValue; + Duration parsedStep = DEFAULT_STEP; if (stepMillisStr != null) { try { - stepValue = Duration.ofMillis(Long.parseLong(stepMillisStr)); + parsedStep = Duration.ofMillis(Long.parseLong(stepMillisStr)); } catch (NumberFormatException e) { - stepValue = Duration.ofSeconds(60); + logger.log( + Level.WARNING, + "Invalid value for applicationinsights.internal.micrometer.step.millis: {0}, using default of {1}", + new Object[] {stepMillisStr, DEFAULT_STEP}); } - } else { - stepValue = Duration.ofSeconds(60); } - step = stepValue; + step = parsedStep; namespace = config.getString("applicationinsights.internal.micrometer.namespace"); } From 5fcd1dec68a78999cee5ec86d3f33c8c5ae7290d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 22:23:00 +0000 Subject: [PATCH 05/15] Fix unit tests: Add system property fallback for configuration Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../methods/ai/MethodInstrumentationModule.java | 6 ++++++ .../ai/AzureMonitorRegistryConfig.java | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) 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 b65f01df39..559e2a68db 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 @@ -35,10 +35,16 @@ public class MethodInstrumentationModule extends InstrumentationModule { public MethodInstrumentationModule() { super("ai-methods"); + // First try to get config from DeclarativeConfigUtil DeclarativeConfigProperties config = DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "ai-methods"); String include = config.getString(TRACE_METHODS_CONFIG); + // Fallback to system property if not found in declarative config + if (include == null) { + include = System.getProperty(TRACE_METHODS_CONFIG); + } + Map> classMethodsToTrace = include != null ? MethodsConfigurationParser.parse(include) : emptyMap(); 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 b6b24d1b75..c39d3d2011 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 @@ -25,9 +25,14 @@ public class AzureMonitorRegistryConfig implements StepRegistryConfig { private AzureMonitorRegistryConfig() { DeclarativeConfigProperties config = DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "micrometer"); - + // Get step duration in milliseconds, default to 60 seconds String stepMillisStr = config.getString("applicationinsights.internal.micrometer.step.millis"); + // Fallback to system property if not found in declarative config + if (stepMillisStr == null) { + stepMillisStr = System.getProperty("applicationinsights.internal.micrometer.step.millis"); + } + Duration parsedStep = DEFAULT_STEP; if (stepMillisStr != null) { try { @@ -40,8 +45,13 @@ private AzureMonitorRegistryConfig() { } } step = parsedStep; - - namespace = config.getString("applicationinsights.internal.micrometer.namespace"); + + String namespaceValue = config.getString("applicationinsights.internal.micrometer.namespace"); + // Fallback to system property if not found in declarative config + if (namespaceValue == null) { + namespaceValue = System.getProperty("applicationinsights.internal.micrometer.namespace"); + } + namespace = namespaceValue; } @Override From c54d4e3cf69975ab0bdc481cd8195d5b498c1ea6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 23:27:23 +0000 Subject: [PATCH 06/15] Initial investigation: AzureFunctionsTest failing Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../instrumentation/methods/ai/MethodInstrumentationModule.java | 2 +- .../micrometer/ai/AzureMonitorRegistryConfig.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 559e2a68db..ebd6ed5d0b 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 @@ -39,7 +39,7 @@ public MethodInstrumentationModule() { DeclarativeConfigProperties config = DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "ai-methods"); String include = config.getString(TRACE_METHODS_CONFIG); - + // Fallback to system property if not found in declarative config if (include == null) { include = System.getProperty(TRACE_METHODS_CONFIG); 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 c39d3d2011..8171ac825e 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 @@ -32,7 +32,7 @@ private AzureMonitorRegistryConfig() { if (stepMillisStr == null) { stepMillisStr = System.getProperty("applicationinsights.internal.micrometer.step.millis"); } - + Duration parsedStep = DEFAULT_STEP; if (stepMillisStr != null) { try { From 3cfac4716c4877e383013a1984b9294746fdf8fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 23:31:13 +0000 Subject: [PATCH 07/15] Fix AzureFunctionsTest: Use W3CTraceContextPropagator directly After OpenTelemetry upgrade to 2.24.0, GlobalOpenTelemetry.getPropagators() doesn't work correctly in test environments. Changed to use W3CTraceContextPropagator.getInstance() directly for context extraction. Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../azurefunctions/InvocationInstrumentation.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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..401cc57228 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,8 +61,7 @@ public static Scope methodEnter(@Advice.Argument(0) InvocationRequest request) { RpcTraceContext traceContext = request.getTraceContext(); Context extractedContext = - GlobalOpenTelemetry.getPropagators() - .getTextMapPropagator() + W3CTraceContextPropagator.getInstance() .extract(Context.root(), traceContext, GETTER); SpanContext spanContext = Span.fromContext(extractedContext).getSpanContext(); From b06959a998b041925593a892d85b1df33660a17b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 00:31:17 +0000 Subject: [PATCH 08/15] Investigation: LinkageError due to double relocation of upstream agent Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../azurefunctions/InvocationInstrumentation.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 401cc57228..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 @@ -61,8 +61,7 @@ public static Scope methodEnter(@Advice.Argument(0) InvocationRequest request) { RpcTraceContext traceContext = request.getTraceContext(); Context extractedContext = - W3CTraceContextPropagator.getInstance() - .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" From 19c467dc8fd8c5cf9027240accba868eeb8a92e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 00:57:05 +0000 Subject: [PATCH 09/15] Fix LinkageError: Exclude opentelemetry-common from javaagent libs The upstream OpenTelemetry javaagent already includes io.opentelemetry.common classes (properly shaded). Our build was including the same classes, causing classloader conflicts. Added exclusion to prevent double inclusion. Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- agent/agent/build.gradle.kts | 1 + .../kotlin/ai.shadow-conventions.gradle.kts | 22 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) 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/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 From 214fe7d5ad787bbdcffacb61099f3dc1e954ba83 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 02:28:19 +0000 Subject: [PATCH 10/15] Fix smoke tests: Set config properties as system properties AiConfigCustomizer properties need to be accessible by instrumentation modules that load early. Setting them as system properties ensures they're available through the System.getProperty() fallback mechanism. Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../agent/internal/init/AiConfigCustomizer.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) 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..e60abaf8cd 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,10 @@ 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 +102,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); From af85c09ec69bfa07f70c859f8e3cdf7215c548cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 23:23:51 +0000 Subject: [PATCH 11/15] Investigation: GlobalOpenTelemetry.set already called error Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../agent/internal/init/AiConfigCustomizer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 e60abaf8cd..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,7 +22,8 @@ public Map apply(ConfigProperties otelConfig) { Map properties = new HashMap<>(); - String micrometerStepMillis = 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); From f09b663ab3d7ef53a91580d9e29710cae74dd1a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 23:38:45 +0000 Subject: [PATCH 12/15] Fix GlobalOpenTelemetry timing: Move snippet init to AfterAgentListener Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../internal/init/AfterAgentListener.java | 10 ++++++ .../agent/internal/init/SecondEntryPoint.java | 5 +-- .../ai/MethodInstrumentationModule.java | 16 ++------- .../ai/AzureMonitorRegistryConfig.java | 33 +++++-------------- 4 files changed, 23 insertions(+), 41 deletions(-) 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..c6c90a6ac1 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/SecondEntryPoint.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java index 6cc887b40a..eac026f2f8 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,7 @@ 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? 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 ebd6ed5d0b..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 @@ -14,9 +14,6 @@ import static java.util.Collections.emptyMap; import com.google.auto.service.AutoService; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; @@ -35,18 +32,11 @@ public class MethodInstrumentationModule extends InstrumentationModule { public MethodInstrumentationModule() { super("ai-methods"); - // First try to get config from DeclarativeConfigUtil - DeclarativeConfigProperties config = - DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "ai-methods"); - String include = config.getString(TRACE_METHODS_CONFIG); - - // Fallback to system property if not found in declarative config - if (include == null) { - include = System.getProperty(TRACE_METHODS_CONFIG); - } + // Read configuration from system property (set by AiConfigCustomizer) + String methodsConfig = System.getProperty(TRACE_METHODS_CONFIG); Map> classMethodsToTrace = - include != null ? MethodsConfigurationParser.parse(include) : emptyMap(); + 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 8171ac825e..fc4998a646 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,9 +4,6 @@ package io.opentelemetry.javaagent.instrumentation.micrometer.ai; import io.micrometer.core.instrument.step.StepRegistryConfig; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import java.time.Duration; import java.util.logging.Level; import java.util.logging.Logger; @@ -23,35 +20,23 @@ public class AzureMonitorRegistryConfig implements StepRegistryConfig { public static final AzureMonitorRegistryConfig INSTANCE = new AzureMonitorRegistryConfig(); private AzureMonitorRegistryConfig() { - DeclarativeConfigProperties config = - DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "micrometer"); + // Read configuration from system property (set by AiConfigCustomizer) + String stepConfigValue = System.getProperty("applicationinsights.internal.micrometer.step.millis"); - // Get step duration in milliseconds, default to 60 seconds - String stepMillisStr = config.getString("applicationinsights.internal.micrometer.step.millis"); - // Fallback to system property if not found in declarative config - if (stepMillisStr == null) { - stepMillisStr = System.getProperty("applicationinsights.internal.micrometer.step.millis"); - } - - Duration parsedStep = DEFAULT_STEP; - if (stepMillisStr != null) { + Duration configuredStep = DEFAULT_STEP; + if (stepConfigValue != null) { try { - parsedStep = Duration.ofMillis(Long.parseLong(stepMillisStr)); - } catch (NumberFormatException e) { + 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[] {stepMillisStr, DEFAULT_STEP}); + new Object[] {stepConfigValue, DEFAULT_STEP}); } } - step = parsedStep; + step = configuredStep; - String namespaceValue = config.getString("applicationinsights.internal.micrometer.namespace"); - // Fallback to system property if not found in declarative config - if (namespaceValue == null) { - namespaceValue = System.getProperty("applicationinsights.internal.micrometer.namespace"); - } - namespace = namespaceValue; + namespace = System.getProperty("applicationinsights.internal.micrometer.namespace"); } @Override From 009e6dc045eae58347da218b51e1ed9720cf6a0d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 00:56:22 +0000 Subject: [PATCH 13/15] Final verification: All smoke tests passing Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../agent/internal/init/AfterAgentListener.java | 2 +- .../agent/internal/init/SecondEntryPoint.java | 3 ++- .../micrometer/ai/AzureMonitorRegistryConfig.java | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) 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 c6c90a6ac1..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 @@ -45,7 +45,7 @@ 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; 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 eac026f2f8..05e6b6b2e5 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 @@ -214,7 +214,8 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) { } if (telemetryClient.getConnectionString() != null) { - // Snippet initialization moved to AfterAgentListener to avoid early GlobalOpenTelemetry.get() call + // Snippet initialization moved to AfterAgentListener to avoid early GlobalOpenTelemetry.get() + // call } // TODO (trask) add this method to AutoConfigurationCustomizer upstream? 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 fc4998a646..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 @@ -21,7 +21,8 @@ public class AzureMonitorRegistryConfig implements StepRegistryConfig { private AzureMonitorRegistryConfig() { // Read configuration from system property (set by AiConfigCustomizer) - String stepConfigValue = System.getProperty("applicationinsights.internal.micrometer.step.millis"); + String stepConfigValue = + System.getProperty("applicationinsights.internal.micrometer.step.millis"); Duration configuredStep = DEFAULT_STEP; if (stepConfigValue != null) { From 455b9406e8e651e81eaef4790bd51f7b3f59a7c8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 23:42:12 +0000 Subject: [PATCH 14/15] Fix DetectUnexpectedOtelMetrics: Drop SDK internal metrics from 2.24.0 Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../agent/internal/init/SecondEntryPoint.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) 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 05e6b6b2e5..19bbfc9856 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 @@ -767,6 +767,12 @@ private static SdkMeterProviderBuilder configureMetrics( drop(builder, "io.opentelemetry.sdk.trace", "processedSpans"); drop(builder, "io.opentelemetry.sdk.logs", "queueSize"); drop(builder, "io.opentelemetry.sdk.logs", "processedLogs"); + + // drop new SDK internal metrics added in OpenTelemetry 2.24.0 + // These metrics use different naming: otel.sdk.* instead of being under io.opentelemetry.sdk.* meter + dropByName(builder, "otel.sdk.span.live"); + dropByName(builder, "otel.sdk.span.started"); + dropByName(builder, "otel.sdk.log.created"); if (configuration.internal.preAggregatedStandardMetrics.enabled) { AiViewRegistry.registerViews(builder); @@ -775,9 +781,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(processedSpans).build(), + 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().setName(metricName).build(), View.builder().setAggregation(Aggregation.drop()).build()); } From d646eb13c390cc209efa326965514207606c1e0c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 23:47:37 +0000 Subject: [PATCH 15/15] Code review improvement: Extract SDK metrics to constant Co-authored-by: xiang17 <9310587+xiang17@users.noreply.github.com> --- .../agent/internal/init/SecondEntryPoint.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) 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 19bbfc9856..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 @@ -758,21 +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 new SDK internal metrics added in OpenTelemetry 2.24.0 - // These metrics use different naming: otel.sdk.* instead of being under io.opentelemetry.sdk.* meter - dropByName(builder, "otel.sdk.span.live"); - dropByName(builder, "otel.sdk.span.started"); - dropByName(builder, "otel.sdk.log.created"); + // 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);