View Javadoc

1   package net.sf.logdistiller.logtypes;
2   
3   /*
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  import java.io.*;
18  import java.text.DateFormat;
19  import java.text.ParseException;
20  import java.text.SimpleDateFormat;
21  import java.util.Date;
22  import java.util.Locale;
23  import java.util.Map;
24  
25  import net.sf.logdistiller.LogEvent;
26  import net.sf.logdistiller.LogType;
27  import net.sf.logdistiller.util.FormatUtil;
28  import net.sf.logdistiller.util.StringCutter;
29  
30  /**
31   * Log event for <a href="http://edocs.bea.com/">BEA Weblogic server</a>'s logs. By default, the date format is
32   * <code>MMM d, yyyy K:mm:ss a zz</code> with <code>en_US</code> locale, but you can change these values with logtype
33   * parameters <code>date.format</code> (expressed as a
34   * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html">java.text.SimpleDateFormat pattern</a>)
35   * and <code>date.locale</code>.<br>
36   * Example:
37   *
38   * <pre>
39   * &lt;logtype id=&quot;weblogic&quot;&gt;
40   *  &lt;param name=&quot;date.locale&quot;&gt;fr_FR&lt;/param&gt;
41   *  &lt;param name=&quot;date.format&quot;&gt;MMM d, yyyy K:mm:ss a zz&lt;/param&gt;
42   * &lt;/logtype&gt;
43   * </pre>
44   *
45   * By default, the classification rules generated by the GUI for this type of logs will sort events based on the
46   * following attributes: <code>severity</code>, then <code>subsystem</code> then <code>message_id</code>.
47   *
48   * @see java.text.SimpleDateFormat
49   */
50  public class WeblogicLogEvent
51      extends LogEvent
52      implements Comparable
53  {
54      public final static String ID = "weblogic";
55  
56      public final Date date;
57  
58      public final String timestamp;
59  
60      public final String severity;
61  
62      public final String subsystem;
63  
64      public final String machine;
65  
66      public final String server;
67  
68      public final String thread_id;
69  
70      public final String transaction_id;
71  
72      public final String user_id;
73  
74      public final String message_id;
75  
76      public final String message_text;
77  
78      public final String stacktrace;
79  
80      public final static LogType LOGTYPE = new WlLogType();
81  
82      private final static String LOGEVENT_START = "####<";
83  
84      private final static String[] ATTRIBUTE_NAMES =
85          { "logSource", "timestamp", "severity", "subsystem", "machine", "server", "thread_id", "transaction_id",
86              "user_id", "message_id", "message_text", "stacktrace" };
87  
88      public WeblogicLogEvent( Factory factory, String rawLog )
89          throws ParseException
90      {
91          super( factory, rawLog );
92          StringCutter cutter = new StringCutter( rawLog );
93          cutter.parseTo( LOGEVENT_START );
94          timestamp = cutter.parseTo( "> <" );
95          date = factory.parseDate( timestamp );
96          severity = cutter.parseTo( "> <" );
97          subsystem = cutter.parseTo( "> <" );
98          machine = cutter.parseTo( "> <" );
99          server = cutter.parseTo( "> <" );
100         thread_id = cutter.parseTo( "> <" );
101         transaction_id = cutter.parseTo( "> <" );
102         user_id = cutter.parseTo( "> <" );
103         message_id = cutter.parseTo( "> <" );
104         message_text = cutter.parseTo( "> " );
105         String remaining = cutter.getRemaining();
106         stacktrace = ( "".equals( remaining ) ) ? "" : remaining.substring( LogEvent.Factory.NEWLINE.length() );
107         setAttributes( new String[] { factory.getLogSource(), timestamp, severity, subsystem, machine, server,
108             thread_id, transaction_id, user_id, message_id, message_text, stacktrace } );
109     }
110 
111     public int compareTo( Object o )
112     {
113         return date.compareTo( ( (WeblogicLogEvent) o ).date );
114     }
115 
116     /**
117      * Weblogic log type supports following parameters:
118      * <ul>
119      * <li><code>date.format</code></li>
120      * <li><code>date.locale</code></li>
121      * </ul>
122      */
123     private static class WlLogType
124         extends LogType
125     {
126         private final static String DEFAULT_DATE_FORMAT = "MMM d, yyyy K:mm:ss a zz";
127 
128         public WlLogType()
129         {
130             super( WeblogicLogEvent.ID );
131         }
132 
133         public LogType.Description newDescription( Map params )
134         {
135             String dateFormat = (String) params.get( "date.format" );
136             dateFormat = ( dateFormat == null ) ? DEFAULT_DATE_FORMAT : dateFormat;
137             String locale = (String) params.get( "date.locale" );
138             Locale lcle = ( locale == null ) ? Locale.US : FormatUtil.parseLocale( locale );
139             return new WeblogicLogEvent.Description( this, WeblogicLogEvent.ATTRIBUTE_NAMES, dateFormat, lcle );
140         }
141     }
142 
143     private static class Description
144         extends LogType.Description
145     {
146         /** @since 0.9 */
147         private final String format;
148 
149         /** @since 0.9 */
150         private final Locale locale;
151 
152         /** @since 0.9 */
153         private final DateFormat df;
154 
155         public Description( LogType logtype, String[] attributeNames, String format, Locale locale )
156         {
157             super( logtype, attributeNames );
158             this.format = format;
159             this.locale = locale;
160             this.df = new SimpleDateFormat( format, locale );
161         }
162 
163         public LogEvent.Factory newFactory( Reader reader, String logSource )
164             throws IOException
165         {
166             return new Factory( this, reader, logSource );
167         }
168 
169         /** @since 0.9 */
170         public DateFormat getDateFormat()
171         {
172             return df;
173         }
174 
175         /** @since 0.9 */
176         public Locale getLocale()
177         {
178             return locale;
179         }
180 
181         /** @since 0.9 */
182         public String getFormat()
183         {
184             return format;
185         }
186 
187         public String getDefaultSpecificGroups()
188         {
189             return "  <group id=\"warning\">\n"
190                 + "    <description>Warning events</description>\n"
191                 + "    <condition>\n"
192                 + "      <match attribute=\"severity\" type=\"equals\">Warning</match>\n"
193                 + "    </condition>\n"
194                 + "    <report publisher=\"file\"/>\n"
195                 + "    <plugin type=\"sampling\">\n"
196                 + "      <param name=\"attributes\">subsystem,message_id</param>\n"
197                 + "    </plugin>\n"
198                 + "  </group>\n"
199                 + "\n"
200                 + "  <group id=\"error\">\n"
201                 + "    <description>Error events</description>\n"
202                 + "    <condition>\n"
203                 + "      <match attribute=\"severity\" type=\"equals\">Error</match>\n"
204                 + "    </condition>\n"
205                 + "    <report publisher=\"file\"/>\n"
206                 + "    <plugin type=\"sampling\">\n"
207                 + "      <param name=\"attributes\">subsystem,message_id</param>\n"
208                 + "    </plugin>\n"
209                 + "  </group>";
210         }
211 
212         public String getDefaultSamplingAttributes()
213         {
214             return "severity,subsystem,message_id";
215         }
216     }
217 
218     private static class Factory
219         extends LogEvent.Factory
220     {
221         private final DateFormat df;
222 
223         private final LineNumberReader reader;
224 
225         private String curLine;
226 
227         public Factory( Description description, Reader reader, String logSource )
228             throws FileNotFoundException
229         {
230             super( description, logSource );
231             this.reader = new LineNumberReader( reader );
232             this.df = description.getDateFormat();
233         }
234 
235         protected boolean detectLogEventStart( String line )
236         {
237             return line.startsWith( LOGEVENT_START );
238         }
239 
240         protected LogEvent readNextEvent()
241             throws IOException, ParseException
242         {
243             if ( curLine == null )
244             {
245                 curLine = reader.readLine();
246                 if ( curLine == null )
247                 {
248                     // EOF
249                     return null;
250                 }
251             }
252             if ( !detectLogEventStart( curLine ) )
253             {
254                 if ( curLine.length() > 15 )
255                 {
256                     curLine = curLine.substring( 0, 15 ) + "...";
257                 }
258                 String msg = " should start with '" + LOGEVENT_START + "' but found '" + curLine + "'";
259                 if ( reader.getLineNumber() == 1 )
260                 {
261                     throw new ParseException( "bad log format: is it really a Weblogic log file? It" + msg, 0 );
262                 }
263                 throw new ParseException( "bad log format, line " + reader.getLineNumber() + msg, 0 );
264             }
265             StringBuffer buffer = new StringBuffer( curLine );
266             while ( ( ( curLine = reader.readLine() ) != null ) && ( !detectLogEventStart( curLine ) ) )
267             {
268                 buffer.append( NEWLINE );
269                 buffer.append( curLine );
270             }
271             return new WeblogicLogEvent( this, buffer.toString() );
272         }
273 
274         public Date parseDate( String date )
275             throws ParseException
276         {
277             try
278             {
279                 return df.parse( date );
280             }
281             catch ( ParseException pe )
282             {
283                 Description desc = (Description) description;
284                 throw new ParseException( pe.getMessage() + ", expected format: " + desc.getFormat()
285                     + ", expected locale: " + desc.getLocale(), pe.getErrorOffset() );
286             }
287         }
288     }
289 }