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.Locale;
23  import java.util.regex.Pattern;
24  
25  import net.sf.logdistiller.LogEvent;
26  import net.sf.logdistiller.LogType;
27  import net.sf.logdistiller.util.LogEventBuilder;
28  
29  /**
30   * Oracle Database's <code>alert.log</code> file parser. A typical rule configuration with such log files is:
31   *
32   * <pre>
33   * &lt;group id=&quot;ORA&quot;&gt;
34   *  &lt;description&gt;ORA-* messages&lt;/description&gt;
35   *  &lt;condition&gt;
36   *    &lt;match attribute=&quot;message&quot; type=&quot;contains&quot;&gt;ORA-&lt;/match&gt;
37   *  &lt;/condition&gt;
38   *  &lt;plugin type=&quot;sampling&quot;&gt;
39   *    &lt;param name=&quot;attribute&quot;&gt;message&lt;/param&gt;
40   *    &lt;param name=&quot;regexp&quot;&gt;(ORA-\d+)&lt;/param&gt;
41   *  &lt;/plugin&gt;
42   * lt;/group&gt;
43   * </pre>
44   *
45   * By default, the classification rules generated by the GUI for this type of logs:
46   * <ol>
47   * <li>will contain a such "ORA" group for events with an ORA- id</li>
48   * <li>but won't be able to sort other events, as the log event structure is too generic (the message has no specific
49   * format).</li>
50   * </ol>
51   *
52   * @since 0.9
53   */
54  public class OracleAlertLogEvent
55      extends LogEvent
56      implements Comparable<OracleAlertLogEvent>
57  {
58      public final static String ID = "oracle-alert";
59  
60      public final String timestamp;
61  
62      public final Date date;
63  
64      public final String message;
65  
66      public final static LogType LOGTYPE = new LogType.Basic( ID );
67  
68      private final static DateFormat DATE_FORMAT = new SimpleDateFormat( "EEE MMM dd HH:mm:ss yyyy", Locale.US );
69  
70      private final static String[] ATTRIBUTE_NAMES =
71          { "logSource", "timestamp", "timestamp.day", "timestamp.time", "message" };
72  
73      public final static LogType.Description DESCRIPTION = new Description( (LogType.Basic) LOGTYPE, ATTRIBUTE_NAMES );
74  
75      public OracleAlertLogEvent( LogEvent.Factory factory, String firstLine, String message )
76          throws ParseException
77      {
78          super( factory, firstLine + Factory.NEWLINE + message );
79          timestamp = firstLine;
80          date = DATE_FORMAT.parse( timestamp );
81          this.message = message;
82          setAttributes( new String[] { factory.getLogSource(), timestamp,
83              timestamp.substring( 0, 10 ) + timestamp.substring( 19, 24 ), timestamp.substring( 11, 19 ), message } );
84      }
85  
86      public int compareTo( OracleAlertLogEvent o )
87      {
88          return date.compareTo( o.date );
89      }
90  
91      private static class Description
92          extends LogType.Description
93      {
94          public Description( LogType.Basic logtype, String[] attributeNames )
95          {
96              super( logtype, attributeNames );
97              logtype.setDescription( this );
98          }
99  
100         public LogEvent.Factory newFactory( Reader reader, String logSource )
101             throws IOException
102         {
103             return new Factory( this, reader, logSource );
104         }
105 
106         public String getDefaultSpecificGroups()
107         {
108             return "  <group id=\"ORA\">\n"
109                 + "    <description>ORA-* messages</description>\n"
110                 + "    <condition>\n"
111                 + "      <match attribute=\"message\" type=\"contains\">ORA-</match>\n"
112                 + "    </condition>\n"
113                 + "    <report publisher=\"file\"/>\n"
114                 + "    <plugin type=\"sampling\">\n"
115                 + "      <param name=\"attribute\">message</param>\n"
116                 + "      <param name=\"regexp\">(ORA-\\d+)</param>\n"
117                 + "    </plugin>\n"
118                 + "  </group>";
119         }
120     }
121 
122     private static class Factory
123         extends LogEvent.Factory
124     {
125         private final LineNumberReader reader;
126 
127         private String curLine;
128 
129         private final static Pattern DATE_PATTERN =
130             Pattern.compile( "\\w{3} \\w{3} \\d{2} \\d{2}:\\d{2}:\\d{2} \\d{4}" );
131 
132         public Factory( Description description, Reader reader, String logSource )
133             throws FileNotFoundException
134         {
135             super( description, logSource );
136             this.reader = new LineNumberReader( reader );
137         }
138 
139         /**
140          * Detect the start of a new log event
141          */
142         protected boolean detectLogEventStart( String line )
143         {
144             return DATE_PATTERN.matcher( line ).matches();
145         }
146 
147         protected LogEvent readNextEvent()
148             throws IOException, ParseException
149         {
150             if ( curLine == null )
151             {
152                 curLine = reader.readLine();
153                 if ( curLine == null )
154                 {
155                     // EOF
156                     return null;
157                 }
158                 // beginning of log file does not start with a complete log event with timestamp
159                 while ( !detectLogEventStart( curLine ) )
160                 {
161                     curLine = reader.readLine();
162                     if ( curLine == null )
163                     {
164                         // EOF
165                         return null;
166                     }
167                 }
168             }
169 
170             String firstLine = curLine;
171             int lineNumber = reader.getLineNumber();
172 
173             StringBuffer buffer = new StringBuffer();
174             while ( ( ( curLine = reader.readLine() ) != null ) && ( !detectLogEventStart( curLine ) ) )
175             {
176                 if ( buffer.length() > 0 )
177                 {
178                     buffer.append( NEWLINE );
179                 }
180                 buffer.append( curLine );
181             }
182 
183             return BUILDER.buildLogEvent( this, lineNumber, firstLine, buffer.toString() );
184         }
185 
186         private final static LogEventBuilder BUILDER = new LogEventBuilder()
187         {
188             protected LogEvent newEvent( LogEvent.Factory factory, String curLine, Object... objects )
189                 throws ParseException
190             {
191                 return new OracleAlertLogEvent( factory, curLine, (String) objects[0] );
192             }
193         };
194     }
195 }