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.ParseException;
019
020 import net.sf.logdistiller.LogEvent;
021 import net.sf.logdistiller.LogType;
022 import net.sf.logdistiller.util.StringCutter;
023
024 /**
025 * Log event for Unix syslog facility. By default, the classification rules generated by the GUI for this type of logs
026 * will sort events based on the following attributes: <code>host</code>, then <code>program</code>.
027 */
028 public class SyslogLogEvent
029 extends LogEvent
030 {
031 public final static String ID = "syslog";
032
033 // see http://logreport.org/doc/gen/os/
034 public final String timestamp;
035
036 public final String host;
037
038 public final String program;
039
040 public final String pid;
041
042 public final String message;
043
044 public final static LogType LOGTYPE = new LogType.Basic( ID );
045
046 private final static String[] ATTRIBUTE_NAMES = { "logSource", "timestamp", "host", "program", "pid", "message" };
047
048 public final static LogType.Description DESCRIPTION = new Description( (LogType.Basic) LOGTYPE, ATTRIBUTE_NAMES );
049
050 public SyslogLogEvent( Factory factory, String rawLog )
051 throws ParseException
052 {
053 super( factory, rawLog );
054 timestamp = rawLog.substring( 0, 15 );
055 StringCutter sc = new StringCutter( rawLog, 16 );
056 host = sc.parseTo( " " );
057 String remaining = sc.getRemaining();
058 if ( remaining.indexOf( ": " ) < 0 )
059 {
060 program = "";
061 pid = "";
062 message = remaining;
063 }
064 else
065 {
066 // <program>[<pid>]: <message>
067 String programPid = sc.parseTo( ": " );
068 message = sc.getRemaining();
069
070 int index = programPid.indexOf( '[' );
071 if ( ( index >= 0 ) && programPid.endsWith( "]" ) )
072 {
073 program = programPid.substring( 0, index );
074 pid = programPid.substring( index + 1, programPid.length() - 1 );
075 }
076 else
077 {
078 program = programPid;
079 pid = "";
080 }
081 }
082 setAttributes( new String[] { factory.getLogSource(), timestamp, host, program, pid, message } );
083 }
084
085 private static class Description
086 extends LogType.Description
087 {
088 public Description( LogType.Basic logtype, String[] attributeNames )
089 {
090 super( logtype, attributeNames );
091 logtype.setDescription( this );
092 }
093
094 public LogEvent.Factory newFactory( Reader reader, String logSource )
095 throws IOException
096 {
097 return new Factory( this, reader, logSource );
098 }
099
100 public String getDefaultSamplingAttributes()
101 {
102 return "host,program";
103 }
104 }
105
106 private static class Factory
107 extends LogEvent.Factory
108 {
109 private final LineNumberReader reader;
110
111 public Factory( Description description, Reader reader, String logSource )
112 throws FileNotFoundException
113 {
114 super( description, logSource );
115 this.reader = new LineNumberReader( reader );
116 }
117
118 protected LogEvent readNextEvent()
119 throws IOException, ParseException
120 {
121 String curLine = reader.readLine();
122 if ( curLine == null )
123 {
124 // EOF
125 return null;
126 }
127 try
128 {
129 return new SyslogLogEvent( this, curLine );
130 }
131 catch ( RuntimeException re )
132 {
133 throw new RuntimeException( "error while parsing line '" + curLine + "'", re );
134 }
135 }
136 }
137 }