Skip to content

Commit 664b9a4

Browse files
authored
Protect exception advices from NoClassDefFound (#9769)
* Protect exception advices from NoClassDefFound * review
1 parent 1a32bbb commit 664b9a4

File tree

1 file changed

+73
-34
lines changed
  • dd-java-agent/agent-bootstrap/src/main/java11/datadog/trace/bootstrap/instrumentation/jfr/exceptions

1 file changed

+73
-34
lines changed

dd-java-agent/agent-bootstrap/src/main/java11/datadog/trace/bootstrap/instrumentation/jfr/exceptions/ExceptionProfiling.java

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,41 @@
22

33
import datadog.trace.api.Config;
44
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
57

68
/**
79
* JVM-wide singleton exception profiling service. Uses {@linkplain Config} class to configure
810
* itself using either system properties, environment or properties override.
911
*/
10-
public final class ExceptionProfiling {
12+
public interface ExceptionProfiling {
13+
14+
void start();
15+
16+
ExceptionSampleEvent process(final Throwable t);
17+
18+
boolean recordExceptionMessage();
1119

1220
/** Lazy initialization-on-demand. */
13-
private static final class Holder {
14-
static final ExceptionProfiling INSTANCE = new ExceptionProfiling(Config.get());
21+
final class Holder {
22+
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionProfiling.class);
23+
static final ExceptionProfiling INSTANCE = create();
24+
25+
private static ExceptionProfiling create() {
26+
try {
27+
return new ExceptionProfilingImpl(Config.get());
28+
} catch (Throwable t) {
29+
LOGGER.debug("Unable to create ExceptionProfiling", t);
30+
return new NoOpExceptionProfiling();
31+
}
32+
}
1533
}
1634

1735
/**
1836
* Support for excluding certain exception types because they are used for control flow or leak
1937
* detection.
2038
*/
21-
public static final class Exclusion {
39+
final class Exclusion {
2240
public static void enter() {
2341
CallDepthThreadLocalMap.incrementCallDepth(Exclusion.class);
2442
}
@@ -37,46 +55,67 @@ public static boolean isEffective() {
3755
*
3856
* @return the shared instance
3957
*/
40-
public static ExceptionProfiling getInstance() {
58+
static ExceptionProfiling getInstance() {
4159
return Holder.INSTANCE;
4260
}
4361

44-
private final ExceptionHistogram histogram;
45-
private final ExceptionSampler sampler;
46-
private final boolean recordExceptionMessage;
62+
final class NoOpExceptionProfiling implements ExceptionProfiling {
63+
@Override
64+
public void start() {}
4765

48-
private ExceptionProfiling(final Config config) {
49-
this(
50-
new ExceptionSampler(config),
51-
new ExceptionHistogram(config),
52-
config.isProfilingRecordExceptionMessage());
53-
}
66+
@Override
67+
public ExceptionSampleEvent process(Throwable t) {
68+
return null;
69+
}
5470

55-
ExceptionProfiling(
56-
final ExceptionSampler sampler,
57-
final ExceptionHistogram histogram,
58-
boolean recordExceptionMessage) {
59-
this.sampler = sampler;
60-
this.histogram = histogram;
61-
this.recordExceptionMessage = recordExceptionMessage;
71+
@Override
72+
public boolean recordExceptionMessage() {
73+
return false;
74+
}
6275
}
6376

64-
public void start() {
65-
sampler.start();
66-
}
77+
final class ExceptionProfilingImpl implements ExceptionProfiling {
6778

68-
public ExceptionSampleEvent process(final Throwable t) {
69-
// always record the exception in histogram
70-
final boolean firstHit = histogram.record(t);
79+
private final ExceptionHistogram histogram;
80+
private final ExceptionSampler sampler;
81+
private final boolean recordExceptionMessage;
7182

72-
final boolean sampled = sampler.sample();
73-
if (firstHit || sampled) {
74-
return new ExceptionSampleEvent(t, sampled, firstHit);
83+
ExceptionProfilingImpl(final Config config) {
84+
this(
85+
new ExceptionSampler(config),
86+
new ExceptionHistogram(config),
87+
config.isProfilingRecordExceptionMessage());
88+
}
89+
90+
ExceptionProfilingImpl(
91+
final ExceptionSampler sampler,
92+
final ExceptionHistogram histogram,
93+
boolean recordExceptionMessage) {
94+
this.sampler = sampler;
95+
this.histogram = histogram;
96+
this.recordExceptionMessage = recordExceptionMessage;
97+
}
98+
99+
@Override
100+
public void start() {
101+
sampler.start();
75102
}
76-
return null;
77-
}
78103

79-
boolean recordExceptionMessage() {
80-
return recordExceptionMessage;
104+
@Override
105+
public ExceptionSampleEvent process(final Throwable t) {
106+
// always record the exception in histogram
107+
final boolean firstHit = histogram.record(t);
108+
109+
final boolean sampled = sampler.sample();
110+
if (firstHit || sampled) {
111+
return new ExceptionSampleEvent(t, sampled, firstHit);
112+
}
113+
return null;
114+
}
115+
116+
@Override
117+
public boolean recordExceptionMessage() {
118+
return recordExceptionMessage;
119+
}
81120
}
82121
}

0 commit comments

Comments
 (0)