Skip to content

Commit dec3749

Browse files
committed
Remove unnecessary class loader matchers
1 parent 3d445a9 commit dec3749

File tree

17 files changed

+33
-151
lines changed

17 files changed

+33
-151
lines changed

.github/agents/knowledge/javaagent-module-patterns.md

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,45 @@ public class MyLibrary10InstrumentationModule extends InstrumentationModule {
3939
`Arrays.asList(...)` for multiple items and `Collections.singletonList(...)` for a single
4040
item.
4141

42-
### `classLoaderMatcher()`Version-Boundary Detection
42+
### `classLoaderMatcher()`Multi-Version Library Split
4343

44-
Override `classLoaderMatcher()` only when the instrumentation targets a specific library
45-
version range and muzzle cannot distinguish that range on its own. Typical cases are classes
46-
that were added, removed, renamed, or introduced by a library's own native OpenTelemetry
47-
instrumentation, but are not referenced by the helper classes muzzle inspects.
44+
Override `classLoaderMatcher()` only when **multiple instrumentation versions exist for the
45+
same library** and the module still needs an extra class-presence check to keep one versioned
46+
module from applying where another versioned module should win. If `typeMatcher()` or
47+
`classLoaderOptimization()` already differentiates the versions, do not add
48+
`classLoaderMatcher()`.
49+
50+
Do not add `classLoaderMatcher()` just because muzzle mismatches in cross tests, to avoid
51+
debug logging, or as a generic optimization. In the common case, the type instrumentation
52+
already short-circuits when the library is absent, and muzzle handles wrong-version rejection.
4853

4954
**Execution order**: `classLoaderMatcher()` runs **first** and should be very cheap. It is
5055
followed by `typeMatcher()`, then muzzle. Use `classLoaderMatcher()` to reject obvious
51-
non-matches before the more expensive checks run.
56+
non-matches only when a versioned sibling module would otherwise overlap.
5257

5358
**Override it when**:
5459

55-
- A landmark class was **added** in the target version and excludes older versions.
56-
- A landmark class was **removed** in a newer version and excludes newer versions.
57-
- A newer version ships **native OpenTelemetry instrumentation** and the agent should back off.
60+
- There are **multiple instrumentation modules for one library** and a landmark class is needed
61+
to separate their supported version ranges.
62+
- A landmark class was **added** in the target version and excludes older sibling modules.
63+
- A landmark class was **removed** in a newer version and excludes newer sibling modules.
64+
- A newer version ships **native OpenTelemetry instrumentation** and the older module should
65+
back off.
5866

5967
**Do not override it for**:
6068

69+
- Single-version libraries with no competing instrumentation module.
70+
- Cross-test-driven preconditions whose only purpose is to avoid muzzle mismatches.
71+
- Library-absent fast paths that `typeMatcher()` or `classLoaderOptimization()` already cover.
6172
- Method signature changes.
6273
- Parameter type changes.
6374
- Field removals.
6475
- Package relocations that muzzle already sees.
6576

6677
#### Pattern A: Single Landmark Class
6778

68-
This is the most common case: one class cleanly identifies the lower bound.
79+
This is the most common valid case: one class cleanly identifies which sibling versioned
80+
module should handle the library.
6981

7082
```java
7183
@Override
@@ -176,8 +188,8 @@ the 3.7 module from activating on 4.0+ classloaders. That is why the comment mus
176188

177189
#### Pattern C: Exclude Newer Versions with Native Instrumentation
178190

179-
Use `.and(not(hasClassesNamed(...)))` when the newer library version ships its own
180-
OpenTelemetry instrumentation and the agent should opt out.
191+
Use `.and(not(hasClassesNamed(...)))` when a newer sibling version ships its own
192+
OpenTelemetry instrumentation and the older module should opt out.
181193

182194
```java
183195
@Override
@@ -204,13 +216,16 @@ public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
204216

205217
#### Rules for `classLoaderMatcher()`
206218

207-
- **Do NOT add `classLoaderMatcher()` for optimization.** The "skip when library is absent"
208-
optimization belongs on `TypeInstrumentation.classLoaderOptimization()`, not here.
209-
`classLoaderMatcher()` is only for **version-boundary detection**. Most modules do not need
210-
it.
219+
- **Do NOT add `classLoaderMatcher()` for optimization or to silence muzzle mismatches.** The
220+
"skip when library is absent" optimization belongs on
221+
`TypeInstrumentation.classLoaderOptimization()`, not here. `classLoaderMatcher()` is only for
222+
separating **multiple instrumentation versions of the same library** when the type
223+
instrumentation does not already do that. Most modules do not need it.
211224
- **Do NOT flag modules that omit `classLoaderMatcher()`.** The default (`any()`) is correct
212-
when muzzle can detect the version boundary on its own. Only flag a missing override when
213-
the module truly depends on an added or removed landmark class that muzzle does not inspect.
225+
when there is no competing sibling module, or when `typeMatcher()`,
226+
`classLoaderOptimization()`, or muzzle already separates the versions. Only flag a missing
227+
override when sibling versioned modules would otherwise overlap and the module truly depends
228+
on an added or removed landmark class that the other checks do not inspect.
214229
- **Version comments are required on landmark classes.** For multi-class checks, or whenever
215230
the landmark version differs from the module's base version, every `hasClassesNamed()` call
216231
needs a role comment. When the entire return expression is a single `hasClassesNamed(...)`

instrumentation/activej-http-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/activejhttp/ActivejHttpServerInstrumentationModule.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55

66
package io.opentelemetry.javaagent.instrumentation.activejhttp;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Collections.singletonList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1312
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1413
import java.util.List;
15-
import net.bytebuddy.matcher.ElementMatcher;
1614

1715
@AutoService(InstrumentationModule.class)
1816
public class ActivejHttpServerInstrumentationModule extends InstrumentationModule {
@@ -25,10 +23,4 @@ public ActivejHttpServerInstrumentationModule() {
2523
public List<TypeInstrumentation> typeInstrumentations() {
2624
return singletonList(new ActivejAsyncServletInstrumentation());
2725
}
28-
29-
@Override
30-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
31-
// added in 6.0
32-
return hasClassesNamed("io.activej.http.HttpServer");
33-
}
3426
}

instrumentation/armeria/armeria-1.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/armeria/v1_3/ArmeriaInstrumentationModule.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,19 @@
55

66
package io.opentelemetry.javaagent.instrumentation.armeria.v1_3;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Arrays.asList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1312
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1413
import java.util.List;
15-
import net.bytebuddy.matcher.ElementMatcher;
1614

1715
@AutoService(InstrumentationModule.class)
1816
public class ArmeriaInstrumentationModule extends InstrumentationModule {
1917
public ArmeriaInstrumentationModule() {
2018
super("armeria", "armeria-1.3");
2119
}
2220

23-
@Override
24-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
25-
// Unrelated class which was added in Armeria 1.3.0, the minimum version we support.
26-
return hasClassesNamed("com.linecorp.armeria.server.metric.PrometheusExpositionServiceBuilder");
27-
}
28-
2921
@Override
3022
public List<TypeInstrumentation> typeInstrumentations() {
3123
return asList(

instrumentation/clickhouse/clickhouse-client-v1-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/clientv1/v0_5/ClickHouseClientV1InstrumentationModule.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@
55

66
package io.opentelemetry.javaagent.instrumentation.clickhouse.clientv1.v0_5;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Collections.singletonList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1312
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1413
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1514
import java.util.List;
16-
import net.bytebuddy.matcher.ElementMatcher;
1715

1816
@AutoService(InstrumentationModule.class)
1917
public class ClickHouseClientV1InstrumentationModule extends InstrumentationModule
@@ -28,12 +26,6 @@ public boolean isHelperClass(String className) {
2826
return "com.clickhouse.client.ClickHouseRequestAccess".equals(className);
2927
}
3028

31-
@Override
32-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
33-
// Unrelated class which was added in 0.5.0, the minimum version where tests pass
34-
return hasClassesNamed("com.clickhouse.client.config.ClickHouseProxyType");
35-
}
36-
3729
@Override
3830
public List<String> injectedClassNames() {
3931
return singletonList("com.clickhouse.client.ClickHouseRequestAccess");

instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsInstrumentationModule.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55

66
package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Arrays.asList;
10-
import static net.bytebuddy.matcher.ElementMatchers.not;
119

1210
import com.google.auto.service.AutoService;
1311
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1412
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1513
import java.util.List;
16-
import net.bytebuddy.matcher.ElementMatcher;
1714

1815
@AutoService(InstrumentationModule.class)
1916
public class DropwizardMetricsInstrumentationModule extends InstrumentationModule {
@@ -22,12 +19,6 @@ public DropwizardMetricsInstrumentationModule() {
2219
super("dropwizard-metrics", "dropwizard-metrics-4.0");
2320
}
2421

25-
@Override
26-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
27-
// removed in 4.0
28-
return not(hasClassesNamed("com.codahale.metrics.LongAdder"));
29-
}
30-
3122
@Override
3223
public boolean defaultEnabled() {
3324
// the Dropwizard metrics API does not have a concept of metric labels/tags/attributes, thus the

instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,19 @@
55

66
package io.opentelemetry.javaagent.instrumentation.grizzly;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Arrays.asList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1312
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1413
import java.util.List;
15-
import net.bytebuddy.matcher.ElementMatcher;
1614

1715
@AutoService(InstrumentationModule.class)
1816
public class GrizzlyInstrumentationModule extends InstrumentationModule {
1917
public GrizzlyInstrumentationModule() {
2018
super("grizzly", "grizzly-2.3");
2119
}
2220

23-
@Override
24-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
25-
// class added in 2.3
26-
return hasClassesNamed("org.glassfish.grizzly.InputSource");
27-
}
28-
2921
@Override
3022
public List<TypeInstrumentation> typeInstrumentations() {
3123
return asList(

instrumentation/gwt-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/gwt/GwtInstrumentationModule.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55

66
package io.opentelemetry.javaagent.instrumentation.gwt;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Collections.singletonList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1312
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1413
import java.util.List;
15-
import net.bytebuddy.matcher.ElementMatcher;
1614

1715
@AutoService(InstrumentationModule.class)
1816
public class GwtInstrumentationModule extends InstrumentationModule {
@@ -21,12 +19,6 @@ public GwtInstrumentationModule() {
2119
super("gwt", "gwt-2.0");
2220
}
2321

24-
@Override
25-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
26-
// added in 2.0
27-
return hasClassesNamed("com.google.gwt.uibinder.client.UiBinder");
28-
}
29-
3022
@Override
3123
public List<TypeInstrumentation> typeInstrumentations() {
3224
return singletonList(new GwtRpcInstrumentation());

instrumentation/jfinal-3.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jfinal/v3_2/JFinalInstrumentationModule.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55

66
package io.opentelemetry.javaagent.instrumentation.jfinal.v3_2;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Arrays.asList;
10-
import static net.bytebuddy.matcher.ElementMatchers.not;
119

1210
import com.google.auto.service.AutoService;
1311
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1412
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1513
import java.util.List;
16-
import net.bytebuddy.matcher.ElementMatcher;
1714

1815
@AutoService(InstrumentationModule.class)
1916
public class JFinalInstrumentationModule extends InstrumentationModule {
@@ -22,13 +19,6 @@ public JFinalInstrumentationModule() {
2219
super("jfinal", "jfinal-3.2");
2320
}
2421

25-
@Override
26-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
27-
// In version 3.2, TypeConverter is moved from com.jfinal.core
28-
// to com.jfinal.core.converter
29-
return not(hasClassesNamed("com.jfinal.core.TypeConverter"));
30-
}
31-
3222
@Override
3323
public List<TypeInstrumentation> typeInstrumentations() {
3424
return asList(new ActionMappingInstrumentation(), new InvocationInstrumentation());

instrumentation/kafka/kafka-connect-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaconnect/v2_6/KafkaConnectInstrumentationModule.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55

66
package io.opentelemetry.javaagent.instrumentation.kafkaconnect.v2_6;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Arrays.asList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1312
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1413
import java.util.List;
15-
import net.bytebuddy.matcher.ElementMatcher;
1614

1715
@AutoService(InstrumentationModule.class)
1816
public class KafkaConnectInstrumentationModule extends InstrumentationModule {
@@ -25,10 +23,4 @@ public KafkaConnectInstrumentationModule() {
2523
public List<TypeInstrumentation> typeInstrumentations() {
2624
return asList(new SinkTaskInstrumentation(), new WorkerSinkTaskInstrumentation());
2725
}
28-
29-
@Override
30-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
31-
// class added in 2.6.0
32-
return hasClassesNamed("org.apache.kafka.connect.sink.SinkConnectorContext");
33-
}
3426
}

instrumentation/log4j/log4j-mdc-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/Log4j1InstrumentationModule.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,19 @@
55

66
package io.opentelemetry.javaagent.instrumentation.log4j.mdc.v1_2;
77

8-
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
98
import static java.util.Arrays.asList;
109

1110
import com.google.auto.service.AutoService;
1211
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1312
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1413
import java.util.List;
15-
import net.bytebuddy.matcher.ElementMatcher;
1614

1715
@AutoService(InstrumentationModule.class)
1816
public class Log4j1InstrumentationModule extends InstrumentationModule {
1917
public Log4j1InstrumentationModule() {
2018
super("log4j-mdc", "log4j-mdc-1.2");
2119
}
2220

23-
@Override
24-
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
25-
// added in 1.2
26-
return hasClassesNamed("org.apache.log4j.MDC");
27-
}
28-
2921
@Override
3022
public List<TypeInstrumentation> typeInstrumentations() {
3123
return asList(new CategoryInstrumentation(), new LoggingEventInstrumentation());

0 commit comments

Comments
 (0)