001    package hirondelle.web4jtools.logview.stats;
002    
003    import hirondelle.web4j.action.ActionTemplateSearch;
004    import hirondelle.web4j.action.ResponsePage;
005    import hirondelle.web4j.model.AppException;
006    import hirondelle.web4j.request.RequestParameter;
007    import hirondelle.web4j.request.RequestParser;
008    import hirondelle.web4jtools.logview.parsedview.LoggerRecord;
009    import hirondelle.web4jtools.logview.parsedview.ParsedCriteria;
010    import hirondelle.web4jtools.logview.simpleview.LogFileDAO;
011    
012    import java.io.File;
013    import java.util.ArrayList;
014    import java.util.Date;
015    import java.util.List;
016    import java.util.logging.Level;
017    
018    /**
019    * List stats for a log file, including a histogram of relative frequency of levels. 
020    */
021    public final class LogStatsAction extends ActionTemplateSearch {
022    
023      public LogStatsAction(RequestParser aRequestParser){
024        super(FORWARD, aRequestParser);
025      }
026      
027      public static final RequestParameter LOG_FOR = RequestParameter.withRegexCheck("Log For", "(Application|Server)");
028      
029      /** Ensure user input can build a {@link ParsedCriteria}. */
030      @Override protected void validateUserInput() throws AppException {
031        //under normal operation, no chance of faulty user input - a single radio button, 
032        //with a default selection
033        fCriteria = ParsedCriteria.forStats(getParamUnsafe(LOG_FOR));
034      }
035      
036      /** Show stats and histogram.  */
037      @Override protected void listSearchResults() throws AppException {
038        LogFileDAO dao = new LogFileDAO(getRequestParser().getRequest());
039        File mostRecentLog = dao.getMostRecentLogFile(fCriteria.getLogFor());
040        if ( mostRecentLog != null  ) {
041          addToRequest("mostRecentLog", mostRecentLog);
042          addToRequest("mostRecentLogDate", new Date(mostRecentLog.lastModified()));
043          addToRequest("mostRecentLogSize", mostRecentLog.length());
044          
045          List<LoggerRecord> logRecords = dao.getParsedLogFile(mostRecentLog, fCriteria);
046          addToRequest("totalRecords", logRecords.size());
047          addToRequest("firstRecordDate", logRecords.get(0).getDate() );
048          addToRequest("lastRecordDate", logRecords.get(logRecords.size()-1).getDate());
049          calcHistogramBuckets(logRecords);
050          addToRequest("buckets", fBuckets);
051        }
052        else {
053          addError("No files detected in logging directory.");
054        }
055      }
056      
057      // PRIVATE //
058      private ParsedCriteria fCriteria;
059      private List<LevelBucket> fBuckets = new ArrayList<LevelBucket>();
060      private static final ResponsePage FORWARD = new ResponsePage("Log Stats", "view.jsp", LogStatsAction.class);
061      
062      private void calcHistogramBuckets(List<LoggerRecord> aRecords) {
063        buildLevelBuckets();
064        for(LoggerRecord record : aRecords){
065          addToAppropriateBucket(record);
066        }
067      }
068      
069      private void buildLevelBuckets() {
070        addBucketFor(Level.SEVERE);
071        addBucketFor(Level.WARNING);
072        addBucketFor(Level.INFO);
073        addBucketFor(Level.CONFIG);
074        addBucketFor(Level.FINE);
075        addBucketFor(Level.FINER);
076        addBucketFor(Level.FINEST);
077      }
078      
079      private void addBucketFor(Level aLevel) {
080        fBuckets.add(new LevelBucket(aLevel));
081      }
082      
083      private void addToAppropriateBucket(LoggerRecord aRecord){
084        for (LevelBucket bucket : fBuckets){
085          if ( aRecord.getLevel().equals(bucket.getLevel()) ) {
086            bucket.incrementCount();
087          }
088        }
089      }
090    }
091