net.sf.jacclog.service.analyzer.commands.internal.AnalyzeLogEntriesShellCommand.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jacclog.service.analyzer.commands.internal.AnalyzeLogEntriesShellCommand.java

Source

/*******************************************************************************
 * Copyright 2011 Andr Roul
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package net.sf.jacclog.service.analyzer.commands.internal;

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;

import net.sf.jacclog.api.LogEntryService;
import net.sf.jacclog.api.domain.ReadableLogEntry;
import net.sf.jacclog.api.domain.http.ReadableHttpRequestHeaderField;
import net.sf.jacclog.api.domain.http.ReadableHttpResponseHeaderField;
import net.sf.jacclog.service.analyzer.LogEntryAnalysisResult;
import net.sf.jacclog.service.analyzer.LogEntryAnalyzer;
import net.sf.jacclog.uasparser.UserAgentInfo;

import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.Option;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;

/**
 * Command to analyze log entries for a specific day or within a specified period.
 * 
 * <strong>Examples:</strong><br>
 * <code>analyze -f 2011-08-28</code> or<br>
 * <code>analyze -f 2011-08-28 -t 2011-08-30</code>
 * 
 * @author Andr Roul
 */
@Command(scope = "jacclog", name = "analyze", description = "Analyzes log entries of a specific day or within a specified period.")
@SuppressWarnings("PMD.SystemPrintln")
public class AnalyzeLogEntriesShellCommand extends OsgiCommandSupport {

    /**
     * Separator for the period formatter
     */
    private static final String SEPARATOR = " ";

    /**
     * Formatter to format the elapsed time (period) to import log entries
     */
    private static final PeriodFormatter FORMATTER = new PeriodFormatterBuilder().printZeroRarelyLast()
            .appendHours().appendSuffix("H").appendSeparator(SEPARATOR).appendMinutes().appendSuffix("m")
            .appendSeparator(SEPARATOR).appendSeconds().appendSuffix("s").appendSeparator(SEPARATOR).appendMillis()
            .appendSuffix("ms").toFormatter();

    /**
     * Requests an user input to proceed with the analysis.
     * 
     * @param count
     * @return
     */
    private static boolean proceed(final long count) {
        int inChar;
        System.out.println("Do you really want to analyze " + count + " log entries (y/n):");
        boolean result = false;
        try {
            inChar = System.in.read();
            if (inChar == 121 || inChar == 89) {
                result = true;
            }
        } catch (final IOException e) {
            System.out.println("Error reading an answer from user.");
        }
        return result;
    }

    private LogEntryService<ReadableLogEntry<ReadableHttpRequestHeaderField, ReadableHttpResponseHeaderField>> service;

    private LogEntryAnalyzer analyzerService;

    @Option(name = "-f", aliases = "--from", description = "The day to be analyzed or the start date of the interval.", required = true, multiValued = false)
    private final String from = null;

    @Option(name = "-t", aliases = "--to", description = "The end date of the interval. This option must be used in conjunction with option '-f'.", required = false, multiValued = false)
    private final String to = null;

    private void analyzeEntries() {
        if (service != null) {
            final DateTimeFormatter format = DateTimeFormat.forPattern("yyyyMMdd");
            final DateTime from = format.parseDateTime(this.from);
            final DateTime to = (this.to != null) ? format.parseDateTime(this.to) : from.plusDays(1);
            final Interval interval = new Interval(from, to);
            final Period period = interval.toPeriod();

            final StringBuffer buffer = new StringBuffer();
            buffer.append("Analyse the log entries from '");
            buffer.append(from.toString()).append('\'');
            buffer.append(" to '").append(to);

            // print the period
            final String space = " ";
            buffer.append("'. The period includes ");
            final PeriodFormatter dateFormat = new PeriodFormatterBuilder().appendYears()
                    .appendSuffix(" year", " years").appendSeparator(space).appendMonths()
                    .appendSuffix(" month", " months").appendSeparator(space).appendWeeks()
                    .appendSuffix(" week", " weeks").appendSeparator(space).appendDays()
                    .appendSuffix(" day", " days").appendSeparator(space).appendHours()
                    .appendSuffix(" hour", " hours").appendSeparator(space).appendMinutes()
                    .appendSuffix(" minute", " minutes").appendSeparator(space).toFormatter();
            dateFormat.printTo(buffer, period);
            buffer.append('.');

            System.out.println(buffer.toString());

            final long maxResults = service.count(interval);
            if (maxResults > 0) {
                int maxCount = 0;
                if (proceed(maxResults)) {
                    final long startTime = System.currentTimeMillis();

                    final LogEntryAnalysisResult result = analyzerService.analyze(interval).toResult();
                    final Map<UserAgentInfo, AtomicInteger> stats = result.getUserAgentInfos();
                    System.out.println("User agent information count: " + stats.size());

                    String name;
                    String osName;
                    int count;
                    for (final Entry<UserAgentInfo, AtomicInteger> entry : stats.entrySet()) {
                        name = entry.getKey().getName();
                        osName = entry.getKey().getOsName();
                        count = entry.getValue().get();
                        maxCount += count;
                        System.out.println(name + " (" + osName + ") \t" + count);
                    }
                    System.out.println("Sum: " + maxCount);

                    final long elapsedTime = System.currentTimeMillis() - startTime;
                    final Period p = new Period(elapsedTime);
                    System.out.println("Total processing time: " + p.toString(FORMATTER));
                }
            } else {
                System.out.println("There is nothing to analyze.");
            }
        }
    }

    @Override
    protected Object doExecute() throws Exception {
        if (service != null) {
            analyzeEntries();
        } else {
            log.warn("Can not analyze the log entries from '" + from + "' to '" + to + "'.");
        }

        return null;
    }

    public LogEntryAnalyzer getAnalyzerService() {
        return analyzerService;
    }

    public LogEntryService<ReadableLogEntry<ReadableHttpRequestHeaderField, ReadableHttpResponseHeaderField>> getRepositoryService() {
        return service;
    }

    public void setAnalyzerService(final LogEntryAnalyzer analyzerService) {
        this.analyzerService = analyzerService;
    }

    public void setRepositoryService(
            final LogEntryService<ReadableLogEntry<ReadableHttpRequestHeaderField, ReadableHttpResponseHeaderField>> service) {
        this.service = service;
    }

}