diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/ci/CIJobsExtensions.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/ci/CIJobsExtensions.kt index 5fd6b355bf3..a40059d96ac 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/ci/CIJobsExtensions.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/ci/CIJobsExtensions.kt @@ -5,6 +5,8 @@ import org.gradle.api.Task import org.gradle.api.provider.Provider import org.gradle.kotlin.dsl.extra +const val CI_SHARD_PROJECT_PATHS = "ciShardProjectPaths" + /** * Determines if the current project is in the selected slot. * diff --git a/buildSrc/src/main/kotlin/dd-trace-java.ci-jobs.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.ci-jobs.gradle.kts index 4868f4f769b..ddde3e10bd8 100644 --- a/buildSrc/src/main/kotlin/dd-trace-java.ci-jobs.gradle.kts +++ b/buildSrc/src/main/kotlin/dd-trace-java.ci-jobs.gradle.kts @@ -1,3 +1,4 @@ +import datadog.gradle.plugin.ci.CI_SHARD_PROJECT_PATHS import datadog.gradle.plugin.ci.isInSelectedSlot import org.gradle.api.tasks.testing.Test import java.io.File @@ -17,8 +18,16 @@ if (project != rootProject) { allprojects { // Enable tests only on the selected slot (if -Pslot=n/t is provided) tasks.withType().configureEach { - onlyIf("Project is in selected slot") { - project.isInSelectedSlot.get() + onlyIf("Project is in selected slot") { testTask -> + val rootExtraProperties = rootProject.extensions.extraProperties + val shardProjectPaths = if (rootExtraProperties.has(CI_SHARD_PROJECT_PATHS)) { + rootExtraProperties.get(CI_SHARD_PROJECT_PATHS) as? Map<*, *> + } else { + null + } + val shardProjectPath = shardProjectPaths?.get(testTask.path)?.toString() + val shardProject = shardProjectPath?.let(rootProject::project) ?: testTask.project + shardProject.isInSelectedSlot.get() } } } diff --git a/buildSrc/src/main/resources/datadog/gradle/plugin/ci/test-shard-weights.json b/buildSrc/src/main/resources/datadog/gradle/plugin/ci/test-shard-weights.json index 4b1c38c2305..776ded8e17c 100644 --- a/buildSrc/src/main/resources/datadog/gradle/plugin/ci/test-shard-weights.json +++ b/buildSrc/src/main/resources/datadog/gradle/plugin/ci/test-shard-weights.json @@ -5,6 +5,8 @@ "Source: Datadog CI Visibility, sum(@duration) over test modules grouped by", "Gradle project, JVM 11, job test_inst, 7-day window ending 2026-10-11,", "divided by the 491 observed pipelines.", + "JDBC virtual-project weights use coverage-complete test results from", + "pipeline 144158285 on 2026-10-12.", "Projects absent from this map fall back to the default weight.", "See docs/ci-test-shard-weights.md to regenerate." ], @@ -14,44 +16,58 @@ "jvm": "11", "job": "test_inst", "pipelines_observed": 491, - "projects_measured": 36 + "projects_measured": 35, + "projects_derived_from_measured_suites": 14 }, "weights": { - ":dd-java-agent:instrumentation:jdbc": 1116.7, ":dd-java-agent:instrumentation:lettuce:lettuce-5.0": 978.1, ":dd-java-agent:instrumentation:akka:akka-http:akka-http-10.0": 612.3, ":dd-java-agent:instrumentation:spring:spring-webflux:spring-webflux-5.0": 509.4, ":dd-java-agent:instrumentation:kafka:kafka-clients-0.11": 379.1, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-old-h2-test": 321.831, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-forked-test": 310.736, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-instrumentation-forked-test": 279.971, ":dd-java-agent:instrumentation:akka:akka-http:akka-http-10.6": 258.0, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-old-postgres-test": 241.128, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-prepared-forked-test": 228.78, ":dd-java-agent:instrumentation:aws-java:aws-java-sdk-2.2": 220.7, ":dd-java-agent:instrumentation:mule-4.5": 217.1, ":dd-java-agent:instrumentation:grpc-1.5": 196.7, ":dd-java-agent:instrumentation:junit:junit-5:junit-5.3": 195.4, ":dd-java-agent:instrumentation:liberty:liberty-20.0": 187.3, ":dd-java-agent:instrumentation:datastax-cassandra:datastax-cassandra-3.8": 175.4, + ":dd-java-agent:instrumentation:jdbc:jdbc-old-postgres-test": 173.218, ":dd-java-agent:instrumentation:maven:maven-3.2.1": 172.2, ":dd-java-agent:instrumentation:mongo:mongo-driver:mongo-driver-4.0": 171.3, + ":dd-java-agent:instrumentation:jdbc:jdbc-old-h2-test": 167.347, ":dd-java-agent:instrumentation:couchbase:couchbase-3.2": 165.8, ":dd-java-agent:instrumentation:rabbitmq-amqp-2.7": 159.7, ":dd-java-agent:instrumentation:aws-java:aws-java-sqs-1.0": 152.1, ":dd-java-agent:instrumentation:couchbase:couchbase-3.1": 151.2, ":dd-java-agent:instrumentation:aws-java:aws-java-sqs-2.0": 148.7, ":dd-java-agent:instrumentation:vertx:vertx-web:vertx-web-4.0": 140.9, + ":dd-java-agent:instrumentation:jdbc:jdbc-test": 139.615, ":dd-java-agent:instrumentation:spark:spark_2.12": 113.9, ":dd-java-agent:instrumentation:aws-java:aws-java-sdk-1.11": 104.0, ":dd-java-agent:instrumentation:hibernate:hibernate-core-3.3": 93.6, ":dd-java-agent:instrumentation:jersey:jersey-2.0": 84.8, ":dd-java-agent:instrumentation:couchbase:couchbase-2.0": 82.5, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-test": 69.627, + ":dd-java-agent:instrumentation:jdbc:jdbc-instrumentation-forked-tests": 68.703, ":dd-java-agent:instrumentation:akka:akka-actor-2.5": 66.8, ":dd-java-agent:instrumentation:jetty:jetty-server:jetty-server-9.4.21": 64.6, ":dd-java-agent:instrumentation:lettuce:lettuce-4.0": 47.3, ":dd-java-agent:instrumentation:jedis:jedis-3.0": 42.0, + ":dd-java-agent:instrumentation:jdbc:jdbc-decorator-forked-tests": 35.57, ":dd-java-agent:instrumentation:mongo:mongo-driver:mongo-driver-3:mongo-driver-3.1": 34.7, ":dd-java-agent:instrumentation:elasticsearch:elasticsearch-rest:elasticsearch-rest-7.0": 31.7, ":dd-java-agent:instrumentation:couchbase:couchbase-2.6": 25.6, + ":dd-java-agent:instrumentation:jdbc:jdbc-dbm-forked-tests": 25.599, + ":dd-java-agent:instrumentation:jdbc:jdbc-oracle-forked-tests": 25.523, ":dd-java-agent:instrumentation:synapse-3.0": 24.5, ":dd-java-agent:instrumentation:spring:spring-webmvc:spring-webmvc-5.3": 21.9, ":dd-java-agent:instrumentation:spring:spring-boot-1.3": 16.6, - ":dd-java-agent:instrumentation:vertx:vertx-web:vertx-web-3.9": 12.6 + ":dd-java-agent:instrumentation:vertx:vertx-web:vertx-web-3.9": 12.6, + ":dd-java-agent:instrumentation:jdbc:jdbc-sql-server-forked-tests": 11.867 } } diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/ci/TestShardBalancerTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/ci/TestShardBalancerTest.kt index 9765a436492..6966760302d 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/ci/TestShardBalancerTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/ci/TestShardBalancerTest.kt @@ -109,10 +109,9 @@ class TestShardBalancerTest { @Test fun `bundled weights file is parsed`() { - assertThat(WEIGHTS).hasSize(36) + assertThat(WEIGHTS).hasSize(49) assertThat(WEIGHTS.values).allSatisfy { weight -> assertThat(weight).isPositive() } - // docs/ci-test-shard-weights.md names the two heaviest projects - assertThat(heaviestProjects(2)).containsExactly(JDBC, LETTUCE_5_0) + assertThat(heaviestProjects(2)).containsExactly(LETTUCE_5_0, AKKA_HTTP_10_0) } @Test @@ -139,8 +138,8 @@ class TestShardBalancerTest { companion object { private const val INSTRUMENTATION_PREFIX = ":dd-java-agent:instrumentation:" - private const val JDBC = ":dd-java-agent:instrumentation:jdbc" private const val LETTUCE_5_0 = ":dd-java-agent:instrumentation:lettuce:lettuce-5.0" + private const val AKKA_HTTP_10_0 = ":dd-java-agent:instrumentation:akka:akka-http:akka-http-10.0" private val WEIGHTS = loadDefaultWeights() diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index fbacf010b3c..534ba799ed5 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -83,7 +83,26 @@ TaskProvider registerIndexTask(String indexTaskName, String indexer, S } instrumentationNaming { - exclusions = ["org-json-20230227"] // org-json does not use semver + // CI-only virtual projects delegate to the JDBC module's existing test tasks. + exclusions = [ + // org-json does not use semver + "org-json-20230227", + "jdbc-test", + "jdbc-remote-test", + "jdbc-old-h2-test", + "jdbc-remote-old-h2-test", + "jdbc-old-postgres-test", + "jdbc-remote-old-postgres-test", + "jdbc-dbm-forked-tests", + "jdbc-decorator-forked-tests", + "jdbc-instrumentation-forked-tests", + "jdbc-oracle-forked-tests", + "jdbc-sql-server-forked-tests", + "jdbc-remote-dbm-forked-test", + "jdbc-remote-dbm-prepared-forked-test", + "jdbc-remote-instrumentation-forked-test", + "jdbc-other-forked-tests", + ] suffixes = ["-common", "-stubs", "-iast"] } diff --git a/dd-java-agent/instrumentation/jdbc/build.gradle b/dd-java-agent/instrumentation/jdbc/build.gradle index dc2622fdec5..8d64c0ea833 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -95,6 +95,90 @@ tasks.named("latestDepJava11Test", Test) { } } +def ciForkedTestGroups = [ + jdbcDbmForkedTest: [ + includes: ['**/DBM*ForkedTest*'], + ], + jdbcDecoratorForkedTest: [ + includes: ['**/JDBCDecorator*ForkedTest*'], + ], + jdbcInstrumentationForkedTest: [ + includes: ['**/DriverInstrumentation*ForkedTest*', '**/JDBCInstrumentation*ForkedTest*',], + ], + jdbcOracleForkedTest: [ + includes: ['**/Oracle*ForkedTest*'], + ], + jdbcSqlServerForkedTest: [ + includes: ['**/SQLServer*ForkedTest*'], + ], + jdbcRemoteDbmForkedTest: [ + includes: ['**/RemoteDBMTraceInjectedForkedTest.class'], + usesContainers: true, + ], + jdbcRemoteDbmPreparedForkedTest: [ + includes: ['**/RemoteDBMTraceInjectedForkedTestTracePreparedStatements.class'], + usesContainers: true, + ], + jdbcRemoteInstrumentationForkedTest: [ + includes: ['**/RemoteJDBCInstrumentationV1ForkedTest.class'], + usesContainers: true, + ], + // Keep an empty catch-all so newly added forked tests remain covered. + jdbcOtherForkedTest: [ + includes: ['**/*ForkedTest*'], + excludes: [ + '**/DBM*ForkedTest*', + '**/DriverInstrumentation*ForkedTest*', + '**/JDBCDecorator*ForkedTest*', + '**/JDBCInstrumentation*ForkedTest*', + '**/Oracle*ForkedTest*', + '**/RemoteDBMTraceInjectedForkedTest.class', + '**/RemoteDBMTraceInjectedForkedTestTracePreparedStatements.class', + '**/RemoteJDBCInstrumentationV1ForkedTest.class', + '**/SQLServer*ForkedTest*', + ], + usesContainers: true, + allowNoTests: true, + ], +] + +ciForkedTestGroups.each { taskName, groupConfig -> + tasks.register(taskName, Test) { + group = LifecycleBasePlugin.VERIFICATION_GROUP + useJUnitPlatform() + testClassesDirs = sourceSets.test.output.classesDirs + classpath = sourceSets.test.runtimeClasspath + setIncludes(groupConfig.includes) + setExcludes(groupConfig.excludes ?: []) + if (groupConfig.allowNoTests) { + failOnNoDiscoveredTests = false + } + } +} + +// The generated forkedTest task is replaced by the disjoint tasks above. This keeps local check and +// allTests coverage unchanged while allowing CI to schedule each group independently. +tasks.named("forkedTest", Test) { + enabled = false +} + +def remoteTestPattern = '**/RemoteJDBCInstrumentationV0Test*' +def ciRemoteTestGroups = [ + jdbcRemoteTest: [sourceSet: sourceSets.test, originalTask: tasks.named('test')], + jdbcRemoteOldH2Test: [sourceSet: sourceSets.oldH2Test, originalTask: tasks.named('oldH2Test')], + jdbcRemoteOldPostgresTest: [sourceSet: sourceSets.oldPostgresTest, originalTask: tasks.named('oldPostgresTest')], +] + +ciRemoteTestGroups.each { taskName, groupConfig -> + tasks.register(taskName, Test) { + group = LifecycleBasePlugin.VERIFICATION_GROUP + useJUnitPlatform() + testClassesDirs = groupConfig.sourceSet.output.classesDirs + classpath = groupConfig.sourceSet.runtimeClasspath + include remoteTestPattern + } +} + tasks.withType(GroovyCompile).configureEach { configureCompiler( it, @@ -105,8 +189,53 @@ tasks.withType(GroovyCompile).configureEach { } tasks.withType(Test).configureEach { - usesService(testcontainersLimit) + if (!ciForkedTestGroups.containsKey(name) || ciForkedTestGroups[name].usesContainers) { + usesService(testcontainersLimit) + } +} + +// In sharded CI, the virtual child projects below own the default JDBC suites. Outside sharded CI, +// allTests retains the convention plugin's normal dependencies and remains the single local entry point. +if (rootProject.providers.gradleProperty("slot").isPresent()) { + tasks.named("allTests") { + setDependsOn([]) + } + ciRemoteTestGroups.each { taskName, groupConfig -> + groupConfig.originalTask.configure { + exclude remoteTestPattern + } + } +} + +def ciTestShards = [ + 'jdbc-test': tasks.named('test'), + 'jdbc-remote-test': tasks.named('jdbcRemoteTest'), + 'jdbc-old-h2-test': tasks.named('oldH2Test'), + 'jdbc-remote-old-h2-test': tasks.named('jdbcRemoteOldH2Test'), + 'jdbc-old-postgres-test': tasks.named('oldPostgresTest'), + 'jdbc-remote-old-postgres-test': tasks.named('jdbcRemoteOldPostgresTest'), + 'jdbc-dbm-forked-tests': tasks.named('jdbcDbmForkedTest'), + 'jdbc-decorator-forked-tests': tasks.named('jdbcDecoratorForkedTest'), + 'jdbc-instrumentation-forked-tests': tasks.named('jdbcInstrumentationForkedTest'), + 'jdbc-oracle-forked-tests': tasks.named('jdbcOracleForkedTest'), + 'jdbc-sql-server-forked-tests': tasks.named('jdbcSqlServerForkedTest'), + 'jdbc-remote-dbm-forked-test': tasks.named('jdbcRemoteDbmForkedTest'), + 'jdbc-remote-dbm-prepared-forked-test': tasks.named('jdbcRemoteDbmPreparedForkedTest'), + 'jdbc-remote-instrumentation-forked-test': tasks.named('jdbcRemoteInstrumentationForkedTest'), + 'jdbc-other-forked-tests': tasks.named('jdbcOtherForkedTest'), +] + +def ciShardProjectPaths = [:] +ciTestShards.each { childName, testTask -> + def childPath = ":dd-java-agent:instrumentation:jdbc:$childName" + ciShardProjectPaths[testTask.get().path] = childPath + project(childPath) { + tasks.register("allTests") { + dependsOn(testTask) + } + } } +rootProject.extensions.extraProperties.set('ciShardProjectPaths', ciShardProjectPaths) tasks.named("latestDepJava11Test", Test) { testJvmConstraints { diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-dbm-forked-tests/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-dbm-forked-tests/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-dbm-forked-tests/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-decorator-forked-tests/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-decorator-forked-tests/build.gradle new file mode 100644 index 00000000000..d29650ffa17 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-decorator-forked-tests/build.gradle @@ -0,0 +1 @@ +// CI-only virtual project; its allTests task is registered by the parent JDBC project. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-instrumentation-forked-tests/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-instrumentation-forked-tests/build.gradle new file mode 100644 index 00000000000..d29650ffa17 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-instrumentation-forked-tests/build.gradle @@ -0,0 +1 @@ +// CI-only virtual project; its allTests task is registered by the parent JDBC project. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-old-h2-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-old-h2-test/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-old-h2-test/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-old-postgres-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-old-postgres-test/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-old-postgres-test/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-oracle-forked-tests/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-oracle-forked-tests/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-oracle-forked-tests/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-other-forked-tests/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-other-forked-tests/build.gradle new file mode 100644 index 00000000000..d29650ffa17 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-other-forked-tests/build.gradle @@ -0,0 +1 @@ +// CI-only virtual project; its allTests task is registered by the parent JDBC project. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-forked-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-forked-test/build.gradle new file mode 100644 index 00000000000..d29650ffa17 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-forked-test/build.gradle @@ -0,0 +1 @@ +// CI-only virtual project; its allTests task is registered by the parent JDBC project. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-prepared-forked-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-prepared-forked-test/build.gradle new file mode 100644 index 00000000000..d29650ffa17 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-prepared-forked-test/build.gradle @@ -0,0 +1 @@ +// CI-only virtual project; its allTests task is registered by the parent JDBC project. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-remote-instrumentation-forked-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-remote-instrumentation-forked-test/build.gradle new file mode 100644 index 00000000000..d29650ffa17 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-remote-instrumentation-forked-test/build.gradle @@ -0,0 +1 @@ +// CI-only virtual project; its allTests task is registered by the parent JDBC project. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-remote-old-h2-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-remote-old-h2-test/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-remote-old-h2-test/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-remote-old-postgres-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-remote-old-postgres-test/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-remote-old-postgres-test/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-remote-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-remote-test/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-remote-test/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-sql-server-forked-tests/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-sql-server-forked-tests/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-sql-server-forked-tests/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/dd-java-agent/instrumentation/jdbc/jdbc-test/build.gradle b/dd-java-agent/instrumentation/jdbc/jdbc-test/build.gradle new file mode 100644 index 00000000000..894afd1a877 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/jdbc-test/build.gradle @@ -0,0 +1 @@ +// CI shard project configured by the parent JDBC build. diff --git a/docs/ci-test-shard-weights.md b/docs/ci-test-shard-weights.md index b805040c554..95ba8ff6212 100644 --- a/docs/ci-test-shard-weights.md +++ b/docs/ci-test-shard-weights.md @@ -38,7 +38,8 @@ Weights come from Datadog CI Visibility test events at the **module** level, ove 4. Divide each project's total by the pipeline count, and convert from nanoseconds to seconds. The result is a mean per pipeline, not a median. -For example, `jdbc` summed to 548,323.5 seconds over 491 pipelines, giving a weight of `1116.7`. +For example, `jdbc` summed to 548,323.5 seconds over 491 pipelines, giving a weight of `1116.7` +before its test suites were split into independent CI shard projects. Measure every project listed in `settings.gradle.kts` one by one (e.g. `@test.module:lettuce-5.0_*`) instead of reading a single grouped aggregation or guessing family prefixes: @@ -59,6 +60,23 @@ date in `_comment`, update the expected entry count in `TestShardBalancerTest`, heaviest projects land in different shards, and that the modeled instrumentation shards stay balanced, with a max/min load ratio of at most 1.25. That ratio is computed from the weights, not measured, see below. +## JDBC suite shards + +The JDBC instrumentation keeps one Gradle source module, but its `test_inst` work is exposed through 15 virtual +child projects so the balancer can assign its existing suites to different shards. The child projects delegate to +test tasks in the parent project; they do not copy tests or change dependencies. Local `allTests` and `check` still +run every suite from the JDBC project as before. + +Pipeline `144158285` provided a coverage-complete measurement of the refined split on JVM 11: 46 suites and 1,814 +passing tests. It showed that the remote database suites dominate several tasks. The three regular version tasks +therefore expose `RemoteJDBCInstrumentationV0Test` separately from their remaining suites, and the three remote +forked classes each have their own virtual project. The remaining forked tasks form exhaustive, disjoint groups +across all 22 concrete forked classes; an unweighted catch-all keeps newly added forked classes covered. + +The largest measured JDBC unit after this split is the old H2 remote suite at 321.831 s, down 71.18% from the +original 1116.7-second JDBC project. The next largest units are the remote DBM fork at 310.736 s and the remote +instrumentation fork at 279.971 s. The checked-in weights come directly from that pipeline's suite durations. + ## Known limitation: the heaviest project sets a floor A project's tests always run in a single shard, and tests run in parallel within a shard. The balancer only adds up @@ -66,22 +84,23 @@ seconds, so it cannot see that a shard dominated by one large project finishes l spread over many small projects. In the first pipeline using this balancer, shards 1/8 and 4/8 ran almost the same total test time (2312 s and 2292 s), yet took 39 and 24 minutes: shard 1/8 held `jdbc`. -The two heaviest projects per pipeline are currently: +Before the JDBC suite split, the two heaviest projects per pipeline were: - `:dd-java-agent:instrumentation:jdbc`: 1116.7 s, about 18.6 minutes; - `:dd-java-agent:instrumentation:lettuce:lettuce-5.0`: 978.1 s, about 16.3 minutes. -The slowest shard can therefore never be faster than the heaviest single project, plus job setup. A project's -wall-clock span is also longer than its summed test time: in that first pipeline, the `jdbc` tests (20.5 minutes of -summed test time) spanned 27.6 minutes, starting about 10 minutes into the job, so its shard took 39 minutes. Under -the previous hash-based assignment, the `jdbc` shard was already the slowest one. +After the split, JDBC no longer sets that floor; `lettuce-5.0` is the heaviest remaining project. The slowest shard +can never be faster than the heaviest single project, plus job setup. A project's wall-clock span is also longer +than its summed test time: in that first pipeline, the `jdbc` tests (20.5 minutes of summed test time) spanned 27.6 +minutes, starting about 10 minutes into the job, so its shard took 39 minutes. Under the previous hash-based +assignment, the `jdbc` shard was already the slowest one. The modeled max/min ratio is optimistic whenever one project approaches the target shard time, so treat the 1.25 bound as a check of the model rather than a guarantee for wall-clock time. -The two heaviest projects must not share a shard, otherwise their floors stack. Capping weights would not help: -under-weighting `jdbc` makes the model look balanced while letting more work pile onto the `jdbc` shard. Lowering the -floor needs finer-grained sharding than whole projects. +The two heaviest projects must not share a shard, otherwise their floors stack. Capping weights only makes the model +look balanced while letting more work pile onto the affected shard. Lowering the floor requires splitting the work +into independently scheduled units, as the JDBC suite shards do above. ## When to refresh diff --git a/settings.gradle.kts b/settings.gradle.kts index 468d89c5cb4..1cf2e47fb42 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -424,6 +424,21 @@ include( ":dd-java-agent:instrumentation:jboss:jboss-logmanager-1.1", ":dd-java-agent:instrumentation:jboss:jboss-modules-1.3", ":dd-java-agent:instrumentation:jdbc:scalikejdbc-3.5", + ":dd-java-agent:instrumentation:jdbc:jdbc-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-old-h2-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-old-h2-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-old-postgres-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-old-postgres-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-dbm-forked-tests", + ":dd-java-agent:instrumentation:jdbc:jdbc-decorator-forked-tests", + ":dd-java-agent:instrumentation:jdbc:jdbc-instrumentation-forked-tests", + ":dd-java-agent:instrumentation:jdbc:jdbc-oracle-forked-tests", + ":dd-java-agent:instrumentation:jdbc:jdbc-sql-server-forked-tests", + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-forked-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-prepared-forked-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-instrumentation-forked-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-other-forked-tests", ":dd-java-agent:instrumentation:jdbc", ":dd-java-agent:instrumentation:jedis:jedis-1.4", ":dd-java-agent:instrumentation:jedis:jedis-3.0",