/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
* <p>
*/
package org.olat.core.logging;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import org.olat.core.util.Formatter;
import org.olat.core.util.StringHelper;
import org.olat.core.util.vfs.LocalFileImpl;
import org.olat.core.util.vfs.VFSLeaf;
/**
* Description: logfile handling
*
* @author Sabina Jeger
*/
public class LogFileParser extends LogDelegator {
private static String logfilepathBase;
private static String filename;
private static final int linecount = 3; // we always get 4 lines
private static final String matchError = ".*" + Tracing.PREFIX + Tracing.ERROR + ".*";
private static final String matchWarn = ".*" + Tracing.PREFIX + Tracing.WARN + ".*" ;
private static OLog log;
/**
* [spring]
*/
private LogFileParser(String logdir, String file) {
if (StringHelper.containsNonWhitespace(file)) {
filename = file;
} else {
filename = "olat.log";
}
if (StringHelper.containsNonWhitespace(logdir)) {
if (logdir.endsWith(File.separator)) {
logfilepathBase = logdir + filename;
} else {
logfilepathBase = logdir + File.separator + filename;
}
} else {
logfilepathBase = System.getProperty("java.io.tmpdir") + File.separator + "logs" + File.separator + filename;
}
log = getLogger();
}
/**
* @param date the date of the log to retrieve, or null when no date suffix should be appended (= take today's log)
* @return the VFSLeaf of the Logfile given the Date, or null if no such file could be found
*/
public static VFSLeaf getLogfilePath(Date date) {
String tmpFileName = logfilepathBase;
if (date != null) {
SimpleDateFormat sdb = new SimpleDateFormat("yyyy-MM-dd");
String suffix = sdb.format(date);
String today = sdb.format(new Date());
if(suffix.equals(today))
tmpFileName = logfilepathBase;
else
tmpFileName = logfilepathBase + "."+suffix;
}
File logf = new File(tmpFileName);
if (!logf.exists()) return null;
return new LocalFileImpl(logf);
}
/**
* extracts the errormessage from a line in the logfile and formats it for the
* html
*
* @param s
* @return errormsg
*/
private static String extractErrorAsHTML(String s[]) {
StringBuilder sb = new StringBuilder();
if (s.length == 6) {
// before refactoring of logging.Tracing
sb.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">");
sb.append("<tr><td valign=\"top\"><b>Date </b></td><td>" + Formatter.truncate(s[0].trim(), 20) + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Error# </td><td><font color=\"red\"><b>" + s[1].trim() + "</font></td></tr>");
sb.append("<tr><td valign=\"top\"><b>Identity </b></td><td>" + s[3].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Category/Class </b></td><td>" + s[2].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Log msg </b></td><td>" + s[4].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Cause </b></td><td>"
+ s[5].trim().replaceAll(" at ", "<br />at ").replaceAll(">>>", "<br /><br />>>>") + "</td></tr>");
sb.append("</table>");
} else if (s.length == 9) {
// the new Tracing
sb.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">");
sb.append("<tr><td valign=\"top\"><b>Date </b></td><td>" + Formatter.truncate(s[0].trim(), 20) + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Error# </td><td><font color=\"red\"><b>" + s[1].trim() + "</font></td></tr>");
sb.append("<tr><td valign=\"top\"><b>Identity </b></td><td>" + s[3].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Category/Class </b></td><td>" + s[2].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Remote IP </b></td><td>" + s[4].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Referer </b></td><td>" + s[5].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>User-Agent </b></td><td>" + s[6].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Log msg </b></td><td>" + s[7].trim() + "</td></tr>");
sb.append("<tr><td valign=\"top\"><b>Cause </b></td><td>"
+ s[8].trim().replaceAll(" at ", "<br />at ").replaceAll(">>>", "<br /><br />>>>") + "</td></tr>");
sb.append("</table>");
} else {
throw new AssertException("Unknown Logfile format");
}
return sb.toString();
}
/**
* extracts the errormessage from a line in the logfile and formats it as text
*
* @param s
* @return errormsg
*/
private static String extractError(String s[]) {
StringBuilder sb = new StringBuilder();
if (s.length == 6) {
// before refactoring of logging.Tracing
sb.append("Date: " + Formatter.truncate(s[0].trim(), 20) + "\n");
sb.append("Error#: " + s[1].trim() + "\n");
sb.append("Identity: " + s[3].trim() + "\n");
sb.append("Category/Class: " + s[2].trim() + "\n");
sb.append("Log msg: " + s[4].trim() + "\n");
sb.append("Cause: "
+ s[5].trim().replaceAll(" at ", "\nat ").replaceAll(">>>", "\n>>>") + "\n");
} else if (s.length == 9) {
// the new Tracing
sb.append("Date: " + Formatter.truncate(s[0].trim(), 20) + "\n");
sb.append("Error#: " + s[1].trim() + "\n");
sb.append("Identity: " + s[3].trim() + "\n");
sb.append("Category/Class: " + s[2].trim() + "\n");
sb.append("Remote IP: " + s[4].trim() + "\n");
sb.append("Referer: " + s[5].trim() + "\n");
sb.append("User-Agent: " + s[6].trim() + "\n");
sb.append("Log msg: " + s[7].trim() + "\n");
sb.append("Cause: "
+ s[8].trim().replaceAll(" at ", "\nat ").replaceAll(">>>", "\n\n"));
} else {
throw new AssertException("Unknown Logfile format");
}
return sb.toString();
}
/**
*
* @param errorNumber
* @param dd
* @param mm
* @param yyyy
* @param asHTML
* @return
*/
public static Collection<String> getErrorToday(String errorNumber, boolean asHTML) {
return getError(errorNumber, null, asHTML);
}
/**
* looks through the logfile
*
* @param s
* @param dd requested day
* @param mm requested month
* @param yyyy requested yyyy
* @return the first found errormessage
*/
public static Collection<String> getError(String errorNumber, Date date, boolean asHTML) {
if (logfilepathBase == null) {
//this is null when olat is setup with an empty olat.local.properties file and no log.dir path is set.
return Collections.emptyList();
}
String line;
String line2;
String memoryline = "empty";
String em[] = new String[10];
Collection<String> errormsg = new ArrayList<String>();
SimpleDateFormat sdb = new SimpleDateFormat("yyyy-MM-dd");
String logfilepath;
if(date == null) {
logfilepath = logfilepathBase;
} else {
String today = sdb.format(new Date());
String reqdate = sdb.format(date);
if (today.equals(reqdate)) {
logfilepath = logfilepathBase;
} else {
logfilepath = logfilepathBase + "." + reqdate;
}
log.info("logfilepath changed to " + logfilepath + " (today: " + today + ", requested date:" + reqdate + ")");
}
int counter = linecount;
int founderror = 0;
final File logFile = new File(logfilepath);
if(!logFile.exists() || !logFile.canRead()){
errormsg.add("logfile <b>"+logfilepath+"</b> does not exist or unable to read from");
return errormsg;
}
try {
BufferedReader br = new BufferedReader(new FileReader(logFile));
while ((line = br.readLine()) != null) {
if (counter == 0) {
errormsg.add(line);
counter = linecount;
} else if (counter == 1) {
errormsg.add(line);
counter--;
} else if ( line.matches(matchError) || line.matches(matchWarn) ) {
line2 = line.replaceAll("[/^]", "/");
em = line2.split("/%/");
if (errorNumber.equals(em[1].trim())) {
founderror++;
if (asHTML) {
line2 = extractErrorAsHTML(em);
} else {
line2 = extractError(em);
}
errormsg.add(memoryline);
counter--;
errormsg.add(line2);
counter--;
}
}
memoryline = line;
}
br.close();
if (founderror > 0) {
if (counter < linecount) {
while (counter > 0) {
errormsg.add("empty");
counter--;
}
}
}
if (founderror == 0){
errormsg.add("no error with number "+errorNumber+" found in "+logfilepath);
}
return errormsg;
} catch (IOException e) {
throw new OLATRuntimeException("error reading OLAT error log at " + logfilepath, e);
}
}
}