Skip to content

Commit 9f71038

Browse files
committed
backcompat
1 parent e528407 commit 9f71038

8 files changed

Lines changed: 384 additions & 67 deletions

File tree

.fossa.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -565,15 +565,15 @@ targets:
565565
- type: gradle
566566
path: ./
567567
target: ':instrumentation:jaxws:jaxws-2.0-cxf-3.0:javaagent'
568-
- type: gradle
569-
path: ./
570-
target: ':instrumentation:jaxws:jaxws-jws-api-1.1:javaagent'
571568
- type: gradle
572569
path: ./
573570
target: ':instrumentation:jaxws:jaxws-2.0-metro-2.2:javaagent'
574571
- type: gradle
575572
path: ./
576573
target: ':instrumentation:jaxws:jaxws-common:javaagent'
574+
- type: gradle
575+
path: ./
576+
target: ':instrumentation:jaxws:jaxws-jws-api-1.1:javaagent'
577577
- type: gradle
578578
path: ./
579579
target: ':instrumentation:jboss-logmanager:jboss-logmanager-appender-1.1:javaagent'

.github/agents/knowledge/api-deprecation-policy.md

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,23 @@
22

33
## Quick Reference
44

5-
- Use when: reviewing public API removals/renames, `@Deprecated` usage, stable-vs-alpha compatibility
6-
- Review focus: deprecate-then-remove timing, delegation direction, required Javadoc/CHANGELOG coverage
5+
- Use when: reviewing public API removals/renames, `@Deprecated` usage, stable-vs-alpha compatibility, or any module rename that touches user-facing config keys or emitted telemetry identity
6+
- Review focus: deprecate-then-remove timing, delegation direction, required Javadoc/CHANGELOG coverage, v3-preview gating for config keys and scope names
7+
8+
## What Counts as "Public API"
9+
10+
"API" here means **anything a user's code or configuration depends on by name**, including:
11+
12+
- Java symbols in published artifacts (classes, methods, fields in `:library`, `:testing`,
13+
`instrumentation-api*`).
14+
- User-facing configuration keys — `otel.instrumentation.<name>.enabled`, any
15+
`otel.instrumentation.*` property, and the equivalent declarative YAML keys.
16+
- Outgoing telemetry identity — anything users can match on in their backend, including
17+
`otel.scope.name`, span names, metric names, attribute keys, and attribute values. Users
18+
build dashboards, filters, and alerts on these values, so silently renaming them is a
19+
breaking change.
20+
21+
A rename of any of these surfaces is a breaking change even if no Java symbol moved.
722

823
## When Are Breaking Changes Allowed?
924

@@ -75,6 +90,74 @@ default void configure(IgnoredTypesBuilder builder, ConfigProperties config) {
7590
}
7691
```
7792

93+
## Module renames: config keys and emitted scope names
94+
95+
A module rename touches **two user-facing API surfaces** that must each be preserved by default
96+
and only change under `otel.instrumentation.common.v3-preview`. The mechanism differs because
97+
the surfaces are different: config keys can coexist as aliases, emitted scope names cannot.
98+
99+
### 1. `InstrumentationModule` names (controls `otel.instrumentation.<name>.enabled`)
100+
101+
The names passed to the `InstrumentationModule` constructor drive the
102+
`otel.instrumentation.<name>.enabled` config keys — any of them, not just the first. A rename
103+
silently breaks users who have the old key in their config.
104+
105+
Keep the pre-rename name by passing it inline alongside the current name using the
106+
{@code "<current>|deprecated:<old>"} marker recognized by the `InstrumentationModule`
107+
constructor:
108+
109+
```java
110+
public CxfInstrumentationModule() {
111+
super("cxf", "jaxws-2.0-cxf-3.0|deprecated:jaxws-cxf-3.0", "jaxws");
112+
}
113+
```
114+
115+
The framework (`DeprecatedInstrumentationNames.expand`) splits the marker and registers both
116+
names, so both `otel.instrumentation.jaxws-2.0-cxf-3.0.enabled` and
117+
`otel.instrumentation.jaxws-cxf-3.0.enabled` keep working (flat properties and YAML alike).
118+
Under `otel.instrumentation.common.v3-preview=true` the deprecated name is dropped; if the
119+
legacy key is explicitly set, a one-time WARNING is logged pointing at the new key.
120+
121+
No per-module `AgentCommonConfig` branching, `isV3Preview()` checks, or bespoke logging are
122+
needed — one string literal is the entire change.
123+
124+
### 2. Emitted instrumentation scope name (`INSTRUMENTATION_NAME` in `*Singletons`)
125+
126+
The `INSTRUMENTATION_NAME` string passed to `Instrumenter.builder(...)` becomes the
127+
`otel.scope.name` attribute on every emitted span / metric / log. A rename silently breaks
128+
dashboards and filters that match on the old scope.
129+
130+
Keep emitting the **pre-rename** scope name by default, and switch to the new one only under
131+
v3-preview:
132+
133+
```java
134+
public class CxfSingletons {
135+
private static final String INSTRUMENTATION_NAME =
136+
AgentCommonConfig.get().isV3Preview()
137+
? "io.opentelemetry.jaxws-2.0-cxf-3.0"
138+
// keep the pre-rename scope name so existing dashboards/filters on
139+
// otel.scope.name="io.opentelemetry.jaxws-cxf-3.0" continue to work
140+
: "io.opentelemetry.jaxws-cxf-3.0";
141+
...
142+
}
143+
```
144+
145+
Note the asymmetry with the config-key case: there the list carries **both** names at once
146+
(aliases); here only **one** scope name is emitted at a time, and the default is the **old**
147+
one. Do not log a deprecation warning here — users cannot switch the scope name without
148+
enabling v3-preview globally (which affects every module), so a warning would push them
149+
toward something they are not expected to enable generally.
150+
151+
### CHANGELOG
152+
153+
The rename is **not** a breaking change or a deprecation in the current release: by default
154+
the old config keys and scope names continue to work unchanged, and the new names are only
155+
visible under `otel.instrumentation.common.v3-preview` — a preview flag that users are not
156+
generally encouraged to enable. Do not add a `⚠️ Breaking changes to non-stable APIs` or
157+
`🚫 Deprecations` entry for this kind of rename. If mentioned at all, it belongs in whatever
158+
section tracks v3-preview changes. The breaking change will be recorded when v3-preview
159+
becomes the default in 3.0.
160+
78161
## What to Flag in Review
79162

80163
- **Breaking change without a prior deprecation**: a method/class was removed or its signature
@@ -98,3 +181,10 @@ default void configure(IgnoredTypesBuilder builder, ConfigProperties config) {
98181

99182
- **Missing CHANGELOG entry**: a breaking change PR that does not add an
100183
`⚠️ Breaking changes to non-stable APIs` bullet in the `Unreleased` section of `CHANGELOG.md`.
184+
185+
- **Module rename without backcompat**: `InstrumentationModule` constructor uses only the new
186+
name, dropping the pre-rename name that drove the legacy
187+
`otel.instrumentation.<old>.enabled` config key (it should be appended to the new name with
188+
the {@code "|deprecated:<old>"} marker so `DeprecatedInstrumentationNames` can gate it on
189+
v3-preview); and/or `*Singletons#INSTRUMENTATION_NAME` was changed unconditionally instead
190+
of being gated on `AgentCommonConfig.get().isV3Preview()`.
Lines changed: 185 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,197 @@
11
#!/bin/bash -e
22

3-
for dir in $(find instrumentation -name "*.java" | grep library/src/main/java | sed 's#/[^/]*$##' | sort -u); do
3+
check_source_set() {
4+
local source_set="$1"
5+
local expected_prefix="$2"
46

5-
module_name=$(echo "$dir" | sed 's#.*/\([^/]*\)/library/src/main/java[0-9]*/.*#\1#')
7+
for dir in $(find instrumentation -name "*.java" | grep "$source_set/src/main/java" | sed 's#/[^/]*$##' | sort -u); do
68

7-
if [[ "$module_name" =~ ^java- ]]; then
8-
continue
9-
fi
10-
if [[ "$module_name" == "jmx-metrics" ]]; then
11-
continue
12-
fi
13-
if [[ "$module_name" == "runtime-telemetry" ]]; then
14-
continue
15-
fi
16-
if [[ "$module_name" == "servlet-common" ]]; then
17-
continue
18-
fi
19-
if [[ "$module_name" == "graphql-java-common-12.0" ]]; then
20-
continue
21-
fi
9+
module_name=$(echo "$dir" | sed "s#.*/\([^/]*\)/$source_set/src/main/java[0-9]*/.*#\1#")
2210

23-
# these are possibly problematic
24-
if [[ "$dir" == "instrumentation/grpc-1.6/library/src/main/java/io/grpc/override" ]]; then
25-
continue
26-
fi
27-
if [[ "$dir" == "instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/lettuce/core/protocol" ]]; then
28-
continue
29-
fi
30-
if [[ "$dir" == "instrumentation/nats/nats-2.17/library/src/main/java/io/nats/client/impl" ]]; then
31-
continue
32-
fi
33-
if [[ "$dir" == "instrumentation/rxjava/rxjava-1.0/library/src/main/java/rx" ]]; then
34-
continue
35-
fi
11+
if [[ "$module_name" =~ ^java- ]]; then
12+
continue
13+
fi
14+
if [[ "$module_name" == "jmx-metrics" ]]; then
15+
continue
16+
fi
17+
if [[ "$module_name" == "runtime-telemetry" ]]; then
18+
continue
19+
fi
20+
if [[ "$module_name" == "servlet-common" ]]; then
21+
continue
22+
fi
23+
if [[ "$module_name" == "graphql-java-common-12.0" ]]; then
24+
continue
25+
fi
3626

37-
# some common modules don't have any base version (might have a variant instead, ex: javax)
38-
# - jdbc
39-
# - lettuce-common
40-
# - netty-common
41-
# - oshi
42-
# - resources
43-
# - servlet-common-javax
44-
if [[ ! "$module_name" =~ [0-9]$ && "$module_name" != "jdbc" && "$module_name" != "lettuce-common" && "$module_name" != "netty-common" && "$module_name" != "oshi" && "$module_name" != "resources" && "$module_name" != "servlet-common-javax" ]]; then
45-
echo "module name doesn't have a base version: $dir"
46-
exit 1
47-
fi
27+
# these are possibly problematic
28+
if [[ "$source_set" == "library" ]]; then
29+
if [[ "$dir" == "instrumentation/grpc-1.6/library/src/main/java/io/grpc/override" ]]; then
30+
continue
31+
fi
32+
if [[ "$dir" == "instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/lettuce/core/protocol" ]]; then
33+
continue
34+
fi
35+
if [[ "$dir" == "instrumentation/nats/nats-2.17/library/src/main/java/io/nats/client/impl" ]]; then
36+
continue
37+
fi
38+
if [[ "$dir" == "instrumentation/rxjava/rxjava-1.0/library/src/main/java/rx" ]]; then
39+
continue
40+
fi
41+
fi
4842

49-
# convention: if module ends with -java (followed by version), remove -java from the package name
50-
simple_module_name=$(echo "$module_name" | sed 's/-[0-9.]*$//' | sed 's/-java$//' | sed 's/-//g')
51-
base_version=$(echo "$module_name" | sed 's/.*-\([0-9.]*\)$/\1/' | sed 's/\./_/g')
43+
if [[ "$source_set" == "javaagent" ]]; then
44+
# advice packages that must live under the instrumented library's own namespace
45+
case "$dir" in
46+
instrumentation/clickhouse/clickhouse-client-v1-0.5/javaagent/src/main/java/com/clickhouse/client*) continue ;;
47+
instrumentation/finagle-http-23.11/javaagent/src/main/java/com/twitter/finagle*) continue ;;
48+
instrumentation/finagle-http-23.11/javaagent/src/main/java/io/netty/channel*) continue ;;
49+
instrumentation/reactor/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/reactor/netty/http/client*) continue ;;
50+
instrumentation/spring/spring-webmvc/spring-webmvc-3.1/javaagent/src/main/java/org/springframework/web/servlet/v3_1*) continue ;;
51+
instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/main/java/org/springframework/web/servlet/v6_0*) continue ;;
52+
instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/vertx/redis/client/impl*) continue ;;
53+
instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/vertx/sqlclient/impl*) continue ;;
54+
esac
5255

53-
if [[ "$module_name" =~ [0-9]$ ]]; then
54-
expected_package_name="io/opentelemetry/instrumentation/$simple_module_name/v$base_version"
55-
else
56-
expected_package_name="io/opentelemetry/instrumentation/$simple_module_name"
57-
fi
56+
# historical javaagent modules that do not follow the module-name <-> package-name convention
57+
case "$dir" in
58+
instrumentation/akka/akka-actor-fork-join-2.5/javaagent/*) continue ;;
59+
instrumentation/akka/akka-http-10.0/javaagent/*) continue ;;
60+
instrumentation/aws-sdk/aws-sdk-1.11/javaagent/*) continue ;;
61+
instrumentation/aws-sdk/aws-sdk-2.2/javaagent/*) continue ;;
62+
instrumentation/camel-2.20/javaagent/*) continue ;;
63+
instrumentation/clickhouse/clickhouse-client-common/javaagent/*) continue ;;
64+
instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/*) continue ;;
65+
instrumentation/elasticsearch/elasticsearch-rest-common-5.0/javaagent/*) continue ;;
66+
instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/*) continue ;;
67+
instrumentation/external-annotations/javaagent/*) continue ;;
68+
instrumentation/hibernate/hibernate-common/javaagent/*) continue ;;
69+
instrumentation/hibernate/hibernate-procedure-call-4.3/javaagent/*) continue ;;
70+
instrumentation/internal/internal-application-logger/javaagent/*) continue ;;
71+
instrumentation/internal/internal-eclipse-osgi-3.6/javaagent/*) continue ;;
72+
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-annotations/javaagent/*) continue ;;
73+
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/javaagent/*) continue ;;
74+
instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-annotations/javaagent/*) continue ;;
75+
instrumentation/jaxrs/jaxrs-3.0/jaxrs-3.0-common/javaagent/*) continue ;;
76+
instrumentation/jaxrs/jaxrs-common/javaagent/*) continue ;;
77+
instrumentation/jaxws/jaxws-cxf-3.0/javaagent/*) continue ;;
78+
instrumentation/jaxws/jaxws-jws-api-1.1/javaagent/*) continue ;;
79+
instrumentation/jaxws/jaxws-metro-2.2/javaagent/*) continue ;;
80+
instrumentation/jedis/jedis-common/javaagent/*) continue ;;
81+
instrumentation/jms/jms-common/javaagent/*) continue ;;
82+
instrumentation/jsf/jsf-mojarra-1.2/javaagent/*) continue ;;
83+
instrumentation/jsf/jsf-mojarra-3.0/javaagent/*) continue ;;
84+
instrumentation/jsf/jsf-myfaces-1.2/javaagent/*) continue ;;
85+
instrumentation/jsf/jsf-myfaces-3.0/javaagent/*) continue ;;
86+
instrumentation/kotlinx-coroutines/kotlinx-coroutines-1.0/javaagent/*) continue ;;
87+
instrumentation/kotlinx-coroutines/kotlinx-coroutines-flow-1.3/javaagent/*) continue ;;
88+
instrumentation/liberty/liberty-dispatcher-20.0/javaagent/*) continue ;;
89+
instrumentation/opensearch/opensearch-rest-common/javaagent/*) continue ;;
90+
instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/*) continue ;;
91+
instrumentation/opentelemetry-extension-annotations-1.0/javaagent/*) continue ;;
92+
instrumentation/opentelemetry-extension-kotlin-1.0/javaagent/*) continue ;;
93+
instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/*) continue ;;
94+
instrumentation/opentelemetry-instrumentation-api/javaagent/*) continue ;;
95+
instrumentation/play/play-mvc/play-mvc-2.4/javaagent/*) continue ;;
96+
instrumentation/play/play-mvc/play-mvc-2.6/javaagent/*) continue ;;
97+
instrumentation/play/play-ws/play-ws-common/javaagent/*) continue ;;
98+
instrumentation/redisson/redisson-common/javaagent/*) continue ;;
99+
instrumentation/scala-fork-join-2.8/javaagent/*) continue ;;
100+
instrumentation/spark-2.3/javaagent/*) continue ;;
101+
instrumentation/spring/spring-boot-actuator-autoconfigure-2.0/javaagent/*) continue ;;
102+
instrumentation/spring/spring-boot-resources/javaagent/*) continue ;;
103+
instrumentation/spring/spring-cloud-aws-3.0/javaagent/*) continue ;;
104+
instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/*) continue ;;
105+
instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-common/javaagent/*) continue ;;
106+
instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-webmvc-4.3/javaagent/*) continue ;;
107+
instrumentation/spring/spring-webmvc/spring-webmvc-common/javaagent/*) continue ;;
108+
esac
109+
fi
58110

59-
package_name=$(echo "$dir" | sed 's#.*/src/main/java[0-9]*/##')
111+
# some common modules don't have any base version (might have a variant instead, ex: javax)
112+
if [[ ! "$module_name" =~ [0-9]$ ]]; then
113+
case "$source_set:$module_name" in
114+
# library:
115+
library:jdbc) ;;
116+
library:lettuce-common) ;;
117+
library:netty-common) ;;
118+
library:oshi) ;;
119+
library:resources) ;;
120+
library:servlet-common-javax) ;;
121+
# javaagent:
122+
javaagent:clickhouse-client-common) ;;
123+
javaagent:elasticsearch-transport-common) ;;
124+
javaagent:executors) ;;
125+
javaagent:external-annotations) ;;
126+
javaagent:hibernate-common) ;;
127+
javaagent:http-url-connection) ;;
128+
javaagent:internal-application-logger) ;;
129+
javaagent:internal-class-loader) ;;
130+
javaagent:internal-lambda) ;;
131+
javaagent:internal-reflection) ;;
132+
javaagent:internal-url-class-loader) ;;
133+
javaagent:jaxrs-common) ;;
134+
javaagent:jaxws-common) ;;
135+
javaagent:jdbc) ;;
136+
javaagent:jedis-common) ;;
137+
javaagent:jetty-common) ;;
138+
javaagent:jms-common) ;;
139+
javaagent:jsf-common-jakarta) ;;
140+
javaagent:jsf-common-javax) ;;
141+
javaagent:methods) ;;
142+
javaagent:opensearch-rest-common) ;;
143+
javaagent:opentelemetry-instrumentation-api) ;;
144+
javaagent:oshi) ;;
145+
javaagent:payara) ;;
146+
javaagent:play-ws-common) ;;
147+
javaagent:quarkus-resteasy-reactive) ;;
148+
javaagent:redisson-common) ;;
149+
javaagent:rmi) ;;
150+
javaagent:spring-boot-resources) ;;
151+
javaagent:spring-cloud-gateway-common) ;;
152+
javaagent:spring-webmvc-common) ;;
153+
javaagent:tomcat-common) ;;
154+
javaagent:tomcat-jdbc) ;;
155+
javaagent:vertx-http-client-common) ;;
156+
javaagent:vertx-sql-client-common) ;;
157+
javaagent:xxl-job-common) ;;
158+
*)
159+
echo "module name doesn't have a base version: $dir"
160+
exit 1
161+
;;
162+
esac
163+
fi
60164

61-
# deal with differences like module name elasticsearch-rest and package name elasticsearch.rest
62-
expected_package_name_normalized=$(echo "$expected_package_name" | sed 's#/##g')
63-
package_name_normalized=$(echo "$package_name" | sed 's#/##g')
165+
# build expected package name by walking the module name's dash-separated tokens:
166+
# a version token (e.g. "3.0") becomes "/v3_0", any other token becomes "/<token>";
167+
# the literal token "java" is elided (e.g. graphql-java-20.0 -> graphql/v20_0).
168+
# this also handles multi-version modules like jaxrs-2.0-resteasy-3.1 -> jaxrs/v2_0/resteasy/v3_1.
169+
expected_package_name="$expected_prefix"
170+
IFS='-' read -ra module_parts <<< "$module_name"
171+
for part in "${module_parts[@]}"; do
172+
if [[ "$part" == "java" ]]; then
173+
continue
174+
fi
175+
if [[ "$part" =~ ^[0-9][0-9.]*$ ]]; then
176+
expected_package_name="$expected_package_name/v${part//./_}"
177+
else
178+
expected_package_name="$expected_package_name/$part"
179+
fi
180+
done
64181

65-
if [[ "$package_name_normalized" != "$expected_package_name_normalized"* ]]; then
66-
echo "ERROR: $dir"
67-
exit 1
68-
fi
182+
package_name=$(echo "$dir" | sed 's#.*/src/main/java[0-9]*/##')
69183

70-
done
184+
# deal with differences like module name elasticsearch-rest and package name elasticsearch.rest
185+
expected_package_name_normalized=$(echo "$expected_package_name" | sed 's#/##g')
186+
package_name_normalized=$(echo "$package_name" | sed 's#/##g')
187+
188+
if [[ "$package_name_normalized" != "$expected_package_name_normalized"* ]]; then
189+
echo "ERROR: $dir"
190+
exit 1
191+
fi
192+
193+
done
194+
}
195+
196+
check_source_set "library" "io/opentelemetry/instrumentation"
197+
check_source_set "javaagent" "io/opentelemetry/javaagent/instrumentation"

0 commit comments

Comments
 (0)