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.SimpleDateFormat;
19  import java.text.DateFormat;
20  import java.text.ParseException;
21  import java.util.Date;
22  import java.util.regex.Pattern;
23  
24  import net.sf.logdistiller.LogEvent;
25  import net.sf.logdistiller.LogType;
26  import net.sf.logdistiller.util.StringCutter;
27  
28  /**
29   * Log event for <a href="http://jboss.org/">JBoss</a>'s server logs. By default, the classification rules generated by
30   * the GUI for this type of logs will sort events based on the following attributes: <code>level</code> then
31   * <code>logger</code>.
32   *
33   * @since 0.9
34   */
35  public class JBossLogEvent
36      extends LogEvent
37      implements Comparable
38  {
39      public final static String ID = "jboss";
40  
41      public final String timestamp;
42  
43      public final Date date;
44  
45      public final String level;
46  
47      public final String logger;
48  
49      public final String message;
50  
51      public final String throwable;
52  
53      public final String throwable_firstLine;
54  
55      public final String throwable_class;
56  
57      public final static LogType LOGTYPE = new LogType.Basic( ID );
58  
59      private final static DateFormat DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss,SSS" );
60  
61      private final static String[] ATTRIBUTE_NAMES =
62          { "logSource", "timestamp", "timestamp.date", "timestamp.time", "level", "logger", "message", "throwable",
63              "throwable.firstline", "throwable.class" };
64  
65      public final static LogType.Description DESCRIPTION = new Description( (LogType.Basic) LOGTYPE, ATTRIBUTE_NAMES );
66  
67      public JBossLogEvent( Factory factory, String firstLine, String secondLine, String throwable )
68          throws ParseException
69      {
70          super( factory, ( secondLine == null ) ? firstLine : ( firstLine + Factory.NEWLINE + throwable ) );
71          timestamp = firstLine.substring( 0, 23 );
72          date = DATE_FORMAT.parse( timestamp );
73          level = firstLine.substring( 24, 29 ).trim();
74          StringCutter cutter = new StringCutter( firstLine.substring( 31 ) );
75          logger = cutter.parseTo( "] " );
76          message = cutter.getRemaining();
77          this.throwable = throwable;
78          throwable_firstLine = ( secondLine == null ) ? "" : secondLine;
79          int index = throwable_firstLine.indexOf( ':' );
80          throwable_class = ( index > 0 ) ? throwable.substring( 0, index ) : "";
81          setAttributes( new String[] { factory.getLogSource(), timestamp, timestamp.substring( 0, 10 ),
82              timestamp.substring( 11, 23 ), level, logger, message, throwable, throwable_firstLine, throwable_class } );
83      }
84  
85      public int compareTo( Object o )
86      {
87          return date.compareTo( ( (JBossLogEvent) o ).date );
88      }
89  
90      private static class Description
91          extends LogType.Description
92      {
93          public Description( LogType.Basic logtype, String[] attributeNames )
94          {
95              super( logtype, attributeNames );
96              logtype.setDescription( this );
97          }
98  
99          public LogEvent.Factory newFactory( Reader reader, String logSource )
100             throws IOException
101         {
102             return new Factory( this, reader, logSource );
103         }
104 
105         public String getDefaultSpecificGroups()
106         {
107             return "  <group id=\"warn\">\n"
108                 + "    <description>WARN events</description>\n"
109                 + "    <condition>\n"
110                 + "      <match attribute=\"level\" type=\"equals\">WARN</match>\n"
111                 + "    </condition>\n"
112                 + "    <report publisher=\"file\"/>\n"
113                 + "    <plugin type=\"sampling\">\n"
114                 + "      <param name=\"attributes\">logger</param>\n"
115                 + "    </plugin>\n"
116                 + "  </group>\n"
117                 + "\n"
118                 + "  <group id=\"error\">\n"
119                 + "    <description>ERROR events</description>\n"
120                 + "    <condition>\n"
121                 + "      <match attribute=\"level\" type=\"equals\">ERROR</match>\n"
122                 + "    </condition>\n"
123                 + "    <report publisher=\"file\"/>\n"
124                 + "    <plugin type=\"sampling\">\n"
125                 + "      <param name=\"attributes\">logger</param>\n"
126                 + "    </plugin>\n"
127                 + "  </group>";
128         }
129 
130         public String getDefaultSamplingAttributes()
131         {
132             return "level,logger";
133         }
134     }
135 
136     private static class Factory
137         extends LogEvent.Factory
138     {
139         private final LineNumberReader reader;
140 
141         private String curLine;
142 
143         public Factory( Description description, Reader reader, String logSource )
144             throws FileNotFoundException
145         {
146             super( description, logSource );
147             this.reader = new LineNumberReader( reader );
148         }
149 
150         private final static Pattern DATE_PATTERN =
151             Pattern.compile( "\\A\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3} " );
152 
153         /**
154          * Detect the start of a new log event
155          */
156         protected boolean detectLogEventStart( String line )
157         {
158             // heuristics: detects the beginning of the date...
159             return DATE_PATTERN.matcher( line ).find();
160         }
161 
162         protected LogEvent readNextEvent()
163             throws IOException, ParseException
164         {
165             if ( curLine == null )
166             {
167                 curLine = reader.readLine();
168                 if ( curLine == null )
169                 {
170                     // EOF
171                     return null;
172                 }
173             }
174             String firstLine = curLine;
175             String secondLine = null;
176             StringBuffer buffer = new StringBuffer();
177             while ( ( ( curLine = reader.readLine() ) != null ) && ( !detectLogEventStart( curLine ) ) )
178             {
179                 if ( secondLine == null )
180                 {
181                     secondLine = curLine;
182                 }
183                 else
184                 {
185                     buffer.append( NEWLINE );
186                 }
187                 buffer.append( curLine );
188             }
189             return new JBossLogEvent( this, firstLine, secondLine, buffer.toString() );
190         }
191     }
192 }