From 16952912cf5edcbb0e392d3d25f1834806e86477 Mon Sep 17 00:00:00 2001 From: Charles Cote Date: Mon, 12 Oct 2026 16:00:45 +0200 Subject: [PATCH 1/7] Split JDBC tests across CI shards --- .../gradle/plugin/ci/test-shard-weights.json | 10 +++- .../gradle/plugin/ci/TestShardBalancerTest.kt | 7 ++- .../instrumentation/jdbc/build.gradle | 51 ++++++++++++++++++- .../jdbc/jdbc-dbm-forked-tests/build.gradle | 1 + .../jdbc/jdbc-old-h2-test/build.gradle | 1 + .../jdbc/jdbc-old-postgres-test/build.gradle | 1 + .../jdbc-oracle-forked-tests/build.gradle | 1 + .../jdbc-sql-server-forked-tests/build.gradle | 1 + .../jdbc/jdbc-test/build.gradle | 1 + docs/ci-test-shard-weights.md | 32 ++++++++---- settings.gradle.kts | 6 +++ 11 files changed, 96 insertions(+), 16 deletions(-) create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-dbm-forked-tests/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-old-h2-test/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-old-postgres-test/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-oracle-forked-tests/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-sql-server-forked-tests/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-test/build.gradle 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..ea44462bd09 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 @@ -14,23 +14,28 @@ "jvm": "11", "job": "test_inst", "pipelines_observed": 491, - "projects_measured": 36 + "projects_measured": 35, + "projects_derived_from_measured_suites": 6 }, "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:akka:akka-http:akka-http-10.6": 258.0, + ":dd-java-agent:instrumentation:jdbc:jdbc-dbm-forked-tests": 224.0, ":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:jdbc:jdbc-old-h2-test": 215.0, + ":dd-java-agent:instrumentation:jdbc:jdbc-old-postgres-test": 209.0, + ":dd-java-agent:instrumentation:jdbc:jdbc-test": 208.0, ":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: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-oracle-forked-tests": 168.0, ":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, @@ -38,6 +43,7 @@ ":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:spark:spark_2.12": 113.9, + ":dd-java-agent:instrumentation:jdbc:jdbc-sql-server-forked-tests": 112.0, ":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, 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..c6c9efa9173 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(41) 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/jdbc/build.gradle b/dd-java-agent/instrumentation/jdbc/build.gradle index dc2622fdec5..d83e88d1e7e 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -95,6 +95,28 @@ tasks.named("latestDepJava11Test", Test) { } } +def ciForkedTestGroups = [ + jdbcDbmForkedTest: '**/DBM*ForkedTest*', + jdbcOracleForkedTest: '**/Oracle*ForkedTest*', + jdbcSqlServerForkedTest: '**/SQLServer*ForkedTest*', +] + +ciForkedTestGroups.each { taskName, includePattern -> + tasks.register(taskName, Test) { + group = LifecycleBasePlugin.VERIFICATION_GROUP + useJUnitPlatform() + testClassesDirs = sourceSets.test.output.classesDirs + classpath = sourceSets.test.runtimeClasspath + setIncludes([includePattern]) + } +} + +// 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 +} + tasks.withType(GroovyCompile).configureEach { configureCompiler( it, @@ -105,7 +127,34 @@ tasks.withType(GroovyCompile).configureEach { } tasks.withType(Test).configureEach { - usesService(testcontainersLimit) + if (!ciForkedTestGroups.containsKey(name)) { + 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([]) + } +} + +def ciTestShards = [ + 'jdbc-test': tasks.named('test'), + 'jdbc-old-h2-test': tasks.named('oldH2Test'), + 'jdbc-old-postgres-test': tasks.named('oldPostgresTest'), + 'jdbc-dbm-forked-tests': tasks.named('jdbcDbmForkedTest'), + 'jdbc-oracle-forked-tests': tasks.named('jdbcOracleForkedTest'), + 'jdbc-sql-server-forked-tests': tasks.named('jdbcSqlServerForkedTest'), +] + +ciTestShards.each { childName, testTask -> + project(":dd-java-agent:instrumentation:jdbc:$childName") { + tasks.register("allTests") { + dependsOn(testTask) + } + } } tasks.named("latestDepJava11Test", Test) { 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-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-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..320947d4447 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,18 @@ 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 six virtual +child projects so the balancer can assign its existing suites to different shards. The child projects delegate to +the original test tasks; they do not copy tests, change dependencies, or skip coverage. Local `allTests` and `check` +still run every suite from the JDBC project as before. + +The measured suite weights are 208 s for `test`, 215 s for `oldH2Test`, 209 s for `oldPostgresTest`, and 504 s for +`forkedTest`. The forked suite is further divided by its three source groups. Its provisional weights are allocated +by forked JVM count (four DBM classes, three Oracle classes, and two SQL Server classes) and should be replaced with +direct measurements after the first observation window. + ## 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 +79,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..fbbb706a6d3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -424,6 +424,12 @@ 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-old-h2-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-old-postgres-test", + ":dd-java-agent:instrumentation:jdbc:jdbc-dbm-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", ":dd-java-agent:instrumentation:jedis:jedis-1.4", ":dd-java-agent:instrumentation:jedis:jedis-3.0", From 71d98c3f6b988b10cd9ed4d7a05adfd1d3a32da7 Mon Sep 17 00:00:00 2001 From: Charles Cote Date: Mon, 12 Oct 2026 16:13:26 +0200 Subject: [PATCH 2/7] Exclude JDBC CI shards from naming validation --- dd-java-agent/instrumentation/build.gradle | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index fbacf010b3c..09077a98428 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -83,7 +83,16 @@ 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-20230227", // org-json does not use semver + "jdbc-test", + "jdbc-old-h2-test", + "jdbc-old-postgres-test", + "jdbc-dbm-forked-tests", + "jdbc-oracle-forked-tests", + "jdbc-sql-server-forked-tests", + ] suffixes = ["-common", "-stubs", "-iast"] } From 13745aed5c2016c2d621103f71f80730b207e282 Mon Sep 17 00:00:00 2001 From: Charles Cote Date: Mon, 12 Oct 2026 16:24:22 +0200 Subject: [PATCH 3/7] Format JDBC shard naming exclusions --- dd-java-agent/instrumentation/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index 09077a98428..00bd836529c 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -85,7 +85,8 @@ TaskProvider registerIndexTask(String indexTaskName, String indexer, S instrumentationNaming { // CI-only virtual projects delegate to the JDBC module's existing test tasks. exclusions = [ - "org-json-20230227", // org-json does not use semver + // org-json does not use semver + "org-json-20230227", "jdbc-test", "jdbc-old-h2-test", "jdbc-old-postgres-test", From 461e5c44d0c28c5bcc4575d5193948d99f980baa Mon Sep 17 00:00:00 2001 From: Charles Cote Date: Mon, 12 Oct 2026 17:20:14 +0200 Subject: [PATCH 4/7] Cover all JDBC forked tests in CI shards --- .../gradle/plugin/ci/test-shard-weights.json | 11 +++-- .../gradle/plugin/ci/TestShardBalancerTest.kt | 2 +- dd-java-agent/instrumentation/build.gradle | 3 ++ .../instrumentation/jdbc/build.gradle | 45 ++++++++++++++++--- .../jdbc-decorator-forked-tests/build.gradle | 1 + .../build.gradle | 1 + .../jdbc/jdbc-other-forked-tests/build.gradle | 1 + docs/ci-test-shard-weights.md | 9 ++-- settings.gradle.kts | 3 ++ 9 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-decorator-forked-tests/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-instrumentation-forked-tests/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-other-forked-tests/build.gradle 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 ea44462bd09..55c0d7729a8 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 @@ -15,7 +15,7 @@ "job": "test_inst", "pipelines_observed": 491, "projects_measured": 35, - "projects_derived_from_measured_suites": 6 + "projects_derived_from_measured_suites": 9 }, "weights": { ":dd-java-agent:instrumentation:lettuce:lettuce-5.0": 978.1, @@ -23,7 +23,6 @@ ":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:akka:akka-http:akka-http-10.6": 258.0, - ":dd-java-agent:instrumentation:jdbc:jdbc-dbm-forked-tests": 224.0, ":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:jdbc:jdbc-old-h2-test": 215.0, @@ -35,22 +34,26 @@ ":dd-java-agent:instrumentation:datastax-cassandra:datastax-cassandra-3.8": 175.4, ":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-oracle-forked-tests": 168.0, ":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-decorator-forked-tests": 137.5, ":dd-java-agent:instrumentation:spark:spark_2.12": 113.9, - ":dd-java-agent:instrumentation:jdbc:jdbc-sql-server-forked-tests": 112.0, ":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:jdbc:jdbc-dbm-forked-tests": 91.6, + ":dd-java-agent:instrumentation:jdbc:jdbc-instrumentation-forked-tests": 91.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-oracle-forked-tests": 68.7, + ":dd-java-agent:instrumentation:jdbc:jdbc-other-forked-tests": 68.7, ":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:jdbc:jdbc-sql-server-forked-tests": 45.9, ":dd-java-agent:instrumentation:jedis:jedis-3.0": 42.0, ":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, 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 c6c9efa9173..4be1b3cd663 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/ci/TestShardBalancerTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/ci/TestShardBalancerTest.kt @@ -109,7 +109,7 @@ class TestShardBalancerTest { @Test fun `bundled weights file is parsed`() { - assertThat(WEIGHTS).hasSize(41) + assertThat(WEIGHTS).hasSize(44) assertThat(WEIGHTS.values).allSatisfy { weight -> assertThat(weight).isPositive() } assertThat(heaviestProjects(2)).containsExactly(LETTUCE_5_0, AKKA_HTTP_10_0) } diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index 00bd836529c..155923062ff 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -91,8 +91,11 @@ instrumentationNaming { "jdbc-old-h2-test", "jdbc-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-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 d83e88d1e7e..5e344c0f434 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -96,18 +96,48 @@ tasks.named("latestDepJava11Test", Test) { } def ciForkedTestGroups = [ - jdbcDbmForkedTest: '**/DBM*ForkedTest*', - jdbcOracleForkedTest: '**/Oracle*ForkedTest*', - jdbcSqlServerForkedTest: '**/SQLServer*ForkedTest*', + jdbcDbmForkedTest: [ + includes: ['**/DBM*ForkedTest*'], + ], + jdbcDecoratorForkedTest: [ + includes: ['**/JDBCDecorator*ForkedTest*'], + ], + jdbcInstrumentationForkedTest: [ + includes: [ + '**/DriverInstrumentation*ForkedTest*', + '**/JDBCInstrumentation*ForkedTest*', + ], + ], + jdbcOracleForkedTest: [ + includes: ['**/Oracle*ForkedTest*'], + ], + jdbcSqlServerForkedTest: [ + includes: ['**/SQLServer*ForkedTest*'], + ], + // Keep a catch-all so newly added forked tests remain covered. This group currently contains the + // Remote* suites, which use database containers. + jdbcOtherForkedTest: [ + includes: ['**/*ForkedTest*'], + excludes: [ + '**/DBM*ForkedTest*', + '**/DriverInstrumentation*ForkedTest*', + '**/JDBCDecorator*ForkedTest*', + '**/JDBCInstrumentation*ForkedTest*', + '**/Oracle*ForkedTest*', + '**/SQLServer*ForkedTest*', + ], + usesContainers: true, + ], ] -ciForkedTestGroups.each { taskName, includePattern -> +ciForkedTestGroups.each { taskName, groupConfig -> tasks.register(taskName, Test) { group = LifecycleBasePlugin.VERIFICATION_GROUP useJUnitPlatform() testClassesDirs = sourceSets.test.output.classesDirs classpath = sourceSets.test.runtimeClasspath - setIncludes([includePattern]) + setIncludes(groupConfig.includes) + setExcludes(groupConfig.excludes ?: []) } } @@ -127,7 +157,7 @@ tasks.withType(GroovyCompile).configureEach { } tasks.withType(Test).configureEach { - if (!ciForkedTestGroups.containsKey(name)) { + if (!ciForkedTestGroups.containsKey(name) || ciForkedTestGroups[name].usesContainers) { usesService(testcontainersLimit) } } @@ -145,8 +175,11 @@ def ciTestShards = [ 'jdbc-old-h2-test': tasks.named('oldH2Test'), 'jdbc-old-postgres-test': tasks.named('oldPostgresTest'), '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-other-forked-tests': tasks.named('jdbcOtherForkedTest'), ] ciTestShards.each { childName, testTask -> 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-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/docs/ci-test-shard-weights.md b/docs/ci-test-shard-weights.md index 320947d4447..0870be97aee 100644 --- a/docs/ci-test-shard-weights.md +++ b/docs/ci-test-shard-weights.md @@ -62,15 +62,16 @@ max/min load ratio of at most 1.25. That ratio is computed from the weights, not ## JDBC suite shards -The JDBC instrumentation keeps one Gradle source module, but its `test_inst` work is exposed through six virtual +The JDBC instrumentation keeps one Gradle source module, but its `test_inst` work is exposed through nine virtual child projects so the balancer can assign its existing suites to different shards. The child projects delegate to the original test tasks; they do not copy tests, change dependencies, or skip coverage. Local `allTests` and `check` still run every suite from the JDBC project as before. The measured suite weights are 208 s for `test`, 215 s for `oldH2Test`, 209 s for `oldPostgresTest`, and 504 s for -`forkedTest`. The forked suite is further divided by its three source groups. Its provisional weights are allocated -by forked JVM count (four DBM classes, three Oracle classes, and two SQL Server classes) and should be replaced with -direct measurements after the first observation window. +`forkedTest`. The forked suite is further divided into six exhaustive, disjoint groups. Its provisional weights are +allocated across all 22 concrete forked test classes. A catch-all group currently contains the three `Remote*` +classes and ensures future forked tests remain covered. Replace these provisional weights with direct measurements +after the first observation window. ## Known limitation: the heaviest project sets a floor diff --git a/settings.gradle.kts b/settings.gradle.kts index fbbb706a6d3..410d5d58bd4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -428,8 +428,11 @@ include( ":dd-java-agent:instrumentation:jdbc:jdbc-old-h2-test", ":dd-java-agent:instrumentation:jdbc:jdbc-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-other-forked-tests", ":dd-java-agent:instrumentation:jdbc", ":dd-java-agent:instrumentation:jedis:jedis-1.4", ":dd-java-agent:instrumentation:jedis:jedis-3.0", From 5ccd64eff3470bb1b704c77a6944d74ca4bf3d9f Mon Sep 17 00:00:00 2001 From: Charles Cote Date: Mon, 12 Oct 2026 19:10:44 +0200 Subject: [PATCH 5/7] Honor virtual project slots for JDBC tests --- .../datadog/gradle/plugin/ci/CIJobsExtensions.kt | 2 ++ .../main/kotlin/dd-trace-java.ci-jobs.gradle.kts | 13 +++++++++++-- dd-java-agent/instrumentation/jdbc/build.gradle | 11 ++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) 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/dd-java-agent/instrumentation/jdbc/build.gradle b/dd-java-agent/instrumentation/jdbc/build.gradle index 5e344c0f434..b4589b46e6e 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -103,10 +103,7 @@ def ciForkedTestGroups = [ includes: ['**/JDBCDecorator*ForkedTest*'], ], jdbcInstrumentationForkedTest: [ - includes: [ - '**/DriverInstrumentation*ForkedTest*', - '**/JDBCInstrumentation*ForkedTest*', - ], + includes: ['**/DriverInstrumentation*ForkedTest*', '**/JDBCInstrumentation*ForkedTest*',], ], jdbcOracleForkedTest: [ includes: ['**/Oracle*ForkedTest*'], @@ -182,13 +179,17 @@ def ciTestShards = [ 'jdbc-other-forked-tests': tasks.named('jdbcOtherForkedTest'), ] +def ciShardProjectPaths = [:] ciTestShards.each { childName, testTask -> - project(":dd-java-agent:instrumentation:jdbc:$childName") { + 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 { From 337c99e3812baa356bf743d786b1b03470454fc2 Mon Sep 17 00:00:00 2001 From: Charles Cote Date: Mon, 12 Oct 2026 20:07:48 +0200 Subject: [PATCH 6/7] Split slow JDBC remote tests across CI shards --- .../gradle/plugin/ci/test-shard-weights.json | 29 +++++++----- .../gradle/plugin/ci/TestShardBalancerTest.kt | 2 +- dd-java-agent/instrumentation/build.gradle | 6 +++ .../instrumentation/jdbc/build.gradle | 45 ++++++++++++++++++- .../jdbc-remote-dbm-forked-test/build.gradle | 1 + .../build.gradle | 1 + .../build.gradle | 1 + .../jdbc/jdbc-remote-old-h2-test/build.gradle | 1 + .../build.gradle | 1 + .../jdbc/jdbc-remote-test/build.gradle | 1 + docs/ci-test-shard-weights.md | 22 +++++---- settings.gradle.kts | 6 +++ 12 files changed, 94 insertions(+), 22 deletions(-) create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-forked-test/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-remote-dbm-prepared-forked-test/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-remote-instrumentation-forked-test/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-remote-old-h2-test/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-remote-old-postgres-test/build.gradle create mode 100644 dd-java-agent/instrumentation/jdbc/jdbc-remote-test/build.gradle 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 55c0d7729a8..90d1d7c2b30 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 the coverage-complete pipeline 144153574", + "from 2026-10-12 after the first split exposed its slow remote suites.", "Projects absent from this map fall back to the default weight.", "See docs/ci-test-shard-weights.md to regenerate." ], @@ -15,23 +17,26 @@ "job": "test_inst", "pipelines_observed": 491, "projects_measured": 35, - "projects_derived_from_measured_suites": 9 + "projects_derived_from_measured_suites": 14 }, "weights": { ":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-test": 316.5, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-forked-test": 293.7, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-old-h2-test": 288.5, ":dd-java-agent:instrumentation:akka:akka-http:akka-http-10.6": 258.0, ":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:jdbc:jdbc-old-h2-test": 215.0, - ":dd-java-agent:instrumentation:jdbc:jdbc-old-postgres-test": 209.0, - ":dd-java-agent:instrumentation:jdbc:jdbc-test": 208.0, ":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:jdbc:jdbc-test": 186.7, + ":dd-java-agent:instrumentation:jdbc:jdbc-old-h2-test": 175.8, ":dd-java-agent:instrumentation:datastax-cassandra:datastax-cassandra-3.8": 175.4, + ":dd-java-agent:instrumentation:jdbc:jdbc-old-postgres-test": 172.3, ":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:couchbase:couchbase-3.2": 165.8, @@ -40,27 +45,29 @@ ":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-decorator-forked-tests": 137.5, ":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:jdbc:jdbc-dbm-forked-tests": 91.6, - ":dd-java-agent:instrumentation:jdbc:jdbc-instrumentation-forked-tests": 91.6, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-old-postgres-test": 93.5, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-prepared-forked-test": 90.3, + ":dd-java-agent:instrumentation:jdbc:jdbc-remote-instrumentation-forked-test": 86.7, ":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-oracle-forked-tests": 68.7, - ":dd-java-agent:instrumentation:jdbc:jdbc-other-forked-tests": 68.7, + ":dd-java-agent:instrumentation:jdbc:jdbc-instrumentation-forked-tests": 68.1, ":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:jdbc:jdbc-sql-server-forked-tests": 45.9, ":dd-java-agent:instrumentation:jedis:jedis-3.0": 42.0, + ":dd-java-agent:instrumentation:jdbc:jdbc-decorator-forked-tests": 40.3, ":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:jdbc:jdbc-dbm-forked-tests": 25.7, ":dd-java-agent:instrumentation:couchbase:couchbase-2.6": 25.6, ":dd-java-agent:instrumentation:synapse-3.0": 24.5, + ":dd-java-agent:instrumentation:jdbc:jdbc-oracle-forked-tests": 24.2, ":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.2 } } 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 4be1b3cd663..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,7 +109,7 @@ class TestShardBalancerTest { @Test fun `bundled weights file is parsed`() { - assertThat(WEIGHTS).hasSize(44) + assertThat(WEIGHTS).hasSize(49) assertThat(WEIGHTS.values).allSatisfy { weight -> assertThat(weight).isPositive() } assertThat(heaviestProjects(2)).containsExactly(LETTUCE_5_0, AKKA_HTTP_10_0) } diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index 155923062ff..534ba799ed5 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -88,13 +88,19 @@ instrumentationNaming { // 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 b4589b46e6e..cac0fab0aca 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -111,8 +111,20 @@ def ciForkedTestGroups = [ jdbcSqlServerForkedTest: [ includes: ['**/SQLServer*ForkedTest*'], ], + jdbcRemoteDbmForkedTest: [ + includes: ['**/RemoteDBMTraceInjectedForkedTest.class'], + usesContainers: true, + ], + jdbcRemoteDbmPreparedForkedTest: [ + includes: ['**/RemoteDBMTraceInjectedForkedTestTracePreparedStatements.class'], + usesContainers: true, + ], + jdbcRemoteInstrumentationForkedTest: [ + includes: ['**/RemoteJDBCInstrumentationV1ForkedTest.class'], + usesContainers: true, + ], // Keep a catch-all so newly added forked tests remain covered. This group currently contains the - // Remote* suites, which use database containers. + // forked suites not assigned above. jdbcOtherForkedTest: [ includes: ['**/*ForkedTest*'], excludes: [ @@ -121,6 +133,9 @@ def ciForkedTestGroups = [ '**/JDBCDecorator*ForkedTest*', '**/JDBCInstrumentation*ForkedTest*', '**/Oracle*ForkedTest*', + '**/RemoteDBMTraceInjectedForkedTest.class', + '**/RemoteDBMTraceInjectedForkedTestTracePreparedStatements.class', + '**/RemoteJDBCInstrumentationV1ForkedTest.class', '**/SQLServer*ForkedTest*', ], usesContainers: true, @@ -144,6 +159,23 @@ 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, @@ -165,17 +197,28 @@ 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'), ] 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/docs/ci-test-shard-weights.md b/docs/ci-test-shard-weights.md index 0870be97aee..c43843ec28b 100644 --- a/docs/ci-test-shard-weights.md +++ b/docs/ci-test-shard-weights.md @@ -62,16 +62,20 @@ max/min load ratio of at most 1.25. That ratio is computed from the weights, not ## JDBC suite shards -The JDBC instrumentation keeps one Gradle source module, but its `test_inst` work is exposed through nine virtual +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 -the original test tasks; they do not copy tests, change dependencies, or skip coverage. Local `allTests` and `check` -still run every suite from the JDBC project as before. - -The measured suite weights are 208 s for `test`, 215 s for `oldH2Test`, 209 s for `oldPostgresTest`, and 504 s for -`forkedTest`. The forked suite is further divided into six exhaustive, disjoint groups. Its provisional weights are -allocated across all 22 concrete forked test classes. A catch-all group currently contains the three `Remote*` -classes and ensures future forked tests remain covered. Replace these provisional weights with direct measurements -after the first observation window. +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 `144153574` provided the first coverage-complete measurement of the 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 modeled JDBC unit after this split is the base version's remote suite at 316.5 s, down 71.7% from the +original 1116.7-second JDBC project. The next largest units are the remote DBM fork at 293.7 s and the old H2 remote +suite at 288.5 s. The checked-in weights come directly from that pipeline's suite durations. ## Known limitation: the heaviest project sets a floor diff --git a/settings.gradle.kts b/settings.gradle.kts index 410d5d58bd4..1cf2e47fb42 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -425,13 +425,19 @@ include( ":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", From 98d11d6fd156f238573d2fa7fe3f5c0867294afe Mon Sep 17 00:00:00 2001 From: Charles Cote Date: Mon, 12 Oct 2026 21:10:45 +0200 Subject: [PATCH 7/7] Allow an empty JDBC catch-all shard --- .../gradle/plugin/ci/test-shard-weights.json | 32 +++++++++---------- .../instrumentation/jdbc/build.gradle | 7 ++-- docs/ci-test-shard-weights.md | 8 ++--- 3 files changed, 25 insertions(+), 22 deletions(-) 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 90d1d7c2b30..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,8 +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 the coverage-complete pipeline 144153574", - "from 2026-10-12 after the first split exposed its slow remote suites.", + "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." ], @@ -24,50 +24,50 @@ ":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-test": 316.5, - ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-forked-test": 293.7, - ":dd-java-agent:instrumentation:jdbc:jdbc-remote-old-h2-test": 288.5, + ":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:jdbc:jdbc-test": 186.7, - ":dd-java-agent:instrumentation:jdbc:jdbc-old-h2-test": 175.8, ":dd-java-agent:instrumentation:datastax-cassandra:datastax-cassandra-3.8": 175.4, - ":dd-java-agent:instrumentation:jdbc:jdbc-old-postgres-test": 172.3, + ":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:jdbc:jdbc-remote-old-postgres-test": 93.5, - ":dd-java-agent:instrumentation:jdbc:jdbc-remote-dbm-prepared-forked-test": 90.3, - ":dd-java-agent:instrumentation:jdbc:jdbc-remote-instrumentation-forked-test": 86.7, ":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-instrumentation-forked-tests": 68.1, + ":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": 40.3, + ":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:jdbc:jdbc-dbm-forked-tests": 25.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:jdbc:jdbc-oracle-forked-tests": 24.2, ":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:jdbc:jdbc-sql-server-forked-tests": 11.2 + ":dd-java-agent:instrumentation:jdbc:jdbc-sql-server-forked-tests": 11.867 } } diff --git a/dd-java-agent/instrumentation/jdbc/build.gradle b/dd-java-agent/instrumentation/jdbc/build.gradle index cac0fab0aca..8d64c0ea833 100644 --- a/dd-java-agent/instrumentation/jdbc/build.gradle +++ b/dd-java-agent/instrumentation/jdbc/build.gradle @@ -123,8 +123,7 @@ def ciForkedTestGroups = [ includes: ['**/RemoteJDBCInstrumentationV1ForkedTest.class'], usesContainers: true, ], - // Keep a catch-all so newly added forked tests remain covered. This group currently contains the - // forked suites not assigned above. + // Keep an empty catch-all so newly added forked tests remain covered. jdbcOtherForkedTest: [ includes: ['**/*ForkedTest*'], excludes: [ @@ -139,6 +138,7 @@ def ciForkedTestGroups = [ '**/SQLServer*ForkedTest*', ], usesContainers: true, + allowNoTests: true, ], ] @@ -150,6 +150,9 @@ ciForkedTestGroups.each { taskName, groupConfig -> classpath = sourceSets.test.runtimeClasspath setIncludes(groupConfig.includes) setExcludes(groupConfig.excludes ?: []) + if (groupConfig.allowNoTests) { + failOnNoDiscoveredTests = false + } } } diff --git a/docs/ci-test-shard-weights.md b/docs/ci-test-shard-weights.md index c43843ec28b..95ba8ff6212 100644 --- a/docs/ci-test-shard-weights.md +++ b/docs/ci-test-shard-weights.md @@ -67,15 +67,15 @@ child projects so the balancer can assign its existing suites to different shard 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 `144153574` provided the first coverage-complete measurement of the split on JVM 11: 46 suites and 1,814 +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 modeled JDBC unit after this split is the base version's remote suite at 316.5 s, down 71.7% from the -original 1116.7-second JDBC project. The next largest units are the remote DBM fork at 293.7 s and the old H2 remote -suite at 288.5 s. The checked-in weights come directly from that pipeline's suite durations. +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