Skip to content

Commit d192716

Browse files
authored
Merge branch 'main' into mutators
2 parents c15f431 + 4b142bd commit d192716

784 files changed

Lines changed: 3640 additions & 3136 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/agents/knowledge/general-rules.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ When a "Knowledge File" is listed, load it from `knowledge/` before reviewing th
2727
| Semconv | Dual semconv testing | `SemconvStability`, `maybeStable`, semconv Gradle tasks | `testing-semconv-stability.md` |
2828
| Testing | General test patterns | Test files in scope — assertion style, test method signatures and throws clauses, resource cleanup, attribute assertions | `testing-general-patterns.md` |
2929
| Testing | Experimental flag tests | `testExperimental`, experimental attribute assertions, `experimental` flags in JVM args or system properties | `testing-experimental-flags.md` |
30+
| Testing | Flag-gated / mode-dependent assertion shape (experimental, `testLatestDeps`, semconv) — shared accessor (`testLatestDeps()`, `emitStable*Semconv()`) or `EXPERIMENTAL_ATTRIBUTES` constant, inline ternary with `null` for "absent" | Test classes branching on `EXPERIMENTAL_ATTRIBUTES`, `testLatestDeps()`, or `emitOld*`/`emitStable*` | `testing-general-patterns.md` |
3031
| Library | TelemetryBuilder/getter/setter patterns | Library instrumentation classes | `library-patterns.md` |
3132
| API | Deprecation and breaking-change policy | Public API changes | `api-deprecation-policy.md` |
3233
| Config | Config property stability/renames/removals | `otel.instrumentation.*` property changes, `DeclarativeConfigUtil` or `ConfigProperties` usage | `config-property-stability.md` |
@@ -103,9 +104,8 @@ Reason about visibility from "what does the advice method directly reference?".
103104

104105
## [Style] `@SuppressWarnings` Usage
105106

106-
- Method-level `@SuppressWarnings` is preferred over class-level for tighter scope, but
107-
if more than one method in the class needs the same suppression, class-level is fine.
108-
Do not flag class-level `@SuppressWarnings` when multiple methods use the suppressed API.
107+
- Place `@SuppressWarnings` on the single member that needs it, or on the class when two
108+
or more members in the class need the same suppression.
109109
- **Do not add `@SuppressWarnings("deprecation")` unless the build fails without it.**
110110
The project disables javac's `-Xlint:deprecation` globally and uses a custom Error Prone
111111
check (`OtelDeprecatedApiUsage`) instead. Only add the annotation when it is actually
@@ -375,14 +375,17 @@ ambiguous and the cast would otherwise be required). Do not flag those cases.
375375

376376
## [Semconv] Constants by Module Type
377377

378-
- `library/src/main/`: incubating semconv constants (from
379-
`io.opentelemetry.semconv.incubating`) must be copied locally as `private static final`
380-
fields with a `// copied from <ClassName>` comment. Stable semconv constants (from
381-
`io.opentelemetry.semconv`) may be imported directly.
378+
- `library/src/main/`: constants from `io.opentelemetry.semconv.incubating.*` must be
379+
copied locally as `private static final` fields with a `// copied from <ClassName>`
380+
comment. Constants from `io.opentelemetry.semconv.*` (stable) must be imported
381+
directly via `import static` and must not be copied locally.
382382
- `javaagent/src/main/`: all semconv artifact constants (stable and incubating) may be used
383383
directly.
384384
- tests: all semconv artifact constants are allowed.
385385

386+
The trigger for copying is the import package, not the constant name. Only convert an
387+
import to a local copy when it comes from `io.opentelemetry.semconv.incubating.*`.
388+
386389
## [NewModule] New Instrumentation Checklist
387390

388391
If a new module is added, verify all of the following:

.github/agents/knowledge/gradle-conventions.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ Flag `build.gradle.kts` dependencies that appear unused or redundant:
157157
- A dependency that duplicates something already provided transitively.
158158
- A `testImplementation` dependency for a library not used in tests.
159159

160+
### Never declare `javaagent-bootstrap` explicitly in javaagent modules
161+
162+
The `otel.javaagent-instrumentation` convention plugin already provides
163+
`javaagent-bootstrap` on the `compileOnly` classpath transitively. Do not add
164+
`compileOnly(project(":javaagent-bootstrap"))` to a javaagent module's
165+
`build.gradle.kts`, and remove it if present.
166+
160167
## Custom Test Tasks
161168

162169
Every custom `Test` task registered with `val foo by registering(Test::class)` **must** include
@@ -215,15 +222,16 @@ block, not repeated on each individual task.
215222
If a property or JVM arg is moved into `withType<Test>().configureEach`, remove any now-redundant
216223
copies from individual tasks unless a task intentionally overrides the shared value.
217224

218-
When the module's `build.gradle.kts` does not explicitly register additional `Test` tasks,
219-
`tasks.test { ... }` is fine — **do not** convert it to `withType<Test>().configureEach` and
220-
do not flag it.
225+
**When the module has only a single test task, prefer the simple `tasks.test { ... }` form.**
226+
Do **not** convert `tasks.test { ... }` to `withType<Test>().configureEach` in single-test-task
227+
modules, and do **not** flag the simple form as a problem. The `withType<Test>().configureEach`
228+
form is only justified when the same `build.gradle.kts` actually registers additional `Test` tasks.
221229

222230
**`latestDepTest` does not count as a second test task for this rule.** It is registered
223231
implicitly by the convention plugin when `testLatestDeps` is set, and it inherits the
224232
configuration of `tasks.test`. A module with only a `tasks.test { ... }` block and no
225233
`by registering(Test::class)` declarations is a single-test-task module — leave it alone
226-
even if `testLatestDeps = true`.
234+
(use the simple form) even if `testLatestDeps = true`.
227235

228236
Only consider converting to `withType<Test>().configureEach` when the **same
229237
`build.gradle.kts`** explicitly registers one or more additional `Test` tasks via
@@ -261,9 +269,11 @@ review**. Only verify correctness when they are already present.
261269

262270
When already present, verify:
263271

264-
- `collectMetadata` is in `withType<Test>().configureEach` (or `tasks.test` if the module
265-
does not explicitly register additional `Test` tasks — `latestDepTest` does not count) —
266-
never on individual tasks.
272+
- `collectMetadata` is in `tasks.test` for single-test-task modules, or in
273+
`withType<Test>().configureEach` for modules that explicitly register additional `Test`
274+
tasks via `by registering(Test::class)` (`latestDepTest` does not count) — never on
275+
individual tasks. Do not use
276+
`withType<Test>().configureEach { ... }` in single-test-task modules.
267277
- `metadataConfig` is on each non-default task. It may also appear on the default `test`
268278
task when that task itself runs with non-default `jvmArgs` (e.g., an experimental flag
269279
enabled module-wide via `withType<Test>().configureEach { jvmArgs(...) }`); in that case

.github/agents/knowledge/testing-experimental-flags.md

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ block but there is no dedicated `testExperimental` task, fix it:
2828

2929
1. Create a `testExperimental` task (see Gradle Task Setup below).
3030
2. Move the experimental flag out of the shared/default task config into `testExperimental`.
31-
3. Add a `private static final boolean EXPERIMENTAL_ATTRIBUTES` field to test classes.
32-
4. Wrap experimental attribute assertions with the `experimental()` helper.
33-
5. Wire the new task into `check`.
31+
3. Add a `private static final boolean EXPERIMENTAL_ATTRIBUTES` field to test classes and
32+
gate experimental attribute assertions on it (see Java Test Patterns below).
33+
4. Wire the new task into `check`.
3434

3535
## Gradle Task Setup
3636

@@ -51,30 +51,38 @@ val testExperimental by registering(Test::class) {
5151

5252
## Java Test Patterns
5353

54-
Read the flag once into a `private static final boolean` at class level:
54+
For the cross-cutting shape — inline ternary with `null` for "absent", when to use top-level
55+
`if` blocks, and `assumeTrue(...)` guidance — see
56+
[testing-general-patterns.md](testing-general-patterns.md#flag-gated--mode-dependent-assertions).
57+
The experimental-specific patterns below build on that shape.
58+
59+
### Hoist the flag into a per-class `EXPERIMENTAL_ATTRIBUTES` constant
60+
61+
The property name is module-specific, so there is no shared accessor. Read it once into a
62+
`private static final boolean` near the top of the class and reference the constant
63+
everywhere in the file:
5564

5665
```java
5766
private static final boolean EXPERIMENTAL_ATTRIBUTES =
5867
Boolean.getBoolean("otel.instrumentation.<module>.experimental-span-attributes");
5968
```
6069

61-
Use inline ternary in assertions — `null` means attribute expected absent:
70+
When multiple experimental flags coexist in one class, use a more specific name per flag.
6271

63-
```java
64-
equalTo(ExperimentalAttributes.SOME_ATTR, EXPERIMENTAL_ATTRIBUTES ? "value" : null)
65-
```
72+
### Single-arg `experimental(value)` helper
6673

67-
When many assertions share the flag, extract an `experimental()` helper:
74+
Experimental attributes are by definition absent when the flag is off, so the off-branch is
75+
always `null`. When several assertions in the same class gate attributes on
76+
`EXPERIMENTAL_ATTRIBUTES`, extract a tiny helper:
6877

6978
```java
7079
@Nullable
7180
private static <T> T experimental(T value) {
7281
return EXPERIMENTAL_ATTRIBUTES ? value : null;
7382
}
83+
84+
equalTo(SOME_KEY, experimental("value"))
7485
```
7586

7687
For multiple test classes sharing the same flag, move the helper into a shared
7788
`ExperimentalTestHelper` class and static-import it.
78-
79-
Use `assumeTrue(EXPERIMENTAL_ATTRIBUTES)` only when an entire test is meaningful in
80-
experimental mode only — prefer the ternary/helper pattern so both modes are exercised.

.github/agents/knowledge/testing-general-patterns.md

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@
4848
- In JUnit tests, when an `AutoCloseable` is intended to remain live for most or all of the test
4949
and only needs cleanup at test end, prefer `AutoCleanupExtension` with `deferCleanup(...)`
5050
over wrapping most of the test body in try-with-resources.
51-
- For resources created in `@BeforeAll` or other class-scoped setup, prefer
52-
`AutoCleanupExtension` with `deferAfterAll(...)` over nested `@AfterAll` cleanup
53-
chains. Do not introduce or keep `AutoCleanupExtension` solely for a single
54-
`deferAfterAll(...)` call — use a plain `@AfterAll` instead.
51+
- Use `AutoCleanupExtension.deferAfterAll(...)` only for cleanup actions registered
52+
dynamically (from inside test methods or other runtime-conditional setup). For a
53+
fixed set of class-scoped fields known at class-init time, use a plain `@AfterAll`
54+
that closes each field directly.
5555
- Reuse an existing `cleanup` extension when one is already in scope.
5656
Otherwise, add a `@RegisterExtension` field when the deferred-cleanup pattern improves
5757
clarity or avoids wrapping most of the test body.
@@ -135,3 +135,41 @@ unless the span ordering within a trace is genuinely non-deterministic (e.g., co
135135
producers/consumers, thread-pool fan-out, or channel interleaving). Sequential operations
136136
like `repeat {}` loops, single-child traces, and `flux` sequential emission produce spans
137137
in deterministic order — use `hasSpansSatisfyingExactly` for those.
138+
139+
## Flag-Gated / Mode-Dependent Assertions
140+
141+
Several test modes change which attributes, span names, status codes, or span indexes are
142+
expected:
143+
144+
- Experimental attributes (`-Dotel.instrumentation.<module>.experimental-*=true`) — see
145+
[testing-experimental-flags.md](testing-experimental-flags.md).
146+
- Semconv stability (`-Dotel.semconv-stability.opt-in=...`) — see
147+
[testing-semconv-stability.md](testing-semconv-stability.md).
148+
- `testLatestDeps` Gradle property — runs against the newest supported library versions
149+
instead of the pinned earliest-supported ones.
150+
151+
### Read the flag through a shared static helper, not a per-class field
152+
153+
Each flag has a shared static accessor; static-import it and call it directly. Never call
154+
`Boolean.getBoolean("…")` inline and never duplicate the property-name string at the call
155+
site.
156+
157+
| Flag | Shared accessor | Where it lives |
158+
| --- | --- | --- |
159+
| `-PtestLatestDeps=true` | `testLatestDeps()` | `io.opentelemetry.instrumentation.testing.util.TestLatestDeps` (testing-common) |
160+
| `otel.semconv-stability.opt-in=…` | `emitStableDatabaseSemconv()`, `emitOldDatabaseSemconv()`, `emitStableCodeSemconv()`, etc. | `io.opentelemetry.instrumentation.api.internal.SemconvStability` |
161+
| `otel.instrumentation.<module>.experimental-*` | per-module `EXPERIMENTAL_ATTRIBUTES` constant — see [testing-experimental-flags.md](testing-experimental-flags.md) | within the test class |
162+
163+
### Inline ternary in `equalTo(...)` with `null` for "absent"
164+
165+
Push the ternary as deep as possible — into the `equalTo` value or single attribute key —
166+
rather than duplicating two whole `hasAttributesSatisfyingExactly(...)` blocks under a
167+
`flag ? a : b`. The assertion API treats `null` as "expect attribute absent":
168+
169+
```java
170+
equalTo(DB_USER, emitStableDatabaseSemconv() ? null : USER_DB)
171+
equalTo(ERROR_TYPE, emitStableDatabaseSemconv() ? "42601" : null)
172+
equalTo(SOME_KEY, EXPERIMENTAL_ATTRIBUTES ? "value" : null)
173+
span.hasName(testLatestDeps() ? "GET" : "HTTP GET")
174+
.hasParent(trace.getSpan(testLatestDeps() ? 0 : 1))
175+
```

.github/agents/knowledge/testing-semconv-stability.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,30 @@ for other domains `check { dependsOn(testStableSemconv) }`.
7676

7777
## Asserting Attributes in Tests
7878

79-
Preferred approach (most compact) — inline ternary with `emitStable*()`, where `null` means
80-
the attribute is expected absent:
79+
For the cross-cutting shape — inline ternary with `null` for "absent", static-imported flag
80+
accessors, and `assumeTrue(...)` guidance — see
81+
[testing-general-patterns.md](testing-general-patterns.md#flag-gated--mode-dependent-assertions).
82+
The semconv-specific patterns below build on that shape.
8183

82-
```java
83-
equalTo(DB_USER, emitStableDatabaseSemconv() ? null : USER_DB)
84-
equalTo(ERROR_TYPE, emitStableDatabaseSemconv() ? "42601" : null)
85-
span.hasName(emitStableDatabaseSemconv() ? "SELECT" : "SELECT dbname")
86-
```
84+
### `maybeStable(OLD_KEY)` for 1:1 key renames
8785

88-
Use `maybeStable(oldKey)` when only the attribute key changes and the value stays the same.
89-
`maybeStable()` does NOT cover `dup` mode — use separate `if` blocks for that.
86+
Use `maybeStable(OLD_KEY)` when only the attribute *key* flips between old and stable
87+
semconv and the value is identical:
9088

9189
```java
9290
span.hasAttribute(equalTo(maybeStable(DB_STATEMENT), "SELECT ?"));
9391
```
9492

95-
Use separate `if` blocks (not `if/else`) when assertion structure differs significantly between
96-
modes — this ensures both branches execute in `dup` mode:
93+
`maybeStable()` does **not** cover `/dup` mode (it returns one key, not both), and does
94+
**not** apply where the mapping isn't 1:1 — for example `DB_RESPONSE_STATUS_CODE`
95+
`ERROR_TYPE`. Use `emitOld*()` / `emitStable*()` `if` blocks for those.
96+
97+
### `if` blocks (not `if/else`) when structure differs
98+
99+
When the *set* of asserted attributes differs between modes — not just values — use
100+
separate top-level `if` blocks rather than `if/else`. For domains that support `/dup` mode
101+
(currently RPC), this is required so both branches run; for other domains it's a habit
102+
that keeps the assertion `/dup`-safe if the domain ever adopts it:
97103

98104
```java
99105
if (emitStableCodeSemconv()) {
@@ -104,11 +110,6 @@ if (emitOldCodeSemconv()) {
104110
}
105111
```
106112

107-
Use `assumeTrue(emitStable*())` only when an entire test is meaningful in one mode only.
108-
109113
## Key Rules
110114

111115
- Add `@SuppressWarnings("deprecation")` at class level when tests use old Semconv constants.
112-
- Use `if` (not `if/else`) for dual-mode assertions so both branches run in `/dup` mode.
113-
- Do NOT use `maybeStable()` for `DB_RESPONSE_STATUS_CODE``ERROR_TYPE` — these don't have
114-
a 1:1 mapping. Use `emitOld*()`/`emitStable*()` `if` blocks instead.

.github/config/latest-dep-versions.json

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"com.ning:async-http-client#1.8.+": "1.8.17",
6161
"com.ning:async-http-client#1.9.+": "1.9.40",
6262
"com.noelios.restlet:com.noelios.restlet#+": "1.1.10",
63-
"com.openai:openai-java#+": "4.32.0",
63+
"com.openai:openai-java#+": "4.33.0",
6464
"com.oracle.database.jdbc:ojdbc8#+": "23.26.1.0.0",
6565
"com.oracle.database.jdbc:ucp#+": "23.26.1.0.0",
6666
"com.rabbitmq:amqp-client#+": "5.30.0",
@@ -110,7 +110,7 @@
110110
"com.typesafe.play:play_2.11#+": "2.7.9",
111111
"com.typesafe.play:play_2.12#+": "2.8.22",
112112
"com.typesafe.play:play_2.13#+": "2.9.10",
113-
"com.vaadin:flow-server#+": "25.1.3",
113+
"com.vaadin:flow-server#+": "25.1.4",
114114
"com.vaadin:vaadin-spring-boot-starter#14.11.+": "14.11.14",
115115
"com.xuxueli:xxl-job-core#+": "3.4.0",
116116
"com.xuxueli:xxl-job-core#2.2.+": "2.2.0",
@@ -308,16 +308,16 @@
308308
"org.apache.pekko:pekko-http_3#+": "1.3.0",
309309
"org.apache.pekko:pekko-stream_2.12#+": "1.4.0",
310310
"org.apache.pekko:pekko-stream_2.13#+": "1.5.0",
311-
"org.apache.pulsar:pulsar-client#+": "4.2.0",
312-
"org.apache.pulsar:pulsar-client-admin#+": "4.2.0",
311+
"org.apache.pulsar:pulsar-client#+": "4.2.1",
312+
"org.apache.pulsar:pulsar-client-admin#+": "4.2.1",
313313
"org.apache.rocketmq:rocketmq-client#+": "5.5.0",
314314
"org.apache.rocketmq:rocketmq-client-java#+": "5.2.0",
315315
"org.apache.rocketmq:rocketmq-test#+": "5.5.0",
316316
"org.apache.shardingsphere.elasticjob:elasticjob-lite-core#+": "3.0.4",
317317
"org.apache.shenyu:shenyu-spring-boot-starter-gateway#+": "2.7.0.3",
318318
"org.apache.shenyu:shenyu-web#+": "2.7.0.3",
319319
"org.apache.struts:struts2-core#+": "7.1.1",
320-
"org.apache.struts:struts2-core#6.+": "6.8.0",
320+
"org.apache.struts:struts2-core#6.+": "6.9.0",
321321
"org.apache.tapestry:tapestry-core#+": "5.9.1",
322322
"org.apache.tomcat.embed:tomcat-embed-core#+": "11.0.21",
323323
"org.apache.tomcat.embed:tomcat-embed-core#9.+": "9.0.117",
@@ -523,24 +523,24 @@
523523
"org.springframework:spring-webmvc#+": "7.0.7",
524524
"org.testcontainers:testcontainers-kafka#+": "2.0.5",
525525
"org.vibur:vibur-dbcp#+": "26.0",
526-
"redis.clients:jedis#+": "7.4.1",
526+
"redis.clients:jedis#+": "7.5.0",
527527
"redis.clients:jedis#2.+": "2.10.2",
528528
"redis.clients:jedis#3.+": "3.10.0",
529529
"software.amazon.awssdk.crt:aws-crt#+": "0.45.1",
530-
"software.amazon.awssdk:aws-core#+": "2.42.41",
531-
"software.amazon.awssdk:aws-json-protocol#+": "2.42.41",
532-
"software.amazon.awssdk:bedrockruntime#+": "2.42.41",
533-
"software.amazon.awssdk:dynamodb#+": "2.42.41",
534-
"software.amazon.awssdk:ec2#+": "2.42.41",
535-
"software.amazon.awssdk:kinesis#+": "2.42.41",
536-
"software.amazon.awssdk:lambda#+": "2.42.41",
537-
"software.amazon.awssdk:rds#+": "2.42.41",
538-
"software.amazon.awssdk:s3#+": "2.42.41",
539-
"software.amazon.awssdk:secretsmanager#+": "2.42.41",
540-
"software.amazon.awssdk:ses#+": "2.42.41",
541-
"software.amazon.awssdk:sfn#+": "2.42.41",
542-
"software.amazon.awssdk:sns#+": "2.42.41",
543-
"software.amazon.awssdk:sqs#+": "2.42.41",
530+
"software.amazon.awssdk:aws-core#+": "2.43.0",
531+
"software.amazon.awssdk:aws-json-protocol#+": "2.43.0",
532+
"software.amazon.awssdk:bedrockruntime#+": "2.43.0",
533+
"software.amazon.awssdk:dynamodb#+": "2.43.0",
534+
"software.amazon.awssdk:ec2#+": "2.43.0",
535+
"software.amazon.awssdk:kinesis#+": "2.43.0",
536+
"software.amazon.awssdk:lambda#+": "2.43.0",
537+
"software.amazon.awssdk:rds#+": "2.43.0",
538+
"software.amazon.awssdk:s3#+": "2.43.0",
539+
"software.amazon.awssdk:secretsmanager#+": "2.43.0",
540+
"software.amazon.awssdk:ses#+": "2.43.0",
541+
"software.amazon.awssdk:sfn#+": "2.43.0",
542+
"software.amazon.awssdk:sns#+": "2.43.0",
543+
"software.amazon.awssdk:sqs#+": "2.43.0",
544544
"tech.powerjob:powerjob-official-processors#+": "5.1.2",
545545
"tech.powerjob:powerjob-worker#+": "5.1.2"
546546
}

.github/repository-settings.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ Secrets:
2424

2525
## Secrets and variables > Actions
2626

27-
### Repository secrets
28-
29-
- `FLAKY_TEST_REPORTER_ACCESS_KEY` - owned by [@laurit](https://github.com/laurit)
30-
3127
### Organization secrets
3228

3329
- `DEVELOCITY_ACCESS_KEY` (scoped only to Java repos)

0 commit comments

Comments
 (0)