View Javadoc

1   /*
2   Copyright (c) 2005, CodeSmarts
3    All rights reserved.
4   
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions are
7   met:
8   	* 	Redistributions of source code must retain the above copyright
9   notice, this list of conditions and the following disclaimer.
10  	* 	Redistributions in binary form must reproduce the above
11  copyright notice, this list of conditions and the following disclaimer
12  in the documentation and/or other materials provided with the
13  distribution.
14  	* 	Neither the name of the CodeSmarts nor the names of its
15  contributors may be used to endorse or promote products derived from
16  this software without specific prior written permission.
17  
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
19  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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             // Prune older events          
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             // Don't make a report if threshold size has not been met
137             if (_events.size()<_thresholdSize)
138                 return null;
139             
140             // find the last instance of a threshold or greater event
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         // Package events into a bug report
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 }