I recently delivered a training where users needed to learn their system for functional maintenance. There always is a vague boundary where functional ends, and where technical starts. Log files do provide good clue’s what a problem can be. But then you need to contact a tech-guy and get a zip with all kind of stuff, taking too long. Web based would be so easy…
In this post you will find a Log Browser based on Alfresco Explorer. A JSP file you can include in the jsp/admin folder of your %Tomcat%/webapps/alfresco. Usually you will find your alfresco.log’s in the ALF_HOME, I happen to have some Alfresco’s running as Windows service, and they log into %Tomcat%/logs.
Features:
- The script is quite configurable. You can play with the required number of columns, influencing the number of items in a column.
- The script has highlighting if a number of words occurs in a line in the logfile. Configure the words, and the highlight color.
- Configure if you want the logs in Tomcat/logs as well, or leave them out.
<%--
*
* This file is NOT part of Alfresco, and comes with no warrenty
* This scipt will show all logs in ALF_HOME and CATALINA_HOME (that are > 1kb)
*
--%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
<%@ page import="java.lang.String" %>
<%@ page import="java.lang.Integer" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.Enumeration" %>
<%@ page import="java.util.Properties" %>
<%@ page import="java.io.BufferedReader" %>
<%@ page import="java.io.File" %>
<%@ page import="java.io.FileReader" %>
<r:page title="Alfresco Log Browser">
<f:view>
<%-- load a bundle of properties with I18N strings --%>
<r:loadBundle var="msg"/>
<h:form id="log-console-title">
<table width="100%">
<tr>
<td>
<h:graphicImage value="/images/logo/AlfrescoLogo32.png" alt="Alfresco" />
</td>
<td>
<nobr><span class="mainTitle">Alfresco Log Browser</span></nobr>
</td>
<td width="100%" align="right">
<h:commandButton value="#{msg.close}" action="adminConsole" />
</td>
</tr>
</table>
</h:form>
<br>
<span class="mainTitle">List of Alfresco + Tomcat Logs</span>
<p/>
<%
int max0=10; // number of items per column
int max1=15; // increasing per step
int max2=20;
int max3=30;
int max=0; // determined max number of items in a column
int cols=7; // preferred max number of columns in the table. decrease depending on screen size
int count=0; // counter to determine if a new table column needs to start
int counta=0; // counter of Alfresco logs >0Kb
int countt=0; // counter of Tomcat logs >0Kb
String[] wordlist="ERROR,SEVERE,Exception ,aused by:".split(","); // list of words, if exist, highlight this line in the log
String highlightColor="red"; // will be used to highlight line containing any of the wordlist tokens. Used in <font color=...>
String noLogToDisplay="There is no log to display.";
boolean includeTomcat = true; //
// ************************************
// no configuration foreseen below here
// ************************************
String file="";
String alf_home = System.getProperty("catalina.base") + File.separator + ".."; // Get ALF_HOME
String tomcat_home = System.getProperty("catalina.base") + File.separator + "logs"; // Get CATALINA_HOME
File[] dirt = new File[0];
File[] dira = ((File)(new File(alf_home))).listFiles();
// count the number of items to print (only items >1Kb
for( int ii=0 ; ii< dira.length ; ii++){
if (dira[ii].length()/1024>0){ counta++;}
}
if (includeTomcat){
// count the number of items to print (only items >1Kb
dirt = ((File)(new File(tomcat_home))).listFiles();
for( int ii=0 ; ii< dirt.length ; ii++){
if (dirt[ii].length()/1024>0){ countt++;}
}
} else {
countt=0;
}
// Determine how many rows in a column
if ((counta+countt)<(cols*max0)) {max=max0;} else
if ((counta+countt)<(cols*max1)) {max=max1;} else
if ((counta+countt)<(cols*max2)) {max=max2;} else {max=max3;}
%>
<style type="text/css">
<!--
div.scroll {
height: <%=Math.min(15*max, 255)%>px;
width: 95%;
overflow: auto;
border: 1px solid #666;
padding: 0px;
}
-->
</style>
<div class="scroll">
<table>
<tr><td valign="top">
<%
// First, display all Alfresco logs. Create a new column if there are more than %max% rows
Arrays.sort( dira );
for( int ii=0 ; ii< dira.length ; ii++){
if (dira[ii].isFile() && dira[ii].length()/1024>0 && dira[ii].getName().indexOf(".log")>1){
file = dira[ii].getName(); // get the filename
count++; // count how many lines we print in a column
%>
<a href=?count=<%=ii%>&type=a><%=file%></a> (<%=dira[ii].length()/1024%>Kb)<br/>
<%
// find out if we need to create a new column, of just add a 'row'
if (count==max){
count=0;
%></td><td valign="top"><%
} // end if count=max
} // end if
} // end for
%>
</td><td valign="top">
<%
if (includeTomcat){
// Second, display all Tomcat logs. Create a new column if there are more than %max% rows
count=0;
Arrays.sort( dirt ) ;
for( int jj=0 ; jj< dirt.length ; jj++){
if (dirt[jj].isFile() && dirt[jj].length()/1024>0 && dirt[jj].getName().indexOf(".log")>1){
file = dirt[jj].getName() ; // get the filename
count++; // count how many lines we print in a column
%>
<a href=?count=<%=jj%>&type=t><%=file%></a>(<%=dirt[jj].length()/1024%>Kb) <br/>
<%
// find out if we need to create a new column, of just add a 'row'
if (count==max){
count=0;
%></td><td valign="top"><%
} // end if count=max
} // end if
} // end for
} // end if includeTomcat
%>
</td></tr></table>
</div>
<br/>
<%
File log=new File("");
boolean go = false;
String type = request.getParameter("type");
// if appropriate, get the Alfresco log file
if (type!=null && type.equals("a") && request.getParameter("count")!=null){
log=dira[Integer.parseInt(request.getParameter("count"))];
go=true;
}
if (includeTomcat){
// if appropriate, get the Tomcat log file
if (type!=null && type.equals("t") && request.getParameter("count")!=null){
log=dirt[Integer.parseInt(request.getParameter("count"))];
go=true;
}
} // end if includeTomcat
if (go){ // only if there -is- a logfile, otherwise, don't display any
try{
%>
<span class="mainTitle">Logfile: <%=log.getName()%></span>
<small><pre>
<%
String thisLine="";
boolean highlight=false;
BufferedReader br = new BufferedReader(new FileReader(log));
while ((thisLine = br.readLine()) != null) { // while loop begins here
if (thisLine.trim().length()>=0)
for (int i=0;i<wordlist.length;i++){
if (thisLine.indexOf(wordlist[i])>0) highlight=true;
}
if (highlight){
%><font color="<%=highlightColor%>"><%
}
%><%=thisLine%><br> <%
if (highlight){
%></font><%
}
highlight=false;
} // end while
br.close();
} catch (Exception e)
{} finally {}
} else {
// What do we display if there is no log to show (e.g. only the contents of the folders, no log selected
%>
<%=noLogToDisplay%>
<%
}
%>
</pre></small>
</f:view>
</r:page>
[update 20110527: added syntax highlighting]


Have you looked at log4mongo (http://log4mongo.org/display/PUB/Home)? It enables any log4j based application (including Alfresco) to log to the MongoDB document database, thereby allowing the log data to be sliced, diced and presented all sorts of different ways.
The log4mongo project had originally intended to include a neat log slicing / dicing / presentation tool (ala the venerable Chainsaw tool), but the recent focus has been on extending the library to support other logging libraries in other languages.