1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package net.codesmarts.log4j;
32
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.LinkedList;
36 import org.apache.log4j.Priority;
37 import org.apache.log4j.spi.LoggingEvent;
38
39 /***
40 * Log of events for a single appender and thread.
41 * @author Fred McCann
42 */
43 public class ThreadEventLog {
44 public static final boolean FULL_REPORT = true;
45 public static final boolean INCREMENTAL_REPORT = false;
46
47 /***
48 * Set to true if a threashold level event has occured
49 */
50 private boolean _triggered = false;
51
52 /***
53 * List of logged events
54 */
55 private List _events = new LinkedList();
56
57 /***
58 * Threshold required to generate a bug report
59 */
60 private Priority _threadhold;
61
62 /***
63 * For short running threads (like serlvet requets/reponse handlers), a log report is
64 * generated when the application thread dies. For longer running threads, a threadhold
65 * size is used. If a watch thread wakes from sleep and there are events in the buffer
66 * at or greater than the threshold size and there is at least one event of sufficient
67 * priority level, a bug report is generated.
68 */
69 private int _thresholdSize;
70
71 /***
72 * Amount of non threshold or greater events to prune
73 */
74 private int _remove;
75
76 /***
77 * Maximum buffer size
78 */
79 private int _maxSize;
80
81 /***
82 * Hash method
83 */
84 private int _hashMethod = HashUtility.LOCATION;
85
86 /***
87 * Constructor
88 * @param threadhold Threshold required to generate a bug report
89 * @param thresholdSize Threshold size of buffer required to trigger a bug report
90 * @param maxSize maximum size of buffer
91 * @param hashMethod value specifying hash method for creating semiunique keys
92 */
93 protected ThreadEventLog(Priority threadhold, int thresholdSize, int maxSize, int hashMethod) {
94 _threadhold = threadhold;
95 _thresholdSize = thresholdSize;
96 _remove = (int)((float)_thresholdSize*.2);
97 _maxSize = maxSize;
98 _hashMethod = hashMethod;
99 }
100
101 /***
102 * Add event to the log
103 * @param event
104 */
105 protected synchronized void addEvent(LoggingEvent event) {
106 _events.add(event);
107
108 if (event.getLevel().isGreaterOrEqual(_threadhold))
109 _triggered = true;
110
111 if (!_triggered && _events.size()>=_thresholdSize) {
112
113 int i=0;
114 while (i<_events.size() && i<=_remove) {
115 _events.remove(0);
116 i++;
117 }
118 }
119 else if (_events.size()>_maxSize) {
120 _events.remove(0);
121 }
122 }
123
124 /***
125 * Generate a bug report from this list
126 * @param all set to true to dump all events
127 * @return BugReport object if a report can be filed, else returns null
128 */
129 protected synchronized BugReport generateBugReport(boolean all) {
130 _triggered = false;
131
132 int index = _events.size()-1;
133
134 if (all==false) {
135
136
137 if (_events.size()<_thresholdSize)
138 return null;
139
140
141 boolean found = false;
142 int i = index;
143
144 while (!found && index>=0) {
145 LoggingEvent event = (LoggingEvent)_events.get(i);
146 if (event.getLevel().isGreaterOrEqual(_threadhold)) {
147 index = i;
148 found = true;
149 }
150 i--;
151 }
152 }
153
154
155 List reportedEvents = new ArrayList(index+1);
156
157 for (int i=0; i<=index; i++) {
158 reportedEvents.add(_events.remove(0));
159 }
160
161 if (reportedEvents.size()>0)
162 return new BugReport(reportedEvents, _hashMethod);
163
164 return null;
165 }
166
167 /***
168 * @return Returns the _triggered.
169 */
170 protected synchronized boolean isTriggered() {
171 return _triggered;
172 }
173 }