From 7316f0ffa09003f65432acff382ab6d9cfaf0cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez=20Garc=C3=ADa?= Date: Thu, 15 Oct 2026 16:03:38 +0200 Subject: [PATCH] fix(telemetry): report effective AppSec state in app-started app-started derived products.appsec.enabled from the configured activation, so the default inactive mode reported true while AppSec was not active. When AppSec never reaches AppSecSystem.setActive (remote config disabled, aborted startup) no app-product-change corrects it. Read ActiveSubsystems.APPSEC_ACTIVE instead: AppSec starts before telemetry, so the flag holds the effective state. --- .../datadog/telemetry/TelemetryRequest.java | 5 ++- .../telemetry/TelemetryServiceTest.java | 39 ++++++++++++++----- .../telemetry/TestTelemetryRouter.java | 2 +- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/telemetry/src/main/java/datadog/telemetry/TelemetryRequest.java b/telemetry/src/main/java/datadog/telemetry/TelemetryRequest.java index 5c756d73ad1..d26a229e5e8 100644 --- a/telemetry/src/main/java/datadog/telemetry/TelemetryRequest.java +++ b/telemetry/src/main/java/datadog/telemetry/TelemetryRequest.java @@ -12,10 +12,10 @@ import datadog.trace.api.ConfigSetting; import datadog.trace.api.DDTags; import datadog.trace.api.InstrumenterConfig; -import datadog.trace.api.ProductActivation; import datadog.trace.api.telemetry.Endpoint; import datadog.trace.api.telemetry.ProductChange; import datadog.trace.api.telemetry.ProductChange.ProductType; +import datadog.trace.bootstrap.ActiveSubsystems; import datadog.trace.config.inversion.ConfigHelper; import java.io.IOException; import java.util.EnumMap; @@ -112,8 +112,9 @@ public void writeConfigurations() { public void writeProducts() { try { + // Effective AppSec state: AppSec starts before telemetry (see Agent), so it is already set requestBody.writeProducts( - InstrumenterConfig.get().getAppSecActivation() != ProductActivation.FULLY_DISABLED, + ActiveSubsystems.APPSEC_ACTIVE, InstrumenterConfig.get().isProfilingEnabled(), Config.get().isDynamicInstrumentationEnabled()); } catch (IOException e) { diff --git a/telemetry/src/test/java/datadog/telemetry/TelemetryServiceTest.java b/telemetry/src/test/java/datadog/telemetry/TelemetryServiceTest.java index 661ef36f474..d36056e84f6 100644 --- a/telemetry/src/test/java/datadog/telemetry/TelemetryServiceTest.java +++ b/telemetry/src/test/java/datadog/telemetry/TelemetryServiceTest.java @@ -36,6 +36,7 @@ import datadog.trace.api.config.ProfilingConfig; import datadog.trace.api.telemetry.Endpoint; import datadog.trace.api.telemetry.ProductChange; +import datadog.trace.bootstrap.ActiveSubsystems; import datadog.trace.test.junit.utils.config.WithConfigExtension; import datadog.trace.util.ConfigStrings; import java.io.IOException; @@ -43,6 +44,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.tabletest.junit.TableTest; @@ -93,6 +96,19 @@ class TelemetryServiceTest { .responseCode(singletonList(200)) .authentication(singletonList("JWT")); + private boolean previousAppSecActive; + + @BeforeEach + void setUp() { + previousAppSecActive = ActiveSubsystems.APPSEC_ACTIVE; + ActiveSubsystems.APPSEC_ACTIVE = false; + } + + @AfterEach + void tearDown() { + ActiveSubsystems.APPSEC_ACTIVE = previousAppSecActive; + } + @Test void happyPathWithoutData() throws IOException { TestTelemetryRouter testHttpClient = new TestTelemetryRouter(); @@ -646,17 +662,19 @@ void appStartedMustHaveInstallSignature(String installId, String installType, St } @TableTest({ - "scenario | appsecConfig | appsecEnabled | profilingConfig | profilingEnabled | dynInstrConfig | dynInstrEnabled", - "all products enabled | 1 | true | 1 | true | 1 | true ", - "dynamic instrumentation disabled | 1 | true | 1 | true | 0 | false ", - "profiling disabled | 1 | true | 0 | false | 1 | true ", - "profiling and dyn instr disabled | 1 | true | 0 | false | 0 | false ", - "all products disabled | 0 | false | 0 | false | 0 | false ", - "appsec inactive value treated enabled | inactive | true | 0 | false | 0 | false " + "scenario | appsecConfig | appsecActive | profilingConfig | profilingEnabled | dynInstrConfig | dynInstrEnabled", + "all products enabled | 1 | true | 1 | true | 1 | true ", + "dynamic instrumentation disabled | 1 | true | 1 | true | 0 | false ", + "profiling disabled | 1 | true | 0 | false | 1 | true ", + "profiling and dyn instr disabled | 1 | true | 0 | false | 0 | false ", + "all products disabled | 0 | false | 0 | false | 0 | false ", + "appsec inactive not activated | inactive | false | 0 | false | 0 | false ", + "appsec inactive activated by RC | inactive | true | 0 | false | 0 | false ", + "appsec enabled but startup failed | 1 | false | 0 | false | 0 | false " }) void appStartedMustIncludeActivatedProductsInfo( String appsecConfig, - boolean appsecEnabled, + boolean appsecActive, String profilingConfig, boolean profilingEnabled, String dynInstrConfig, @@ -668,6 +686,7 @@ void appStartedMustIncludeActivatedProductsInfo( ConfigStrings.toEnvVar(ProfilingConfig.PROFILING_ENABLED), profilingConfig); WithConfigExtension.injectEnvConfig( ConfigStrings.toEnvVar(DebuggerConfig.DYNAMIC_INSTRUMENTATION_ENABLED), dynInstrConfig); + ActiveSubsystems.APPSEC_ACTIVE = appsecActive; TestTelemetryRouter testHttpClient = new TestTelemetryRouter(); TelemetryService telemetryService = new TelemetryService(testHttpClient, 10000, false); @@ -676,11 +695,11 @@ void appStartedMustIncludeActivatedProductsInfo( testHttpClient.expectRequest(SUCCESS); telemetryService.sendAppStartedEvent(); - // app-started + // app-started reports the effective AppSec state, not the configured activation testHttpClient .assertRequestBody(APP_STARTED) .assertPayload() - .products(appsecEnabled, profilingEnabled, dynInstrEnabled); + .products(appsecActive, profilingEnabled, dynInstrEnabled); testHttpClient.assertNoMoreRequests(); } } diff --git a/telemetry/src/test/java/datadog/telemetry/TestTelemetryRouter.java b/telemetry/src/test/java/datadog/telemetry/TestTelemetryRouter.java index 5038614045d..485e43b752d 100644 --- a/telemetry/src/test/java/datadog/telemetry/TestTelemetryRouter.java +++ b/telemetry/src/test/java/datadog/telemetry/TestTelemetryRouter.java @@ -370,7 +370,7 @@ PayloadAssertions endpoint(Endpoint... endpoints) { } PayloadAssertions products() { - return products(true, false, false); + return products(false, false, false); } PayloadAssertions products(boolean appsecEnabled) {