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    }