-
Notifications
You must be signed in to change notification settings - Fork 0
/
MuzzleMatcher.java
111 lines (99 loc) · 4.11 KB
/
MuzzleMatcher.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.tooling.instrumentation;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.WARNING;
import static net.bytebuddy.dynamic.loading.ClassLoadingStrategy.BOOTSTRAP_LOADER;
import io.opentelemetry.instrumentation.api.internal.cache.Cache;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.tooling.TransformSafeLogger;
import io.opentelemetry.javaagent.tooling.Utils;
import io.opentelemetry.javaagent.tooling.config.AgentConfig;
import io.opentelemetry.javaagent.tooling.muzzle.Mismatch;
import io.opentelemetry.javaagent.tooling.muzzle.ReferenceMatcher;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.security.ProtectionDomain;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.utility.JavaModule;
/**
* A ByteBuddy matcher that decides whether this instrumentation should be applied. Calls generated
* {@link ReferenceMatcher}: if any mismatch with the passed {@code classLoader} is found this
* instrumentation is skipped.
*/
class MuzzleMatcher implements AgentBuilder.RawMatcher {
private static final Logger muzzleLogger = Logger.getLogger(MuzzleMatcher.class.getName());
private final TransformSafeLogger instrumentationLogger;
private final InstrumentationModule instrumentationModule;
private final Level muzzleLogLevel;
private final AtomicBoolean initialized = new AtomicBoolean(false);
private final Cache<ClassLoader, Boolean> matchCache = Cache.weak();
private volatile ReferenceMatcher referenceMatcher;
MuzzleMatcher(
TransformSafeLogger instrumentationLogger,
InstrumentationModule instrumentationModule,
ConfigProperties config) {
this.instrumentationLogger = instrumentationLogger;
this.instrumentationModule = instrumentationModule;
this.muzzleLogLevel = AgentConfig.isDebugModeEnabled(config) ? WARNING : FINE;
}
@Override
public boolean matches(
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain) {
if (classLoader == BOOTSTRAP_LOADER) {
classLoader = Utils.getBootstrapProxy();
}
return matchCache.computeIfAbsent(classLoader, this::doesMatch);
}
private boolean doesMatch(ClassLoader classLoader) {
ReferenceMatcher muzzle = getReferenceMatcher();
boolean isMatch = muzzle.matches(classLoader);
if (!isMatch) {
MuzzleFailureCounter.inc();
if (muzzleLogger.isLoggable(muzzleLogLevel)) {
muzzleLogger.log(
muzzleLogLevel,
"Instrumentation skipped, mismatched references were found: {0} [class {1}] on {2}",
new Object[] {
instrumentationModule.instrumentationName(),
instrumentationModule.getClass().getName(),
classLoader
});
List<Mismatch> mismatches = muzzle.getMismatchedReferenceSources(classLoader);
for (Mismatch mismatch : mismatches) {
muzzleLogger.log(muzzleLogLevel, "-- {0}", mismatch);
}
}
} else {
if (instrumentationLogger.isLoggable(FINE)) {
instrumentationLogger.log(
FINE,
"Applying instrumentation: {0} [class {1}] on {2}",
new Object[] {
instrumentationModule.instrumentationName(),
instrumentationModule.getClass().getName(),
classLoader
});
}
}
return isMatch;
}
// ReferenceMatcher is lazily created to avoid unnecessarily loading the muzzle references from
// the module during the agent setup
private ReferenceMatcher getReferenceMatcher() {
if (initialized.compareAndSet(false, true)) {
referenceMatcher = ReferenceMatcher.of(instrumentationModule);
}
return referenceMatcher;
}
}