001package net.sf.logdistiller.reports;
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.IOException;
018import java.io.PrintWriter;
019import java.io.Writer;
020import java.text.DateFormat;
021import java.util.Date;
022
023import org.apache.commons.lang.StringUtils;
024import org.apache.commons.lang.SystemUtils;
025import org.jdom.Element;
026import org.jdom.output.Format;
027import org.jdom.output.XMLOutputter;
028
029import net.sf.logdistiller.LogDistillation;
030import net.sf.logdistiller.LogDistiller;
031import net.sf.logdistiller.ReportFormat;
032import net.sf.logdistiller.util.FormatUtil;
033
034/**
035 * Pure text report format.
036 */
037public class TextReport
038    extends ReportFormat
039{
040    private final static DateFormat DF = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.LONG );
041
042    public TextReport()
043    {
044        super( "txt" );
045    }
046
047    public String getContentType()
048    {
049        return "text/plain";
050    }
051
052    public String getFileExtension()
053    {
054        return "txt";
055    }
056
057    public void report( LogDistillation ld, Writer output )
058        throws IOException
059    {
060        LogDistiller definition = ld.getDefinition();
061        PrintWriter out = new PrintWriter( output ); // TODO configure encoding
062        out.println( "LogDistillation result (LogDistiller " + ld.getVersion() + ")" );
063        out.println();
064        out.println( "LogDistiller used: " + definition.getOutput().getId() + " - " + definition.getDescription() );
065        out.println( "log content processed: " + ( ( ld.getContent() == null ) ? "not specified" : ld.getContent() ) );
066        out.println( "distillation started on " + DF.format( new Date( ld.getBeginTime() ) ) + ", finished on "
067            + DF.format( new Date( ld.getEndTime() ) ) + ": "
068            + FormatUtil.formatPeriod( ld.getEndTime() - ld.getBeginTime() ) );
069        if ( ld.getSkippedEventCount() > 0 )
070        {
071            out.println( "skipped " + ld.getSkippedEventCount() + " events ("
072                + FormatUtil.formatSize( ld.getSkippedEventBytes() ) + ")" );
073        }
074        String logsUrl = definition.getOutput().getUrl();
075        if ( logsUrl != null )
076        {
077            out.println( "reports and logs url: " + logsUrl );
078        }
079        for ( String warning : definition.getWarnings() )
080        {
081            out.println( "WARNING: " + warning );
082        }
083        out.println();
084        if ( ld.getEventCount() == 0 )
085        {
086            out.println( "found 0 event to classify." );
087        }
088        else
089        {
090            out.println( "found " + ld.getEventCount() + " events (" + FormatUtil.formatSize( ld.getEventBytes() )
091                + ") classified as follow:" );
092            // report for categories, and corresponding groups
093            for ( LogDistillation.Category category : ld.listCategoriesToReport() )
094            {
095                int categoryEventCount = category.sumEventCount();
096                LogDistiller.Category categoryDefinition = category.getDefinition();
097                out.println( "*** " + categoryEventCount + " " + categoryDefinition.getId() + " ("
098                    + FormatUtil.formatFraction( categoryEventCount, ld.getEventCount() ) + "): "
099                    + categoryDefinition.getDescription() );
100                int countLength = String.valueOf( categoryEventCount ).length();
101
102                for ( LogDistillation.Group group : category.listGroupsToReport() )
103                {
104                    String fraction = formatFraction( group.getEventCount(), categoryEventCount );
105                    out.println( "*" + fraction + ' ' + formatGroup( group, countLength, ld.getEventCount() ) );
106                    addPluginsGlobalReport( group, new TextPluginReport( out, "*       ", group.getEventCount() ) );
107                }
108
109                out.println();
110            }
111
112            // report for groups without category
113            int countLength = String.valueOf( ld.getEventCount() ).length();
114            for ( LogDistillation.Group group : ld.listGroupsToReport() )
115            {
116                out.println( formatGroup( group, countLength, ld.getEventCount() ) );
117                addPluginsGlobalReport( group, new TextPluginReport( out, "   ", group.getEventCount() ) );
118            }
119        }
120        out.flush();
121    }
122
123    private String formatGroup( LogDistillation.Group group, int countLength, int eventCount )
124    {
125        int groupEventCount = group.getEventCount();
126        LogDistiller.Group groupDefinition = group.getDefinition();
127        String sep = groupDefinition.continueProcessing() ? "+ " : "- ";
128        return sep + StringUtils.leftPad( String.valueOf( groupEventCount ), countLength ) + " ("
129            + formatFraction( groupEventCount, eventCount ) + ") " + groupDefinition.getId() + ": "
130            + groupDefinition.getDescription();
131    }
132
133    private String formatFraction( long fraction, long total )
134    {
135        return StringUtils.leftPad( FormatUtil.formatFraction( fraction, total ), 6 );
136    }
137
138    public void report( LogDistillation.Group group, Writer output )
139        throws IOException
140    {
141        LogDistiller.Group definition = group.getDefinition();
142        PrintWriter out = new PrintWriter( output );
143        out.println( "LogDistillation group result (LogDistiller " + LogDistiller.getVersion() + ")" );
144        out.println();
145        out.println( "LogDistiller group: " + definition.getId() + " - " + definition.getDescription() );
146        out.println( "for LogDistiller: " + definition.getLogdistiller().getOutput().getId() + " - "
147            + definition.getLogdistiller().getDescription() );
148        out.println( "log content processed: "
149            + ( ( group.getLogdistillation().getContent() == null ) ? "not specified"
150                            : group.getLogdistillation().getContent() ) );
151        out.println( "found " + group.getEventCount() + " events (" + FormatUtil.formatSize( group.getBytes() )
152            + ") matching following definition:" );
153        Element elmt = new Element( "conditions" );
154        definition.dumpConditions( elmt );
155        if ( elmt.getContentSize() > 0 )
156        {
157            out.print( "  " );
158            new XMLOutputter( Format.getPrettyFormat().setLineSeparator( SystemUtils.LINE_SEPARATOR + "  " ) ).outputElementContent(
159                                                                                                                                     elmt,
160                                                                                                                                     output );
161            out.println();
162        }
163        else
164        {
165            out.println( "  no condition specified: every log event accepted" );
166        }
167
168        String logsUrl = definition.getLogdistiller().getOutput().getUrl();
169        if ( definition.getSave() )
170        {
171            out.println( "log events saved in file: " + group.getLogFile().getAbsolutePath() );
172            out.print( "max save count: " );
173            if ( group.getMaxSaveCount() < 0 )
174            {
175                out.println( "none" );
176            }
177            else
178            {
179                out.println( String.valueOf( group.getMaxSaveCount() ) );
180            }
181            out.print( "max save size: " );
182            if ( group.getMaxSaveBytes() < 0 )
183            {
184                out.println( "none" );
185            }
186            else
187            {
188                out.println( String.valueOf( group.getMaxSaveBytes() / 1024 ) + " kb" );
189            }
190            if ( group.getSavedEventCount() < group.getEventCount() )
191            {
192                out.println( "save limit reached: " + group.getSavedEventCount() + " events" );
193            }
194            if ( logsUrl != null )
195            {
196                out.println( "log events url: "
197                    + definition.getLogdistiller().getOutput().getUrl( group.getLogFile().getName() ) );
198            }
199        }
200        else
201        {
202            out.println( "log events not saved" );
203        }
204        if ( logsUrl != null )
205        {
206            out.println( "reports and logs url: " + logsUrl );
207        }
208        if ( definition.continueProcessing() )
209        {
210            out.println( "continueProcessing: true" );
211        }
212        out.println();
213        addPluginsGroupReport( group, new TextPluginReport( out, "", group.getEventCount() ) );
214        out.flush();
215    }
216
217    private static class TextPluginReport
218        extends PluginReport
219    {
220        private final PrintWriter out;
221
222        private final String prefix;
223
224        private final int groupEventCount;
225
226        private final int countLength;
227
228        public TextPluginReport( PrintWriter out, String prefix, int groupEventCount )
229        {
230            this.out = out;
231            this.prefix = prefix;
232            this.groupEventCount = groupEventCount;
233            countLength = String.valueOf( groupEventCount ).length();
234        }
235
236        public void beginPluginReport( LogDistillation.Plugin plugin, String description )
237        {
238            out.println( prefix + plugin.getDefinition().getType() + ": " + description );
239        }
240
241        public void addLink( String filename, String description )
242        {
243            out.println( prefix + "file " + filename + ": " + description );
244        }
245
246        public void addParam( String param, String value )
247        {
248            out.println( prefix + param + ": " + value );
249        }
250
251        public void addItem( int count, String description )
252        {
253            out.println( prefix + "  # " + StringUtils.leftPad( String.valueOf( count ), countLength ) + " ("
254                + StringUtils.leftPad( FormatUtil.formatFraction( count, groupEventCount ), 6 ) + ") " + description );
255        }
256
257        public void endPluginReport()
258        {
259            out.println( prefix.trim() );
260        }
261    }
262}