001 package net.sf.logdistiller.logtypes; 002 003 /* 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 import java.io.*; 018 import java.text.SimpleDateFormat; 019 import java.text.DateFormat; 020 import java.text.ParseException; 021 import java.util.Date; 022 import java.util.Locale; 023 import java.util.regex.Pattern; 024 025 import net.sf.logdistiller.LogEvent; 026 import net.sf.logdistiller.LogType; 027 028 /** 029 * Oracle Database's <code>alert.log</code> file parser. A typical rule configuration with such log files is: 030 * 031 * <pre> 032 * <group id="ORA"> 033 * <description>ORA-* messages</description> 034 * <condition> 035 * <match attribute="message" type="contains">ORA-</match> 036 * </condition> 037 * <plugin type="sampling"> 038 * <param name="attribute">message</param> 039 * <param name="regexp">(ORA-\d+)</param> 040 * </plugin> 041 * lt;/group> 042 * </pre> 043 * 044 * By default, the classification rules generated by the GUI for this type of logs: 045 * <ol> 046 * <li>will contain a such "ORA" group for events with an ORA- id</li> 047 * <li>but won't be able to sort other events, as the log event structure is too generic (the message has no specific 048 * format).</li> 049 * </ol> 050 * 051 * @since 0.9 052 */ 053 public class OracleAlertLogEvent 054 extends LogEvent 055 implements Comparable 056 { 057 public final static String ID = "oracle-alert"; 058 059 public final String timestamp; 060 061 public final Date date; 062 063 public final String message; 064 065 public final static LogType LOGTYPE = new LogType.Basic( ID ); 066 067 private final static DateFormat DATE_FORMAT = new SimpleDateFormat( "EEE MMM dd HH:mm:ss yyyy", Locale.US ); 068 069 private final static String[] ATTRIBUTE_NAMES = 070 { "logSource", "timestamp", "timestamp.day", "timestamp.time", "message" }; 071 072 public final static LogType.Description DESCRIPTION = new Description( (LogType.Basic) LOGTYPE, ATTRIBUTE_NAMES ); 073 074 public OracleAlertLogEvent( Factory factory, String firstLine, String message ) 075 throws ParseException 076 { 077 super( factory, firstLine + Factory.NEWLINE + message ); 078 timestamp = firstLine; 079 date = DATE_FORMAT.parse( timestamp ); 080 this.message = message; 081 setAttributes( new String[] { factory.getLogSource(), timestamp, 082 timestamp.substring( 0, 10 ) + timestamp.substring( 19, 24 ), timestamp.substring( 11, 19 ), message } ); 083 } 084 085 public int compareTo( Object o ) 086 { 087 return date.compareTo( ( (OracleAlertLogEvent) o ).date ); 088 } 089 090 private static class Description 091 extends LogType.Description 092 { 093 public Description( LogType.Basic logtype, String[] attributeNames ) 094 { 095 super( logtype, attributeNames ); 096 logtype.setDescription( this ); 097 } 098 099 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=\"ORA\">\n" 108 + " <description>ORA-* messages</description>\n" 109 + " <condition>\n" 110 + " <match attribute=\"message\" type=\"contains\">ORA-</match>\n" 111 + " </condition>\n" 112 + " <report publisher=\"file\"/>\n" 113 + " <plugin type=\"sampling\">\n" 114 + " <param name=\"attribute\">message</param>\n" 115 + " <param name=\"regexp\">(ORA-\\d+)</param>\n" 116 + " </plugin>\n" 117 + " </group>"; 118 } 119 } 120 121 private static class Factory 122 extends LogEvent.Factory 123 { 124 private final LineNumberReader reader; 125 126 private String curLine; 127 128 private final static Pattern DATE_PATTERN = 129 Pattern.compile( "\\w{3} \\w{3} \\d{2} \\d{2}:\\d{2}:\\d{2} \\d{4}" ); 130 131 public Factory( Description description, Reader reader, String logSource ) 132 throws FileNotFoundException 133 { 134 super( description, logSource ); 135 this.reader = new LineNumberReader( reader ); 136 } 137 138 /** 139 * Detect the start of a new log event 140 */ 141 protected boolean detectLogEventStart( String line ) 142 { 143 return DATE_PATTERN.matcher( line ).matches(); 144 } 145 146 protected LogEvent readNextEvent() 147 throws IOException, ParseException 148 { 149 if ( curLine == null ) 150 { 151 curLine = reader.readLine(); 152 if ( curLine == null ) 153 { 154 // EOF 155 return null; 156 } 157 // beginning of log file does not start with a complete log event with timestamp 158 while ( !detectLogEventStart( curLine ) ) 159 { 160 curLine = reader.readLine(); 161 if ( curLine == null ) 162 { 163 // EOF 164 return null; 165 } 166 } 167 } 168 String firstLine = curLine; 169 StringBuffer buffer = new StringBuffer(); 170 while ( ( ( curLine = reader.readLine() ) != null ) && ( !detectLogEventStart( curLine ) ) ) 171 { 172 if ( buffer.length() > 0 ) 173 { 174 buffer.append( NEWLINE ); 175 } 176 buffer.append( curLine ); 177 } 178 return new OracleAlertLogEvent( this, firstLine, buffer.toString() ); 179 } 180 } 181 }