44
55import com .datadog .debugger .util .ClassNameFiltering ;
66import java .security .MessageDigest ;
7+ import java .security .NoSuchAlgorithmException ;
78import org .slf4j .Logger ;
89import org .slf4j .LoggerFactory ;
910
1011/** Computes a fingerprint of an exception based on its stacktrace and exception type. */
1112public class Fingerprinter {
1213 private static final Logger LOGGER = LoggerFactory .getLogger (Fingerprinter .class );
13- private static MessageDigest digest ;
14-
15- static {
16- try {
17- digest = MessageDigest .getInstance ("SHA-256" );
18- } catch (Throwable e ) {
19- LOGGER .debug ("Unable to find digest algorithm SHA-256" , e );
20- }
21- }
2214
2315 // compute fingerprint of the Throwable based on the stacktrace and exception type
2416 public static String fingerprint (Throwable t , ClassNameFiltering classNameFiltering ) {
25- if (digest == null ) {
26- return null ;
27- }
2817 t = getInnerMostThrowable (t );
2918 if (t == null ) {
3019 LOGGER .debug ("Unable to find root cause of exception" );
3120 return null ;
3221 }
3322 Class <? extends Throwable > clazz = t .getClass ();
23+ MessageDigest digest ;
24+ try {
25+ // need to create a new instance each time to make it thread safe
26+ // Regarding performance, see the results of micro-benchmarks at the end of the file
27+ digest = MessageDigest .getInstance ("SHA-256" );
28+ } catch (NoSuchAlgorithmException e ) {
29+ LOGGER .debug ("Unable to find digest algorithm SHA-256" , e );
30+ return null ;
31+ }
3432 String typeName = clazz .getTypeName ();
3533 digest .update (typeName .getBytes ());
3634 StackTraceElement [] stackTrace = t .getStackTrace ();
@@ -45,11 +43,14 @@ public static String fingerprint(Throwable t, ClassNameFiltering classNameFilter
4543 }
4644
4745 public static String fingerprint (StackTraceElement element ) {
48- if (digest == null ) {
46+ try {
47+ MessageDigest digest = MessageDigest .getInstance ("SHA-256" );
48+ digest .update (element .toString ().getBytes ());
49+ return bytesToHex (digest .digest ());
50+ } catch (NoSuchAlgorithmException e ) {
51+ LOGGER .debug ("Unable to find digest algorithm SHA-256" , e );
4952 return null ;
5053 }
51- digest .update (element .toString ().getBytes ());
52- return bytesToHex (digest .digest ());
5354 }
5455
5556 // convert byte[] to hex string
@@ -61,3 +62,85 @@ private static String bytesToHex(byte[] bytes) {
6162 return result .toString ();
6263 }
6364}
65+
66+ /*
67+ Micro benchmark results:
68+ jdk8 arm64:
69+ Benchmark Mode Cnt Score Error Units
70+ MessageDigestBenchmark.md5NewInstance avgt 5 4.974 ± 0.069 us/op
71+ MessageDigestBenchmark.md5ReuseInstance avgt 5 4.787 ± 0.137 us/op
72+ MessageDigestBenchmark.sha1NewInstance avgt 5 6.131 ± 0.038 us/op
73+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 6.088 ± 0.016 us/op
74+ MessageDigestBenchmark.sha256NewInstance avgt 5 7.090 ± 0.091 us/op
75+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 7.048 ± 0.132 us/op
76+
77+ jdk11 arm64:
78+ Benchmark Mode Cnt Score Error Units
79+ MessageDigestBenchmark.md5NewInstance avgt 5 5.258 ± 0.166 us/op
80+ MessageDigestBenchmark.md5ReuseInstance avgt 5 5.196 ± 0.053 us/op
81+ MessageDigestBenchmark.sha1NewInstance avgt 5 6.639 ± 0.136 us/op
82+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 6.522 ± 0.096 us/op
83+ MessageDigestBenchmark.sha256NewInstance avgt 5 7.600 ± 0.130 us/op
84+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 7.605 ± 0.115 us/op
85+
86+ jdk17 arm64:
87+ Benchmark Mode Cnt Score Error Units
88+ MessageDigestBenchmark.md5NewInstance avgt 5 3.749 ± 0.054 us/op
89+ MessageDigestBenchmark.md5ReuseInstance avgt 5 3.713 ± 0.061 us/op
90+ MessageDigestBenchmark.sha1NewInstance avgt 5 5.708 ± 0.079 us/op
91+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 5.646 ± 0.070 us/op
92+ MessageDigestBenchmark.sha256NewInstance avgt 5 8.668 ± 0.073 us/op
93+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 8.651 ± 0.131 us/op
94+
95+ jdk21 arm64:
96+ Benchmark Mode Cnt Score Error Units
97+ MessageDigestBenchmark.md5NewInstance avgt 5 2.702 ± 0.023 us/op
98+ MessageDigestBenchmark.md5ReuseInstance avgt 5 2.675 ± 0.018 us/op
99+ MessageDigestBenchmark.sha1NewInstance avgt 5 0.818 ± 0.005 us/op
100+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 0.798 ± 0.035 us/op
101+ MessageDigestBenchmark.sha256NewInstance avgt 5 0.814 ± 0.018 us/op
102+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 0.792 ± 0.017 us/op
103+
104+ jdk21 arm64 -XX:+UnlockDiagnosticVMOptions -XX:-UseSHA1Intrinsics -XX:-UseSHA256Intrinsics
105+ Benchmark Mode Cnt Score Error Units
106+ MessageDigestBenchmark.sha1NewInstance avgt 5 5.030 ± 0.041 us/op
107+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 5.121 ± 0.090 us/op
108+ MessageDigestBenchmark.sha256NewInstance avgt 5 7.677 ± 0.089 us/op
109+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 7.627 ± 0.065 us/op
110+
111+ jdk8 x86_64:
112+ Benchmark Mode Cnt Score Error Units
113+ MessageDigestBenchmark.md5NewInstance avgt 5 4.435 ± 0.166 us/op
114+ MessageDigestBenchmark.md5ReuseInstance avgt 5 4.364 ± 0.206 us/op
115+ MessageDigestBenchmark.sha1NewInstance avgt 5 5.966 ± 0.224 us/op
116+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 5.901 ± 0.349 us/op
117+ MessageDigestBenchmark.sha256NewInstance avgt 5 9.220 ± 0.667 us/op
118+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 9.162 ± 0.860 us/op
119+
120+ jdk11 x86_64:
121+ Benchmark Mode Cnt Score Error Units
122+ MessageDigestBenchmark.md5NewInstance avgt 5 4.716 ± 0.233 us/op
123+ MessageDigestBenchmark.md5ReuseInstance avgt 5 4.662 ± 0.258 us/op
124+ MessageDigestBenchmark.sha1NewInstance avgt 5 1.444 ± 0.066 us/op
125+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 1.396 ± 0.060 us/op
126+ MessageDigestBenchmark.sha256NewInstance avgt 5 1.533 ± 0.054 us/op
127+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 1.494 ± 0.052 us/op
128+
129+ jdk17 x86_64:
130+ Benchmark Mode Cnt Score Error Units
131+ MessageDigestBenchmark.md5NewInstance avgt 5 2.852 ± 0.191 us/op
132+ MessageDigestBenchmark.md5ReuseInstance avgt 5 2.816 ± 0.086 us/op
133+ MessageDigestBenchmark.sha1NewInstance avgt 5 1.329 ± 0.051 us/op
134+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 1.363 ± 0.238 us/op
135+ MessageDigestBenchmark.sha256NewInstance avgt 5 1.397 ± 0.133 us/op
136+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 1.391 ± 0.047 us/op
137+
138+ jdk22 x86_64:
139+ Benchmark Mode Cnt Score Error Units
140+ MessageDigestBenchmark.md5NewInstance avgt 5 4.757 ± 0.179 us/op
141+ MessageDigestBenchmark.md5ReuseInstance avgt 5 4.689 ± 0.300 us/op
142+ MessageDigestBenchmark.sha1NewInstance avgt 5 1.460 ± 0.049 us/op
143+ MessageDigestBenchmark.sha1ReuseInstance avgt 5 1.423 ± 0.066 us/op
144+ MessageDigestBenchmark.sha256NewInstance avgt 5 1.567 ± 0.123 us/op
145+ MessageDigestBenchmark.sha256ReuseInstance avgt 5 1.521 ± 0.084 us/op
146+ */
0 commit comments