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