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.DateFormat; 019 import java.text.ParseException; 020 import java.text.SimpleDateFormat; 021 import java.util.Date; 022 import java.util.Locale; 023 import java.util.Map; 024 025 import net.sf.logdistiller.LogEvent; 026 import net.sf.logdistiller.LogType; 027 import net.sf.logdistiller.util.FormatUtil; 028 import net.sf.logdistiller.util.StringCutter; 029 030 /** 031 * Log event for <a href="http://edocs.bea.com/">BEA Weblogic server</a>'s logs. By default, the date format is 032 * <code>MMM d, yyyy K:mm:ss a zz</code> with <code>en_US</code> locale, but you can change these values with logtype 033 * parameters <code>date.format</code> (expressed as a 034 * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/text/SimpleDateFormat.html">java.text.SimpleDateFormat pattern</a>) 035 * and <code>date.locale</code>.<br> 036 * Example: 037 * 038 * <pre> 039 * <logtype id="weblogic"> 040 * <param name="date.locale">fr_FR</param> 041 * <param name="date.format">MMM d, yyyy K:mm:ss a zz</param> 042 * </logtype> 043 * </pre> 044 * 045 * By default, the classification rules generated by the GUI for this type of logs will sort events based on the 046 * following attributes: <code>severity</code>, then <code>subsystem</code> then <code>message_id</code>. 047 * 048 * @see java.text.SimpleDateFormat 049 */ 050 public class WeblogicLogEvent 051 extends LogEvent 052 implements Comparable 053 { 054 public final static String ID = "weblogic"; 055 056 public final Date date; 057 058 public final String timestamp; 059 060 public final String severity; 061 062 public final String subsystem; 063 064 public final String machine; 065 066 public final String server; 067 068 public final String thread_id; 069 070 public final String transaction_id; 071 072 public final String user_id; 073 074 public final String message_id; 075 076 public final String message_text; 077 078 public final String stacktrace; 079 080 public final static LogType LOGTYPE = new WlLogType(); 081 082 private final static String LOGEVENT_START = "####<"; 083 084 private final static String[] ATTRIBUTE_NAMES = 085 { "logSource", "timestamp", "severity", "subsystem", "machine", "server", "thread_id", "transaction_id", 086 "user_id", "message_id", "message_text", "stacktrace" }; 087 088 public WeblogicLogEvent( Factory factory, String rawLog ) 089 throws ParseException 090 { 091 super( factory, rawLog ); 092 StringCutter cutter = new StringCutter( rawLog ); 093 cutter.parseTo( LOGEVENT_START ); 094 timestamp = cutter.parseTo( "> <" ); 095 date = factory.parseDate( timestamp ); 096 severity = cutter.parseTo( "> <" ); 097 subsystem = cutter.parseTo( "> <" ); 098 machine = cutter.parseTo( "> <" ); 099 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 }