1+ package io .github .rexrk .exception .insights .capture ;
2+
3+ import ch .qos .logback .classic .Level ;
4+ import ch .qos .logback .classic .spi .ILoggingEvent ;
5+ import ch .qos .logback .classic .spi .IThrowableProxy ;
6+ import ch .qos .logback .core .AppenderBase ;
7+ import io .github .rexrk .exception .insights .model .LogLine ;
8+
9+ import java .time .Instant ;
10+ import java .util .ArrayDeque ;
11+ import java .util .ArrayList ;
12+ import java .util .Deque ;
13+ import java .util .List ;
14+
15+ public class RingBufferLogAppender extends AppenderBase <ILoggingEvent > {
16+
17+ private final int bufferSize ;
18+ private final Deque <LogLine > buffer ;
19+
20+ public RingBufferLogAppender (int bufferSize ) {
21+ this .bufferSize = bufferSize ;
22+ this .buffer = new ArrayDeque <>(bufferSize );
23+ }
24+
25+ @ Override
26+ protected synchronized void append (ILoggingEvent event ) {
27+ if (!event .getLevel ().isGreaterOrEqual (Level .WARN )) return ;
28+
29+ if (buffer .size () == bufferSize ) {
30+ buffer .pollFirst ();
31+ }
32+
33+ buffer .addLast (new LogLine (
34+ event .getLevel ().toString (),
35+ event .getFormattedMessage (),
36+ event .getLoggerName (),
37+ event .getThreadName (),
38+ throwableClass (event .getThrowableProxy ()),
39+ throwableMessage (event .getThrowableProxy ()),
40+ Instant .ofEpochMilli (event .getTimeStamp ())
41+ ));
42+ }
43+
44+ public synchronized List <LogLine > drainRecent (int limit ) {
45+ List <LogLine > all = new ArrayList <>(buffer );
46+ int from = Math .max (0 , all .size () - limit );
47+ return all .subList (from , all .size ());
48+ }
49+
50+ private String throwableClass (IThrowableProxy proxy ) {
51+ return proxy != null ? proxy .getClassName () : null ;
52+ }
53+
54+ private String throwableMessage (IThrowableProxy proxy ) {
55+ return proxy != null ? proxy .getMessage () : null ;
56+ }
57+ }
0 commit comments