diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java index 6dfc5137337..9fa24c5be17 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java @@ -7,6 +7,7 @@ import datadog.trace.api.civisibility.telemetry.CiVisibilityCountMetric; import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector; import datadog.trace.api.civisibility.telemetry.tag.EventType; +import datadog.trace.api.civisibility.telemetry.tag.IsAndroid; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; @@ -114,6 +115,10 @@ public void end(@Nullable Long endTime) { span.finish(); } - metricCollector.add(CiVisibilityCountMetric.EVENT_FINISHED, 1, EventType.MODULE); + metricCollector.add( + CiVisibilityCountMetric.EVENT_FINISHED, + 1, + EventType.MODULE, + span.getTag(Tags.TEST_IS_ANDROID) != null ? IsAndroid.TRUE : null); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java index cb17381f420..d5758b74be3 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java @@ -19,6 +19,7 @@ import datadog.trace.api.civisibility.telemetry.tag.FailFastTestOrderEnabled; import datadog.trace.api.civisibility.telemetry.tag.FailedTestReplayEnabled; import datadog.trace.api.civisibility.telemetry.tag.HasCodeowner; +import datadog.trace.api.civisibility.telemetry.tag.IsAndroid; import datadog.trace.api.civisibility.telemetry.tag.IsHeadless; import datadog.trace.api.civisibility.telemetry.tag.IsUnsupportedCI; import datadog.trace.api.civisibility.telemetry.tag.Provider; @@ -200,6 +201,9 @@ protected Collection additionalTelemetryTags() { if (span.getTag(DDTags.TEST_HAS_FAILED_TEST_REPLAY) != null) { tags.add(FailedTestReplayEnabled.SessionMetric.TRUE); } + if (span.getTag(Tags.TEST_IS_ANDROID) != null) { + tags.add(IsAndroid.TRUE); + } return tags; } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java index 3d33141dd19..5d050036e9b 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java @@ -194,6 +194,7 @@ private void onModuleFinish(AgentSpan moduleSpan) { TagMergeSpec.of(Tags.TEST_ITR_TESTS_SKIPPING_COUNT, Long::sum), TagMergeSpec.of(DDTags.CI_ITR_TESTS_SKIPPED, Boolean::logicalOr), TagMergeSpec.of(Tags.TEST_TEST_MANAGEMENT_ENABLED, Boolean::logicalOr), + TagMergeSpec.of(Tags.TEST_IS_ANDROID, Boolean::logicalOr), TagMergeSpec.of(DDTags.TEST_HAS_FAILED_TEST_REPLAY, Boolean::logicalOr), TagMergeSpec.of(DDTags.CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS, Boolean::logicalOr), TagMergeSpec.of(DDTags.CI_LIBRARY_CONFIGURATION_ERROR_SKIPPABLE_TESTS, Boolean::logicalOr), diff --git a/dd-java-agent/instrumentation/gradle/gradle-3.0/src/main/groovy/datadog/trace/instrumentation/gradle/legacy/GradleBuildListener.java b/dd-java-agent/instrumentation/gradle/gradle-3.0/src/main/groovy/datadog/trace/instrumentation/gradle/legacy/GradleBuildListener.java index f92a31b345b..bf99dbe034d 100644 --- a/dd-java-agent/instrumentation/gradle/gradle-3.0/src/main/groovy/datadog/trace/instrumentation/gradle/legacy/GradleBuildListener.java +++ b/dd-java-agent/instrumentation/gradle/gradle-3.0/src/main/groovy/datadog/trace/instrumentation/gradle/legacy/GradleBuildListener.java @@ -7,6 +7,7 @@ import datadog.trace.api.civisibility.domain.BuildSessionSettings; import datadog.trace.api.civisibility.domain.JavaAgent; import datadog.trace.api.civisibility.events.BuildEventsHandler; +import datadog.trace.bootstrap.instrumentation.api.Tags; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -111,9 +112,22 @@ public void beforeExecute(@Nonnull Task task) { List classpath = GradleUtils.getClasspath(task); JavaAgent jacocoAgent = GradleUtils.getJacocoAgent(task); + // "com.android.base" is applied transitively by every Android Gradle Plugin, so it is a + // reliable single marker for an Android project regardless of how its tests are executed. + Map additionalTags = + project.getPluginManager().hasPlugin("com.android.base") + ? Collections.singletonMap(Tags.TEST_IS_ANDROID, true) + : Collections.emptyMap(); + BuildModuleSettings moduleSettings = buildEventsHandler.onTestModuleStart( - gradle, taskPath, moduleLayout, jvmExecutable, classpath, jacocoAgent, null); + gradle, + taskPath, + moduleLayout, + jvmExecutable, + classpath, + jacocoAgent, + additionalTags); Map systemProperties = moduleSettings.getSystemProperties(); GradleProjectConfigurator.INSTANCE.configureTracer(task, systemProperties); } diff --git a/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityGradleListener.java b/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityGradleListener.java index 09d6506822a..ba81d2ac2ff 100644 --- a/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityGradleListener.java +++ b/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityGradleListener.java @@ -183,6 +183,11 @@ public void beforeExecute(TaskIdentity taskIdentity) { Project project = gradle.getRootProject().project(projectPath); Test task = (Test) project.getTasks().getByName(taskIdentity.name); + // "com.android.base" is applied transitively by every Android Gradle Plugin + // (application/library/dynamic-feature/test), so it is a reliable single marker for an + // Android project regardless of how its tests are executed. + boolean isAndroid = project.getPluginManager().hasPlugin("com.android.base"); + Map inputProperties = task.getInputs().getProperties(); BuildModuleLayout moduleLayout = (BuildModuleLayout) inputProperties.get(CiVisibilityPluginExtension.MODULE_LAYOUT_PROPERTY); @@ -197,7 +202,7 @@ public void beforeExecute(TaskIdentity taskIdentity) { List taskClasspath = CiVisibilityPluginExtension.getClasspath(task); ciVisibilityService.onModuleStart( - taskPath, moduleLayout, jvmExecutable, taskClasspath, jacocoAgent); + taskPath, isAndroid, moduleLayout, jvmExecutable, taskClasspath, jacocoAgent); } private JavaAgent getJacocoAgent(Test task) { diff --git a/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityService.java b/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityService.java index adc27283cb0..6d4462f15b0 100644 --- a/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityService.java +++ b/dd-java-agent/instrumentation/gradle/gradle-8.3/src/main/groovy/datadog/trace/instrumentation/gradle/CiVisibilityService.java @@ -123,12 +123,21 @@ public void onBuildTaskFinish(String taskPath, @Nullable Throwable failure) { public void onModuleStart( String taskPath, + boolean isAndroid, BuildModuleLayout moduleLayout, Path jvmExecutable, Collection taskClasspath, JavaAgent jacocoAgent) { + Map additionalTags = + isAndroid ? Collections.singletonMap(Tags.TEST_IS_ANDROID, true) : Collections.emptyMap(); buildEventsHandler.onTestModuleStart( - SESSION_KEY, taskPath, moduleLayout, jvmExecutable, taskClasspath, jacocoAgent, null); + SESSION_KEY, + taskPath, + moduleLayout, + jvmExecutable, + taskClasspath, + jacocoAgent, + additionalTags); } public void onModuleFinish( diff --git a/dd-smoke-tests/gradle/src/test/java/datadog/smoketest/GradleDaemonSmokeTest.java b/dd-smoke-tests/gradle/src/test/java/datadog/smoketest/GradleDaemonSmokeTest.java index 02bc2dc4774..5af09a28a1a 100644 --- a/dd-smoke-tests/gradle/src/test/java/datadog/smoketest/GradleDaemonSmokeTest.java +++ b/dd-smoke-tests/gradle/src/test/java/datadog/smoketest/GradleDaemonSmokeTest.java @@ -131,7 +131,7 @@ void testNew( @TableTest({ "scenario | gradleVersion | projectName | expectedTraces", - "robolectric-latest | latest | test-succeed-robolectric | 6 " + "robolectric-latest | latest | test-succeed-robolectric | 7 " }) @ParameterizedTest void testRobolectric(String gradleVersion, String projectName, int expectedTraces) diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/build.gradleTest b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/build.gradleTest index 43e1b6068d5..618780014b1 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/build.gradleTest +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/build.gradleTest @@ -8,6 +8,10 @@ import org.gradle.api.attributes.CompatibilityCheckDetails import org.gradle.api.attributes.LibraryElements apply plugin: 'java' +// Inert stand-in for the Android Gradle Plugin (see buildSrc/): real AGP needs the Android SDK, +// which is absent in the smoke-test environment. Our build-level Android detection only checks for +// the 'com.android.base' plugin id, so applying an id-only stand-in exercises it. +apply plugin: 'com.android.base' repositories { mavenLocal() diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/build.gradleTest b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/build.gradleTest new file mode 100644 index 00000000000..b894ef21751 --- /dev/null +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/build.gradleTest @@ -0,0 +1,21 @@ +apply plugin: 'java' + +repositories { + mavenLocal() + + def proxyUrl = System.getenv("MAVEN_REPOSITORY_PROXY") + if (proxyUrl) { + maven { + url = proxyUrl + allowInsecureProtocol = true + } + } + + mavenCentral() +} + +dependencies { + // Plugin lives in the Gradle API; the CI Visibility javac plugin is auto-injected into + // this compile task too, so the repositories above must be able to resolve it. + implementation gradleApi() +} diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/src/main/java/datadog/smoke/gradle/AndroidBaseStandInPlugin.java b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/src/main/java/datadog/smoke/gradle/AndroidBaseStandInPlugin.java new file mode 100644 index 00000000000..978fc313857 --- /dev/null +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/src/main/java/datadog/smoke/gradle/AndroidBaseStandInPlugin.java @@ -0,0 +1,22 @@ +package datadog.smoke.gradle; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; + +/** + * No-op stand-in for the Android Gradle Plugin's {@code com.android.base} plugin. + * + *

Real AGP requires the Android SDK to be installed, which is not available in the smoke-test + * environment. The CI Visibility build-level Android detection only checks whether a plugin + * registered under the {@code com.android.base} id has been applied (see {@code + * CiVisibilityGradleListener}); every AGP variant applies {@code com.android.base} transitively. + * Registering an inert plugin under that exact id therefore exercises the detection, the + * module→session tag propagation and the {@code is_android} telemetry faithfully, without pulling + * in AGP or the SDK. + */ +public class AndroidBaseStandInPlugin implements Plugin { + @Override + public void apply(Project project) { + // intentionally empty: only the plugin id matters for detection + } +} diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/src/main/resources/META-INF/gradle-plugins/com.android.base.properties b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/src/main/resources/META-INF/gradle-plugins/com.android.base.properties new file mode 100644 index 00000000000..8f21ff1cce0 --- /dev/null +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/buildSrc/src/main/resources/META-INF/gradle-plugins/com.android.base.properties @@ -0,0 +1 @@ +implementation-class=datadog.smoke.gradle.AndroidBaseStandInPlugin diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/events.ftl index d01993dbd3d..b08072b29ab 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-robolectric/events.ftl @@ -23,6 +23,7 @@ "test.command" : "gradle test", "test.framework" : "junit4", "test.framework_version" : "4.13.2", + "test.is_android" : "true", "test.itr.tests_skipping.enabled" : "true", "test.itr.tests_skipping.type" : "test", "test.status" : "pass", @@ -52,6 +53,48 @@ "meta" : { "_dd.p.tid" : ${content_meta__dd_p_tid_2}, "_dd.test.is_user_provided_service" : "true", + "_dd.tracer_host" : ${content_meta__dd_tracer_host}, + "ci.workspace_path" : ${content_meta_ci_workspace_path}, + "component" : "gradle", + "env" : "integration-test", + "language" : "jvm", + "library_version" : ${content_meta_library_version}, + "os.architecture" : ${content_meta_os_architecture}, + "os.platform" : ${content_meta_os_platform}, + "os.version" : ${content_meta_os_version}, + "runtime-id" : ${content_meta_runtime_id}, + "runtime.name" : ${content_meta_runtime_name}, + "runtime.vendor" : ${content_meta_runtime_vendor}, + "runtime.version" : ${content_meta_runtime_version}, + "span.kind" : "test_session_end", + "test.command" : "gradle :buildSrc", + "test.gradle.nested_build" : "true", + "test.status" : "skip", + "test.toolchain" : ${content_meta_test_toolchain}, + "test.type" : "test", + "test_session.name" : "gradle :buildSrc" + }, + "metrics" : { + "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_2}, + "_dd.profiling.enabled" : 0, + "_dd.trace_span_attribute_schema" : 0, + "process_id" : ${content_metrics_process_id} + }, + "name" : "gradle.test_session", + "resource" : ":buildSrc", + "service" : "test-gradle-service", + "start" : ${content_start_2}, + "test_session_id" : ${content_test_session_id_2} + }, + "type" : "test_session_end", + "version" : 1 +}, { + "content" : { + "duration" : ${content_duration_3}, + "error" : 0, + "meta" : { + "_dd.p.tid" : ${content_meta__dd_p_tid_3}, + "_dd.test.is_user_provided_service" : "true", "ci.workspace_path" : ${content_meta_ci_workspace_path}, "component" : "gradle", "env" : "integration-test", @@ -69,6 +112,7 @@ "test.command" : "gradle test", "test.framework" : "junit4", "test.framework_version" : "4.13.2", + "test.is_android" : "true", "test.itr.tests_skipping.enabled" : "true", "test.itr.tests_skipping.type" : "test", "test.module" : ":test", @@ -77,13 +121,13 @@ "test_session.name" : "gradle test" }, "metrics" : { - "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_2}, + "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_3}, "test.itr.tests_skipping.count" : 0 }, "name" : "gradle.test_module", "resource" : ":test", "service" : "test-gradle-service", - "start" : ${content_start_2}, + "start" : ${content_start_3}, "test_module_id" : ${content_test_module_id}, "test_session_id" : ${content_test_session_id} }, @@ -91,10 +135,10 @@ "version" : 1 }, { "content" : { - "duration" : ${content_duration_3}, + "duration" : ${content_duration_4}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_3}, + "_dd.p.tid" : ${content_meta__dd_p_tid_4}, "_dd.test.is_user_provided_service" : "true", "env" : "integration-test", "language" : "jvm", @@ -109,21 +153,108 @@ }, "metrics" : { }, "name" : "classes", - "parent_id" : ${content_test_session_id}, + "parent_id" : ${content_test_session_id_2}, "resource" : "classes", "service" : "test-gradle-service", "span_id" : ${content_span_id}, - "start" : ${content_start_3}, + "start" : ${content_start_4}, + "trace_id" : ${content_test_session_id_2} + }, + "type" : "span", + "version" : 1 +}, { + "content" : { + "duration" : ${content_duration_5}, + "error" : 0, + "meta" : { + "_dd.p.tid" : ${content_meta__dd_p_tid_5}, + "_dd.test.is_user_provided_service" : "true", + "env" : "integration-test", + "language" : "jvm", + "library_version" : ${content_meta_library_version}, + "os.architecture" : ${content_meta_os_architecture}, + "os.platform" : ${content_meta_os_platform}, + "os.version" : ${content_meta_os_version}, + "runtime-id" : ${content_meta_runtime_id}, + "runtime.name" : ${content_meta_runtime_name}, + "runtime.vendor" : ${content_meta_runtime_vendor}, + "runtime.version" : ${content_meta_runtime_version} + }, + "metrics" : { }, + "name" : "classes", + "parent_id" : ${content_test_session_id}, + "resource" : "classes", + "service" : "test-gradle-service", + "span_id" : ${content_span_id_2}, + "start" : ${content_start_5}, "trace_id" : ${content_test_session_id} }, "type" : "span", "version" : 1 }, { "content" : { - "duration" : ${content_duration_4}, + "duration" : ${content_duration_6}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_4}, + "_dd.p.tid" : ${content_meta__dd_p_tid_6}, + "_dd.test.is_user_provided_service" : "true", + "env" : "integration-test", + "language" : "jvm", + "library_version" : ${content_meta_library_version}, + "os.architecture" : ${content_meta_os_architecture}, + "os.platform" : ${content_meta_os_platform}, + "os.version" : ${content_meta_os_version}, + "runtime-id" : ${content_meta_runtime_id}, + "runtime.name" : ${content_meta_runtime_name}, + "runtime.vendor" : ${content_meta_runtime_vendor}, + "runtime.version" : ${content_meta_runtime_version} + }, + "metrics" : { }, + "name" : "compileGroovy", + "parent_id" : ${content_test_session_id_2}, + "resource" : "compileGroovy", + "service" : "test-gradle-service", + "span_id" : ${content_span_id_3}, + "start" : ${content_start_6}, + "trace_id" : ${content_test_session_id_2} + }, + "type" : "span", + "version" : 1 +}, { + "content" : { + "duration" : ${content_duration_7}, + "error" : 0, + "meta" : { + "_dd.p.tid" : ${content_meta__dd_p_tid_7}, + "_dd.test.is_user_provided_service" : "true", + "env" : "integration-test", + "language" : "jvm", + "library_version" : ${content_meta_library_version}, + "os.architecture" : ${content_meta_os_architecture}, + "os.platform" : ${content_meta_os_platform}, + "os.version" : ${content_meta_os_version}, + "runtime-id" : ${content_meta_runtime_id}, + "runtime.name" : ${content_meta_runtime_name}, + "runtime.vendor" : ${content_meta_runtime_vendor}, + "runtime.version" : ${content_meta_runtime_version} + }, + "metrics" : { }, + "name" : "compileJava", + "parent_id" : ${content_test_session_id_2}, + "resource" : "compileJava", + "service" : "test-gradle-service", + "span_id" : ${content_span_id_4}, + "start" : ${content_start_7}, + "trace_id" : ${content_test_session_id_2} + }, + "type" : "span", + "version" : 1 +}, { + "content" : { + "duration" : ${content_duration_8}, + "error" : 0, + "meta" : { + "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "env" : "integration-test", "language" : "jvm", @@ -141,18 +272,18 @@ "parent_id" : ${content_test_session_id}, "resource" : "compileJava", "service" : "test-gradle-service", - "span_id" : ${content_span_id_2}, - "start" : ${content_start_4}, + "span_id" : ${content_span_id_5}, + "start" : ${content_start_8}, "trace_id" : ${content_test_session_id} }, "type" : "span", "version" : 1 }, { "content" : { - "duration" : ${content_duration_5}, + "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_5}, + "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "env" : "integration-test", "language" : "jvm", @@ -170,18 +301,18 @@ "parent_id" : ${content_test_session_id}, "resource" : "compileTestJava", "service" : "test-gradle-service", - "span_id" : ${content_span_id_3}, - "start" : ${content_start_5}, + "span_id" : ${content_span_id_6}, + "start" : ${content_start_9}, "trace_id" : ${content_test_session_id} }, "type" : "span", "version" : 1 }, { "content" : { - "duration" : ${content_duration_6}, + "duration" : ${content_duration_10}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_6}, + "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, "ci.workspace_path" : ${content_meta_ci_workspace_path}, @@ -208,7 +339,7 @@ "test_session.name" : "gradle test" }, "metrics" : { - "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_3}, + "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_4}, "_dd.profiling.enabled" : 0, "_dd.trace_span_attribute_schema" : 0, "process_id" : ${content_metrics_process_id_2}, @@ -218,7 +349,7 @@ "name" : "junit4.test_suite", "resource" : "datadog.smoke.AndroidJUnit4RunnerTest", "service" : "test-gradle-service", - "start" : ${content_start_6}, + "start" : ${content_start_10}, "test_module_id" : ${content_test_module_id}, "test_session_id" : ${content_test_session_id}, "test_suite_id" : ${content_test_suite_id} @@ -227,7 +358,7 @@ "version" : 1 }, { "content" : { - "duration" : ${content_duration_7}, + "duration" : ${content_duration_11}, "error" : 0, "meta" : { "_dd.library_capabilities.auto_test_retries" : "1", @@ -240,7 +371,7 @@ "_dd.library_capabilities.test_management.attempt_to_fix" : "5", "_dd.library_capabilities.test_management.disable" : "1", "_dd.library_capabilities.test_management.quarantine" : "1", - "_dd.p.tid" : ${content_meta__dd_p_tid_7}, + "_dd.p.tid" : ${content_meta__dd_p_tid_11}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, "ci.workspace_path" : ${content_meta_ci_workspace_path}, @@ -273,7 +404,7 @@ "test_session.name" : "gradle test" }, "metrics" : { - "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_4}, + "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_5}, "_dd.profiling.enabled" : 0, "_dd.trace_span_attribute_schema" : 0, "process_id" : ${content_metrics_process_id_2}, @@ -285,8 +416,8 @@ "parent_id" : ${content_parent_id}, "resource" : "datadog.smoke.AndroidJUnit4RunnerTest.test_androidjunit4_runner", "service" : "test-gradle-service", - "span_id" : ${content_span_id_4}, - "start" : ${content_start_7}, + "span_id" : ${content_span_id_7}, + "start" : ${content_start_11}, "test_module_id" : ${content_test_module_id}, "test_session_id" : ${content_test_session_id}, "test_suite_id" : ${content_test_suite_id}, @@ -296,10 +427,10 @@ "version" : 2 }, { "content" : { - "duration" : ${content_duration_8}, + "duration" : ${content_duration_12}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_8}, + "_dd.p.tid" : ${content_meta__dd_p_tid_12}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, "ci.workspace_path" : ${content_meta_ci_workspace_path}, @@ -326,7 +457,7 @@ "test_session.name" : "gradle test" }, "metrics" : { - "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_5}, + "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_6}, "_dd.profiling.enabled" : 0, "_dd.trace_span_attribute_schema" : 0, "process_id" : ${content_metrics_process_id_2}, @@ -336,7 +467,7 @@ "name" : "junit4.test_suite", "resource" : "datadog.smoke.RobolectricRunnerTest", "service" : "test-gradle-service", - "start" : ${content_start_8}, + "start" : ${content_start_12}, "test_module_id" : ${content_test_module_id}, "test_session_id" : ${content_test_session_id}, "test_suite_id" : ${content_test_suite_id_2} @@ -345,7 +476,7 @@ "version" : 1 }, { "content" : { - "duration" : ${content_duration_9}, + "duration" : ${content_duration_13}, "error" : 0, "meta" : { "_dd.library_capabilities.auto_test_retries" : "1", @@ -358,7 +489,7 @@ "_dd.library_capabilities.test_management.attempt_to_fix" : "5", "_dd.library_capabilities.test_management.disable" : "1", "_dd.library_capabilities.test_management.quarantine" : "1", - "_dd.p.tid" : ${content_meta__dd_p_tid_9}, + "_dd.p.tid" : ${content_meta__dd_p_tid_13}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, "ci.workspace_path" : ${content_meta_ci_workspace_path}, @@ -391,7 +522,7 @@ "test_session.name" : "gradle test" }, "metrics" : { - "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_6}, + "_dd.host.vcpu_count" : ${content_metrics__dd_host_vcpu_count_7}, "_dd.profiling.enabled" : 0, "_dd.trace_span_attribute_schema" : 0, "process_id" : ${content_metrics_process_id_2}, @@ -403,8 +534,8 @@ "parent_id" : ${content_parent_id}, "resource" : "datadog.smoke.RobolectricRunnerTest.test_robolectric_runner", "service" : "test-gradle-service", - "span_id" : ${content_span_id_5}, - "start" : ${content_start_9}, + "span_id" : ${content_span_id_8}, + "start" : ${content_start_13}, "test_module_id" : ${content_test_module_id}, "test_session_id" : ${content_test_session_id}, "test_suite_id" : ${content_test_suite_id_2}, @@ -414,10 +545,68 @@ "version" : 2 }, { "content" : { - "duration" : ${content_duration_10}, + "duration" : ${content_duration_14}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_10}, + "_dd.p.tid" : ${content_meta__dd_p_tid_14}, + "_dd.test.is_user_provided_service" : "true", + "env" : "integration-test", + "language" : "jvm", + "library_version" : ${content_meta_library_version}, + "os.architecture" : ${content_meta_os_architecture}, + "os.platform" : ${content_meta_os_platform}, + "os.version" : ${content_meta_os_version}, + "runtime-id" : ${content_meta_runtime_id}, + "runtime.name" : ${content_meta_runtime_name}, + "runtime.vendor" : ${content_meta_runtime_vendor}, + "runtime.version" : ${content_meta_runtime_version} + }, + "metrics" : { }, + "name" : "jar", + "parent_id" : ${content_test_session_id_2}, + "resource" : "jar", + "service" : "test-gradle-service", + "span_id" : ${content_span_id_9}, + "start" : ${content_start_14}, + "trace_id" : ${content_test_session_id_2} + }, + "type" : "span", + "version" : 1 +}, { + "content" : { + "duration" : ${content_duration_15}, + "error" : 0, + "meta" : { + "_dd.p.tid" : ${content_meta__dd_p_tid_15}, + "_dd.test.is_user_provided_service" : "true", + "env" : "integration-test", + "language" : "jvm", + "library_version" : ${content_meta_library_version}, + "os.architecture" : ${content_meta_os_architecture}, + "os.platform" : ${content_meta_os_platform}, + "os.version" : ${content_meta_os_version}, + "runtime-id" : ${content_meta_runtime_id}, + "runtime.name" : ${content_meta_runtime_name}, + "runtime.vendor" : ${content_meta_runtime_vendor}, + "runtime.version" : ${content_meta_runtime_version} + }, + "metrics" : { }, + "name" : "processResources", + "parent_id" : ${content_test_session_id_2}, + "resource" : "processResources", + "service" : "test-gradle-service", + "span_id" : ${content_span_id_10}, + "start" : ${content_start_15}, + "trace_id" : ${content_test_session_id_2} + }, + "type" : "span", + "version" : 1 +}, { + "content" : { + "duration" : ${content_duration_16}, + "error" : 0, + "meta" : { + "_dd.p.tid" : ${content_meta__dd_p_tid_16}, "_dd.test.is_user_provided_service" : "true", "env" : "integration-test", "language" : "jvm", @@ -435,18 +624,18 @@ "parent_id" : ${content_test_session_id}, "resource" : "processResources", "service" : "test-gradle-service", - "span_id" : ${content_span_id_6}, - "start" : ${content_start_10}, + "span_id" : ${content_span_id_11}, + "start" : ${content_start_16}, "trace_id" : ${content_test_session_id} }, "type" : "span", "version" : 1 }, { "content" : { - "duration" : ${content_duration_11}, + "duration" : ${content_duration_17}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_11}, + "_dd.p.tid" : ${content_meta__dd_p_tid_17}, "_dd.test.is_user_provided_service" : "true", "env" : "integration-test", "language" : "jvm", @@ -464,18 +653,18 @@ "parent_id" : ${content_test_session_id}, "resource" : "processTestResources", "service" : "test-gradle-service", - "span_id" : ${content_span_id_7}, - "start" : ${content_start_11}, + "span_id" : ${content_span_id_12}, + "start" : ${content_start_17}, "trace_id" : ${content_test_session_id} }, "type" : "span", "version" : 1 }, { "content" : { - "duration" : ${content_duration_12}, + "duration" : ${content_duration_18}, "error" : 0, "meta" : { - "_dd.p.tid" : ${content_meta__dd_p_tid_12}, + "_dd.p.tid" : ${content_meta__dd_p_tid_18}, "_dd.test.is_user_provided_service" : "true", "env" : "integration-test", "language" : "jvm", @@ -493,8 +682,8 @@ "parent_id" : ${content_test_session_id}, "resource" : "testClasses", "service" : "test-gradle-service", - "span_id" : ${content_span_id_8}, - "start" : ${content_start_12}, + "span_id" : ${content_span_id_13}, + "start" : ${content_start_18}, "trace_id" : ${content_test_session_id} }, "type" : "span", diff --git a/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/CiVisibilityCountMetric.java b/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/CiVisibilityCountMetric.java index cbb8441e920..43d98bf6955 100644 --- a/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/CiVisibilityCountMetric.java +++ b/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/CiVisibilityCountMetric.java @@ -22,6 +22,7 @@ import datadog.trace.api.civisibility.telemetry.tag.HasCodeowner; import datadog.trace.api.civisibility.telemetry.tag.HasFailedAllRetries; import datadog.trace.api.civisibility.telemetry.tag.ImpactedTestsDetectionEnabled; +import datadog.trace.api.civisibility.telemetry.tag.IsAndroid; import datadog.trace.api.civisibility.telemetry.tag.IsAndroidEmulated; import datadog.trace.api.civisibility.telemetry.tag.IsAttemptToFix; import datadog.trace.api.civisibility.telemetry.tag.IsDisabled; @@ -73,7 +74,8 @@ public enum CiVisibilityCountMetric { HasCodeowner.class, IsUnsupportedCI.class, EarlyFlakeDetectionAbortReason.class, - FailedTestReplayEnabled.SessionMetric.class), + FailedTestReplayEnabled.SessionMetric.class, + IsAndroid.class), /** The number of test events finished */ TEST_EVENT_FINISHED( "event_finished", diff --git a/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/tag/IsAndroid.java b/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/tag/IsAndroid.java new file mode 100644 index 00000000000..bb079a24763 --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/api/civisibility/telemetry/tag/IsAndroid.java @@ -0,0 +1,13 @@ +package datadog.trace.api.civisibility.telemetry.tag; + +import datadog.trace.api.civisibility.telemetry.TagValue; + +/** Whether a test module/session belongs to an Android project. */ +public enum IsAndroid implements TagValue { + TRUE; + + @Override + public String asString() { + return "is_android:true"; + } +} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java index 968d6eea3b3..760c8ea6f4c 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Tags.java @@ -93,6 +93,8 @@ public class Tags { public static final String TEST_ANDROID_CODENAME = "test.android.codename"; public static final String TEST_ANDROID_ROBOLECTRIC_VERSION = "test.android.robolectric.version"; + public static final String TEST_IS_ANDROID = "test.is_android"; + public static final String TEST_SESSION_ID = "test_session_id"; public static final String TEST_MODULE_ID = "test_module_id"; public static final String TEST_SUITE_ID = "test_suite_id";