1- package dev .faststats .errors . impl ;
1+ package dev .faststats .core ;
22
33import com .google .gson .JsonArray ;
44import com .google .gson .JsonObject ;
5- import dev .faststats .errors . ErrorTracker ;
6- import dev .faststats .errors .concurrent .TrackingExecutors ;
7- import dev .faststats .errors .concurrent .TrackingThreadFactory ;
8- import dev .faststats .errors .concurrent .TrackingThreadPoolExecutor ;
5+ import dev .faststats .core . concurrent . TrackingBase ;
6+ import dev .faststats .core .concurrent .TrackingExecutors ;
7+ import dev .faststats .core .concurrent .TrackingThreadFactory ;
8+ import dev .faststats .core .concurrent .TrackingThreadPoolExecutor ;
99import org .jspecify .annotations .Nullable ;
1010
11- import java .security .PrivilegedAction ;
12- import java .security .PrivilegedExceptionAction ;
1311import java .util .ArrayList ;
1412import java .util .Arrays ;
1513import java .util .List ;
1614import java .util .Map ;
17- import java .util .Optional ;
1815import java .util .concurrent .ConcurrentHashMap ;
1916
20- public final class SimpleErrorTracker implements ErrorTracker {
17+ final class SimpleErrorTracker implements ErrorTracker {
2118 private final int stackTraceLimit = Integer .getInteger ("faststats.stack-trace-limit" , 15 );
2219 private final Map <String , Integer > collected = new ConcurrentHashMap <>();
2320 private final Map <String , JsonObject > reports = new ConcurrentHashMap <>();
2421
22+ private final TrackingBase base = new SimpleTrackingBase (this );
2523 private final TrackingExecutors executors = new SimpleTrackingExecutors (this );
2624 private final TrackingThreadFactory threadFactory = new SimpleTrackingThreadFactory (this );
2725 private final TrackingThreadPoolExecutor threadPoolExecutor = new SimpleTrackingThreadPoolExecutor (this );
@@ -86,20 +84,20 @@ private JsonObject compile(Throwable error, @Nullable List<StackTraceElement> su
8684 "\\ b(\\ d{1,3})\\ .(\\ d{1,3})\\ .(\\ d{1,3})\\ .(\\ d{1,3})\\ b" ;
8785 private static final String IPV6_PATTERN =
8886 "(?i)\\ b([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}\\ b|" + // Full form
89- "(?i)\\ b([0-9a-f]{1,4}:){1,7}:\\ b|" + // Trailing ::
90- "(?i)\\ b([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}\\ b|" + // :: in middle (1 group after)
91- "(?i)\\ b([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\\ b|" + // :: in middle (2 groups after)
92- "(?i)\\ b([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\\ b|" + // :: in middle (3 groups after)
93- "(?i)\\ b([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\\ b|" + // :: in middle (4 groups after)
94- "(?i)\\ b([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\\ b|" + // :: in middle (5 groups after)
95- "(?i)\\ b[0-9a-f]{1,4}:(:[0-9a-f]{1,4}){1,6}\\ b|" + // :: in middle (6 groups after)
96- "(?i)\\ b:(:[0-9a-f]{1,4}){1,7}\\ b|" + // Leading ::
97- "(?i)\\ b::([0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4}\\ b|" + // :: at start
98- "(?i)\\ b::\\ b" ; // Just ::
87+ "(?i)\\ b([0-9a-f]{1,4}:){1,7}:\\ b|" + // Trailing ::
88+ "(?i)\\ b([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}\\ b|" + // :: in middle (1 group after)
89+ "(?i)\\ b([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\\ b|" + // :: in middle (2 groups after)
90+ "(?i)\\ b([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\\ b|" + // :: in middle (3 groups after)
91+ "(?i)\\ b([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\\ b|" + // :: in middle (4 groups after)
92+ "(?i)\\ b([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\\ b|" + // :: in middle (5 groups after)
93+ "(?i)\\ b[0-9a-f]{1,4}:(:[0-9a-f]{1,4}){1,6}\\ b|" + // :: in middle (6 groups after)
94+ "(?i)\\ b:(:[0-9a-f]{1,4}){1,7}\\ b|" + // Leading ::
95+ "(?i)\\ b::([0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4}\\ b|" + // :: at start
96+ "(?i)\\ b::\\ b" ; // Just ::
9997 private static final String USER_HOME_PATH_PATTERN =
10098 "(/home/)[^/\\ s]+" + // Linux: /home/username
101- "|(/Users/)[^/\\ s]+" + // macOS: /Users/username
102- "|((?i)[A-Z]:\\ \\ Users\\ \\ )[^\\ \\ \\ s]+" ; // Windows: A-Z:\\Users\\username
99+ "|(/Users/)[^/\\ s]+" + // macOS: /Users/username
100+ "|((?i)[A-Z]:\\ \\ Users\\ \\ )[^\\ \\ \\ s]+" ; // Windows: A-Z:\\Users\\username
103101
104102 private String anonymize (String message ) {
105103 message = message .replaceAll (IPV4_PATTERN , "[IP hidden]" );
@@ -110,8 +108,7 @@ private String anonymize(String message) {
110108 return message ;
111109 }
112110
113- @ Override
114- public Optional <JsonArray > getData () {
111+ public JsonArray getData () {
115112 var report = new JsonArray (reports .size ());
116113
117114 reports .forEach ((hash , object ) -> {
@@ -132,10 +129,9 @@ public Optional<JsonArray> getData() {
132129 report .add (entry );
133130 });
134131
135- return Optional . of ( report ) ;
132+ return report ;
136133 }
137134
138- @ Override
139135 public void clear () {
140136 collected .replaceAll ((k , v ) -> 0 );
141137 reports .clear ();
@@ -152,21 +148,40 @@ public void attachErrorContext(@Nullable ClassLoader loader) {
152148 }
153149
154150 @ Override
155- public boolean isSameLoader (ClassLoader loader , Throwable error ) {
156- StackTraceElement [] stackTrace = error .getStackTrace ();
151+ public TrackingBase base () {
152+ return base ;
153+ }
154+
155+ @ Override
156+ public TrackingExecutors executors () {
157+ return executors ;
158+ }
159+
160+ @ Override
161+ public TrackingThreadFactory threadFactory () {
162+ return threadFactory ;
163+ }
164+
165+ @ Override
166+ public TrackingThreadPoolExecutor threadPoolExecutor () {
167+ return threadPoolExecutor ;
168+ }
169+
170+ private boolean isSameLoader (final ClassLoader loader , final Throwable error ) {
171+ var stackTrace = error .getStackTrace ();
157172 if (stackTrace == null || stackTrace .length == 0 ) {
158173 return false ;
159174 }
160175
161- int firstNonLibraryIndex = findFirstNonLibraryFrameIndex (stackTrace );
176+ var firstNonLibraryIndex = findFirstNonLibraryFrameIndex (stackTrace );
162177 if (firstNonLibraryIndex == -1 ) {
163178 return false ;
164179 }
165180
166- int framesToCheck = Math .min (5 , stackTrace .length - firstNonLibraryIndex );
181+ var framesToCheck = Math .min (5 , stackTrace .length - firstNonLibraryIndex );
167182
168- for (int i = 0 ; i < framesToCheck ; i ++) {
169- StackTraceElement frame = stackTrace [firstNonLibraryIndex + i ];
183+ for (var i = 0 ; i < framesToCheck ; i ++) {
184+ var frame = stackTrace [firstNonLibraryIndex + i ];
170185 if (isLibraryClass (frame .getClassName ())) {
171186 continue ;
172187 }
@@ -178,75 +193,24 @@ public boolean isSameLoader(ClassLoader loader, Throwable error) {
178193 return true ;
179194 }
180195
181- @ Override
182- public Runnable tracked (Runnable runnable ) {
183- return () -> {
184- try {
185- runnable .run ();
186- } catch (Throwable error ) {
187- trackError (error );
188- throw error ;
189- }
190- };
191- }
192-
193- @ Override
194- public <T > PrivilegedAction <T > tracked (PrivilegedAction <T > action ) {
195- return () -> {
196- try {
197- return action .run ();
198- } catch (Throwable error ) {
199- trackError (error );
200- throw error ;
201- }
202- };
203- }
204-
205- @ Override
206- public <T > PrivilegedExceptionAction <T > tracked (PrivilegedExceptionAction <T > action ) {
207- return () -> {
208- try {
209- return action .run ();
210- } catch (Throwable error ) {
211- trackError (error );
212- throw error ;
213- }
214- };
215- }
216-
217- @ Override
218- public TrackingExecutors executors () {
219- return executors ;
220- }
221-
222- @ Override
223- public TrackingThreadFactory threadFactory () {
224- return threadFactory ;
225- }
226-
227- @ Override
228- public TrackingThreadPoolExecutor threadPoolExecutor () {
229- return threadPoolExecutor ;
230- }
231-
232- private int findFirstNonLibraryFrameIndex (StackTraceElement [] stackTrace ) {
233- for (int i = 0 ; i < stackTrace .length ; i ++) {
196+ private int findFirstNonLibraryFrameIndex (final StackTraceElement [] stackTrace ) {
197+ for (var i = 0 ; i < stackTrace .length ; i ++) {
234198 if (!isLibraryClass (stackTrace [i ].getClassName ())) {
235199 return i ;
236200 }
237201 }
238202 return -1 ;
239203 }
240204
241- private boolean isLibraryClass (String className ) {
205+ private boolean isLibraryClass (final String className ) {
242206 return className .startsWith ("java." )
243207 || className .startsWith ("javax." )
244208 || className .startsWith ("sun." )
245209 || className .startsWith ("com.sun." )
246210 || className .startsWith ("jdk." );
247211 }
248212
249- private boolean isFromLoader (StackTraceElement frame , ClassLoader loader ) {
213+ private boolean isFromLoader (final StackTraceElement frame , final ClassLoader loader ) {
250214 try {
251215 var clazz = Class .forName (frame .getClassName (), false , loader );
252216 return isSameClassLoader (clazz .getClassLoader (), loader );
@@ -255,18 +219,13 @@ private boolean isFromLoader(StackTraceElement frame, ClassLoader loader) {
255219 }
256220 }
257221
258- private boolean isSameClassLoader (ClassLoader classLoader , ClassLoader loader ) {
259- if (classLoader == loader ) {
260- return true ;
261- }
262- // Walk up the class loader hierarchy
263- ClassLoader current = classLoader ;
264- while (current != null ) {
265- if (current == loader ) {
266- return true ;
267- }
222+ private boolean isSameClassLoader (final ClassLoader classLoader , final ClassLoader loader ) {
223+ if (classLoader == loader ) return true ;
224+
225+ var current = classLoader ;
226+ while (current != null && current != loader ) {
268227 current = current .getParent ();
269228 }
270- return false ;
229+ return loader == current ;
271230 }
272231}
0 commit comments