📄 loganalyser.java
字号:
/** * using the pre-configuration information passed here, analyse the logs * and produce the aggregation file * * @param context the DSpace context object this occurs under * @param myLogDir the passed log directory. Uses default if null * @param myFileTemplate the passed file name regex. Uses default if null * @param myConfigFile the DStat config file. Uses default if null * @param myOutFile the file to which to output aggregation data. Uses default if null * @param myStartDate the desired start of the analysis. Starts from the beginning otherwise * @param myEndDate the desired end of the analysis. Goes to the end otherwise * @param myLookUp force a lookup of the database */ public static void processLogs(Context context, String myLogDir, String myFileTemplate, String myConfigFile, String myOutFile, Date myStartDate, Date myEndDate, boolean myLookUp) throws IOException, SQLException { // FIXME: perhaps we should have all parameters and aggregators put // together in a single aggregating object // if the timer has not yet been started, then start it if (startTime != null) { startTime = new GregorianCalendar(); } // set the parameters for this analysis setParameters(myLogDir, myFileTemplate, myConfigFile, myOutFile, myStartDate, myEndDate, myLookUp); // pre prepare our standard file readers and buffered readers FileReader fr = null; BufferedReader br = null; // read in the config information, throwing an error if we fail to open // the given config file readConfig(configFile); // assemble the regular expressions for later use (requires the file // template to build the regex to match it setRegex(fileTemplate); // get the log files File[] logFiles = getLogFiles(logDir); // standard loop counter int i = 0; // for every log file do analysis // FIXME: it is easy to implement not processing log files after the // dates exceed the end boundary, but is there an easy way to do it // for the start of the file? Note that we can assume that the contents // of the log file are sequential, but can we assume the files are // provided in a data sequence? for (i = 0; i < logFiles.length; i++) { // check to see if this file is a log file agains the global regex Matcher matchRegex = logRegex.matcher(logFiles[i].getName()); if (matchRegex.matches()) { // if it is a log file, open it up and lets have a look at the // contents. try { fr = new FileReader(logFiles[i].toString()); br = new BufferedReader(fr); } catch (IOException e) { System.out.println("Failed to read log file " + logFiles[i].toString()); System.exit(0); } // for each line in the file do the analysis // FIXME: perhaps each section needs to be dolled out to an // analysing class to allow pluggability of other methods of // analysis, and ease of code reading too - Pending further thought String line = null; while ((line = br.readLine()) != null) { // get the log line object LogLine logLine = getLogLine(line); // if there are line segments get on with the analysis if (logLine != null) { // first find out if we are constraining by date and // if so apply the restrictions if (logLine.beforeDate(startDate)) { continue; } if (logLine.afterDate(endDate)) { break; } // count the number of lines parsed lineCount++; // if we are not constrained by date, register the date // as the start/end date if it is the earliest/latest so far // FIXME: this should probably have a method of its own if (startDate == null) { if (logStartDate != null) { if (logLine.beforeDate(logStartDate)) { logStartDate = logLine.getDate(); } } else { logStartDate = logLine.getDate(); } } if (endDate == null) { if (logEndDate != null) { if (logLine.afterDate(logEndDate)) { logEndDate = logLine.getDate(); } } else { logEndDate = logLine.getDate(); } } // count the warnings if (logLine.isLevel("WARN")) { // FIXME: really, this ought to be some kind of level // aggregator warnCount++; } // is the action a search? if (logLine.isAction("search")) { // get back all the valid search words from the query String[] words = analyseQuery(logLine.getParams()); // for each search word add to the aggregator or // increment the aggregator's counter for (int j = 0; j < words.length; j++) { // FIXME: perhaps aggregators ought to be objects // themselves searchAggregator.put(words[j], increment(searchAggregator, words[j])); } } // is the action a login, and are we counting user logins? if (logLine.isAction("login") && !userEmail.equals("off")) { userAggregator.put(logLine.getUser(), increment(userAggregator, logLine.getUser())); } // is the action an item view? if (logLine.isAction("view_item")) { String handle = logLine.getParams(); // strip the handle string Matcher matchHandle = handleRX.matcher(handle); handle = matchHandle.replaceAll(""); // strip the item id string Matcher matchItem = itemRX.matcher(handle); handle = matchItem.replaceAll(""); handle.trim(); // either add the handle to the aggregator or // increment its counter itemAggregator.put(handle, increment(itemAggregator, handle)); } // log all the activity actionAggregator.put(logLine.getAction(), increment(actionAggregator, logLine.getAction())); } } // close the file reading buffers br.close(); fr.close(); } } // do we want to do a database lookup? Do so only if the start and // end dates are null or lookUp is true // FIXME: this is a kind of separate section. Would it be worth building // the summary string separately and then inserting it into the real // summary later? Especially if we make the archive analysis more complex archiveStats.put("All Items", getNumItems(context)); for (i = 0; i < itemTypes.size(); i++) { archiveStats.put(itemTypes.get(i), getNumItems(context, (String) itemTypes.get(i))); } // now do the host lookup try { InetAddress addr = InetAddress.getLocalHost(); hostName = addr.getHostName(); } catch (UnknownHostException e) { hostName = "unknown host"; } // do the average views analysis if (((Integer) archiveStats.get("All Items")).intValue() != 0) { // FIXME: this is dependent on their being a query on the db, which // there might not always be if it becomes configurable Double avg = new Double( Math.ceil( ((Integer) actionAggregator.get("view_item")).intValue() / ((Integer) archiveStats.get("All Items")).intValue())); views = avg.intValue(); } // finally, write the output createOutput(); return; } /** * set the passed parameters up as global class variables. This has to * be done in a separate method because the API permits for running from * the command line with args or calling the processLogs method statically * from elsewhere * * @param myLogDir the log file directory to be analysed * @param myFileTemplate regex for log file names * @param myConfigFile config file to use for dstat * @param myOutFile file to write the aggregation into * @param myStartDate requested log reporting start date * @param myEndDate requested log reporting end date * @param myLookUp requested look up force flag */ public static void setParameters(String myLogDir, String myFileTemplate, String myConfigFile, String myOutFile, Date myStartDate, Date myEndDate, boolean myLookUp) { if (myLogDir != null) { logDir = myLogDir; } if (myFileTemplate != null) { fileTemplate = myFileTemplate; } if (myConfigFile != null) { configFile = myConfigFile; } if (myStartDate != null) { startDate = myStartDate; } if (myEndDate != null) { endDate = myEndDate; } if (myLogDir != null) { lookUp = myLookUp; } if (myOutFile != null) { outFile = myOutFile; } return; } /** * generate the analyser's output to the specified out file */ public static void createOutput() { // start a string buffer to hold the final output StringBuffer summary = new StringBuffer(); // define an iterator that will be used to go over the hashmap keys Iterator keys = null; // output the number of lines parsed summary.append("log_lines=" + Integer.toString(lineCount) + "\n"); // output the number of warnings encountered summary.append("warnings=" + Integer.toString(warnCount) + "\n"); // set the general summary config up in the aggregator file for (int i = 0; i < generalSummary.size(); i++) { summary.append("general_summary=" + generalSummary.get(i) + "\n"); } // output the host name summary.append("server_name=" + hostName + "\n"); // output the service name summary.append("service_name=" + name + "\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -