Skip to content

Commit c8bb444

Browse files
authored
Use ClassNameFilter to track uninteresting classes (#9976)
* Replace IsPublicFilter with ClassNameFilter * Replace NoMatchFilter with ClassNameFilter * Remove now unused ClassCodeFilter * Document that NoMatchFilter is now a utility class * Catch potential security exception when checking file / installing shutdown hook
1 parent c79dfc6 commit c8bb444

File tree

5 files changed

+68
-151
lines changed

5 files changed

+68
-151
lines changed

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/ClassCodeFilter.java

Lines changed: 0 additions & 85 deletions
This file was deleted.

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/memoize/Memoizer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static net.bytebuddy.matcher.ElementMatchers.not;
44

5+
import datadog.instrument.utils.ClassNameFilter;
56
import datadog.trace.agent.tooling.InstrumenterMetrics;
67
import datadog.trace.agent.tooling.bytebuddy.TypeInfoCache;
78
import datadog.trace.agent.tooling.bytebuddy.TypeInfoCache.SharedTypeInfo;
@@ -61,7 +62,7 @@ enum MatcherKind {
6162
private static final boolean namesAreUnique = InstrumenterConfig.get().isResolverNamesAreUnique();
6263

6364
// compact filter recording uninteresting types
64-
private static final NoMatchFilter noMatchFilter = new NoMatchFilter();
65+
private static final ClassNameFilter noMatchFilter = NoMatchFilter.build();
6566

6667
// caches positive memoized matches
6768
private static final TypeInfoCache<BitSet> memos =

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/memoize/NoMatchFilter.java

Lines changed: 63 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import static datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP;
44

5-
import datadog.trace.agent.tooling.bytebuddy.ClassCodeFilter;
5+
import datadog.instrument.utils.ClassNameFilter;
66
import datadog.trace.api.Config;
77
import datadog.trace.api.DDTraceApiInfo;
88
import datadog.trace.api.InstrumenterConfig;
@@ -19,21 +19,37 @@
1919
import org.slf4j.Logger;
2020
import org.slf4j.LoggerFactory;
2121

22-
/** Compact filter that records uninteresting types. */
23-
final class NoMatchFilter extends ClassCodeFilter {
22+
/** Builds a persistable compact filter that records uninteresting types. */
23+
final class NoMatchFilter {
2424
private static final Logger log = LoggerFactory.getLogger(NoMatchFilter.class);
2525

26-
NoMatchFilter() {
27-
super(InstrumenterConfig.get().getResolverNoMatchesSize());
26+
private static final String TRACER_VERSION_HEADER = "dd-java-agent";
27+
private static final String NO_MATCH_FILTER_HEADER = "NoMatchFilter";
2828

29-
// seed filter from previously collected results?
29+
private NoMatchFilter() {}
30+
31+
public static ClassNameFilter build() {
3032
Path noMatchFile = discoverNoMatchFile();
3133
if (null != noMatchFile) {
32-
seedNoMatchFilter(noMatchFile);
34+
// support persisting/restoring no-match results
35+
try {
36+
if (Files.exists(noMatchFile)) {
37+
// restore existing filter with previously collected results
38+
return seedNoMatchFilter(noMatchFile);
39+
} else {
40+
// populate filter from current run and persist at shutdown
41+
ClassNameFilter filter = emptyNoMatchFilter();
42+
Runtime.getRuntime().addShutdownHook(new ShutdownHook(noMatchFile, filter));
43+
return filter;
44+
}
45+
} catch (Throwable e) {
46+
log.debug("Unable to use NoMatchFilter at {}", noMatchFile, e);
47+
}
3348
}
49+
return emptyNoMatchFilter();
3450
}
3551

36-
static Path discoverNoMatchFile() {
52+
private static Path discoverNoMatchFile() {
3753
String cacheDir = InstrumenterConfig.get().getResolverCacheDir();
3854
if (null == cacheDir) {
3955
return null;
@@ -53,51 +69,49 @@ static Path discoverNoMatchFile() {
5369
return Paths.get(cacheDir, noMatchFilterName);
5470
}
5571

56-
void seedNoMatchFilter(Path noMatchFile) {
57-
if (!Files.exists(noMatchFile)) {
58-
Runtime.getRuntime().addShutdownHook(new ShutdownHook(noMatchFile));
59-
} else {
60-
log.debug("Seeding NoMatchFilter from {}", noMatchFile);
61-
try (DataInputStream in =
62-
new DataInputStream(new BufferedInputStream(Files.newInputStream(noMatchFile)))) {
63-
while (true) {
64-
switch (in.readUTF()) {
65-
case "dd-java-agent":
66-
expectVersion(in, DDTraceApiInfo.VERSION);
67-
break;
68-
case "NoMatchFilter":
69-
if (in.readInt() != slots.length) {
70-
throw new IOException("filter size mismatch");
71-
}
72-
for (int i = 0; i < slots.length; i++) {
73-
slots[i] = in.readLong();
74-
}
75-
return;
76-
default:
77-
throw new IOException("unexpected content");
78-
}
79-
}
80-
} catch (IOException e) {
81-
if (log.isDebugEnabled()) {
82-
log.info("Unable to seed NoMatchFilter from {}", noMatchFile, e);
83-
} else {
84-
log.info("Unable to seed NoMatchFilter from {}: {}", noMatchFile, e.getMessage());
72+
private static ClassNameFilter emptyNoMatchFilter() {
73+
return new ClassNameFilter(InstrumenterConfig.get().getResolverNoMatchesSize());
74+
}
75+
76+
private static ClassNameFilter seedNoMatchFilter(Path noMatchFile) {
77+
log.debug("Seeding NoMatchFilter from {}", noMatchFile);
78+
try (DataInputStream in =
79+
new DataInputStream(new BufferedInputStream(Files.newInputStream(noMatchFile)))) {
80+
while (true) {
81+
switch (in.readUTF()) {
82+
case TRACER_VERSION_HEADER:
83+
expectVersion(in, DDTraceApiInfo.VERSION);
84+
break;
85+
case NO_MATCH_FILTER_HEADER:
86+
return ClassNameFilter.readFrom(in);
87+
default:
88+
throw new IOException("unexpected content");
8589
}
8690
}
91+
} catch (Throwable e) {
92+
if (log.isDebugEnabled()) {
93+
log.info("Unable to seed NoMatchFilter from {}", noMatchFile, e);
94+
} else {
95+
log.info("Unable to seed NoMatchFilter from {}: {}", noMatchFile, e.getMessage());
96+
}
97+
return emptyNoMatchFilter();
8798
}
8899
}
89100

90-
void persistNoMatchFilter(Path noMatchFile) {
101+
private static void expectVersion(DataInputStream in, String version) throws IOException {
102+
if (!version.equals(in.readUTF())) {
103+
throw new IOException("version mismatch");
104+
}
105+
}
106+
107+
static void persistNoMatchFilter(Path noMatchFile, ClassNameFilter filter) {
91108
log.debug("Persisting NoMatchFilter to {}", noMatchFile);
92109
try (DataOutputStream out =
93110
new DataOutputStream(new BufferedOutputStream(Files.newOutputStream(noMatchFile)))) {
94-
out.writeUTF("dd-java-agent");
111+
out.writeUTF(TRACER_VERSION_HEADER);
95112
out.writeUTF(DDTraceApiInfo.VERSION);
96-
out.writeUTF("NoMatchFilter");
97-
out.writeInt(slots.length);
98-
for (long slot : slots) {
99-
out.writeLong(slot);
100-
}
113+
out.writeUTF(NO_MATCH_FILTER_HEADER);
114+
filter.writeTo(out);
101115
} catch (IOException e) {
102116
if (log.isDebugEnabled()) {
103117
log.info("Unable to persist NoMatchFilter to {}", noMatchFile, e);
@@ -107,23 +121,19 @@ void persistNoMatchFilter(Path noMatchFile) {
107121
}
108122
}
109123

110-
static void expectVersion(DataInputStream in, String version) throws IOException {
111-
if (!version.equals(in.readUTF())) {
112-
throw new IOException("version mismatch");
113-
}
114-
}
115-
116-
class ShutdownHook extends Thread {
124+
private static final class ShutdownHook extends Thread {
117125
private final Path noMatchFile;
126+
private final ClassNameFilter filter;
118127

119-
ShutdownHook(Path noMatchFile) {
128+
ShutdownHook(Path noMatchFile, ClassNameFilter filter) {
120129
super(AGENT_THREAD_GROUP, "dd-NoMatchFilter-persist-hook");
121130
this.noMatchFile = noMatchFile;
131+
this.filter = filter;
122132
}
123133

124134
@Override
125135
public void run() {
126-
persistNoMatchFilter(noMatchFile);
136+
persistNoMatchFilter(noMatchFile, filter);
127137
}
128138
}
129139
}

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/IsPublicFilter.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/outline/TypeFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static datadog.trace.bootstrap.AgentClassLoading.LOCATING_CLASS;
66
import static net.bytebuddy.dynamic.loading.ClassLoadingStrategy.BOOTSTRAP_LOADER;
77

8+
import datadog.instrument.utils.ClassNameFilter;
89
import datadog.trace.agent.tooling.InstrumenterMetrics;
910
import datadog.trace.agent.tooling.bytebuddy.ClassFileLocators;
1011
import datadog.trace.agent.tooling.bytebuddy.TypeInfoCache;
@@ -86,7 +87,8 @@ final class TypeFactory {
8687
private static final TypeInfoCache<TypeDescription> fullTypes =
8788
new TypeInfoCache<>(InstrumenterConfig.get().getResolverTypePoolSize());
8889

89-
static final IsPublicFilter isPublicFilter = new IsPublicFilter();
90+
static final ClassNameFilter isPublicFilter =
91+
new ClassNameFilter(InstrumenterConfig.get().getResolverVisibilitySize());
9092

9193
/** Small local cache to help deduplicate lookups when matching/transforming. */
9294
private final DDCache<String, LazyType> deferredTypes = DDCaches.newFixedSizeCache(16);

0 commit comments

Comments
 (0)