For this reason we manage our Log4j appenders @ runtime wherein we can add new appenders and change priority levels of existing appenders @ runtime. Once the stacktrace or the required log is gathered, the priority levels can be reverted back to the non-voluminous/required levels.
We have a Log4j administration page in our application which can only be accessed by super ninjas a.k.a developers. This page can be used to change/add appenders at runtime. The page has sections to add new appenders and change priority levels of existing appenders.
To start with we display all the current appenders with their current priority levels. This can be achieved using the code below (for simplicity sake I am :
// collect all current appenders
List appenders = new ArrayList(50);
Enumeration e = LogManager.getCurrentLoggers();
while ( e.hasMoreElements() )
{
appenders.add(e.nextElement());
}
request.setAttribute("appenders",appenders);
// all possible priority levels
Priority [] prios = Priority.getAllPossiblePriorities();
request.setAtrribute("possiblePriorities", prios);
In the JSP page you can use a simple JSTL tag to display the above collected information in a tabular format.
<%@ page import="java.util.*,org.apache.log4j.*"
....
....
<table>
<tr>
<td> Appender </td>
<c:forEach var="priority" items='${possiblePriorities}'>
<td><c:out value='${priority}'/></td>
</c:forEach>
</tr>
<c:forEach var="appender" items='${appenders}'>
<tr>
<td><c:out value='${appender.getName()}'/></td>
<c:forEach var="priority" items='${possiblePriorities}'>
<td>
<input type="radio" name="'${appender.getName()}'" value="'${priority}'"
<c:if test='${appender.getChainedPriority() == priority)}'> checked </c:if>
>
</td>
</c:forEach>
</tr>
</c:forEach>
<tr>
<td rowspan=5 align="center"> <button type="submit" name="submit" value="update">Update</button></td>
</tr>
</table>
<!-- section of page to add new appender-->
<table style="width:auto;">
<tr>
<td align="center">
<input type="text" name="newLogger" size="70">
<td>
<td>
<select name="newLoggerLevel">
<c:forEach var="priority" items='${possiblePriorities}'>
<option value="<c:out value='${priority}' />"><c:out value='${priority}' /></option>
</c:forEach>
</select>
<td>
<td>
<button type="submit" name="submit" value="Add">Add Logger</button>
</td>
</tr>
</table>
The idea is to get a view of this sort:
Two events can generate from the above page:
1) add a new appender
2) update level of existing appender
Both of these events can be handled with the below servlet code:
import org.apache.log4j.*;
....
....
Enumeration e = LogManager.getCurrentLoggers();
while (e.hasMoreElements())
{
Logger logger = (Logger) e.nextElement();
String prio = request.getParameter(logger.getName());
if (prio != null && prio.length() > 0)
{
Level p = Level.toLevel(prio);
if (p != null && ! p.equals(logger.getEffectiveLevel()))
{
logger.setLevel(p);
}
}
}
// add new loggers desired
String newLogger = request.getParameter("newLogger");
String newLoggerLevel = request.getParameter("newLoggerLevel");
if (newLogger != null)
{
Level p = Level.toLevel(newLoggerLevel);
Logger logger = Logger.getLogger(newLogger);
logger.setLevel(p);
}
No comments:
Post a Comment