There is often a need to modify/change the log level of your (J2EE) application or parts of your application, without a server restart. These may be done for various purposes, debugging being one very obvious need.
Here’s a simple way to achieve the same, wherein we once you have deployed the EAR (if your WAR is wrapped within it) or WAR, you can simply place a JSP file at the root folder of your WAR file, and viola!, you have a custom log level configuration console.
In a typical JBOSS installation this would be placed under : <jboss home>\server\<profile>\tmp\deploy\<EAR – if wrapped within>\<WAR>
In a typical WAS installation this would be placed under : <WebSphere Installation Directory>\AppServer\profiles\<profile>\installedApps\<node name>\<EAR – if wrapped within>\<WAR>
Of course, you should have configured the log4j in your application properly.
Here is the configureLogging.jsp:
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ page import="org.apache.log4j.Level"%>
<%@ page import="org.apache.log4j.LogManager"%>
<%@ page import="org.apache.log4j.Logger"%>
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Enumeration"%>
<%@ page import="java.util.Set"%>
<%@ page import="java.util.Arrays"%>
<html>
<head>
<title>Log Level Configuration</title>
<style type="text/css">
<!--
#content {
margin: 0px;
padding: 0px;
text-align: center;
background-color: green;
border: 1px solid #000;
width: 100%;
}
body {
position: relative;
margin: 10px;
padding: 0px;
color: #333;
}
h1 {
margin-top: 20px;
font: 1.5em Verdana, Arial, Helvetica sans-serif;
}
h2 {
margin-top: 10px;
font: 0.75em Verdana, Arial, Helvetica sans-serif;
text-align: left;
}
a,a:link,a:visited,a:active {
color: blue;
text-decoration: none;
text-transform: uppercase;
}
table {
width: 100%;
background-color: #000;
padding: 3px;
border: 0px;
}
th {
font-size: 0.75em;
background-color: #eee;
color: #000;
padding-left: 5px;
text-align: center;
border: 1px solid #eee;
white-space: nowrap;
}
td {
font-size: 0.75em;
background-color: #fff;
white-space: nowrap;
}
td.center {
font-size: 0.75em;
background-color: #fff;
text-align: center;
white-space: nowrap;
}
.filterForm {
font-size: 0.9em;
background-color: #000;
color: #fff;
padding-left: 5px;
text-align: left;
border: 1px solid #000;
white-space: nowrap;
}
.filterText {
font-size: 0.75em;
background-color: #ccc;
color: #000;
text-align: left;
border: 1px solid #ccc;
white-space: nowrap;
}
.filterButton {
font-size: 0.75em;
background-color: brown;
color: white;
padding-left: 5px;
padding-right: 5px;
text-align: center;
border: 1px solid #ccc;
width: 100px;
white-space: nowrap;
}
–>
</style>
</head>
<body onLoad=”javascript:document.logFilterForm.logNameFilter.focus();”>
<%
String containsFilter = “Contains”;
String beginsWithFilter = “Begins With”;
String[] logLevels = { “debug”, “info”, “warn”, “error”, “fatal”,
”off” };
String targetOperation = (String) request.getParameter(“operation”);
String targetLogger = (String) request.getParameter(“logger”);
String targetLogLevel = (String) request
.getParameter(“newLogLevel”);
String logNameFilter = (String) request
.getParameter(“logNameFilter”);
String logNameFilterType = (String) request
.getParameter(“logNameFilterType”);
%>
<div id=”content”>
<h1>Log Level Configuration</h1>
<div>
<form action=”configureLogging.jsp” name=”logFilterForm”>
Filter Loggers: <input name=”logNameFilter” type=”text”
size=”50″ value=”<%=(logNameFilter == null ? “” : logNameFilter)%>”
class=”filterText” /> <input name=”logNameFilterType” type=”submit”
value=”<%=beginsWithFilter%>” /> <input
name=”logNameFilterType” type=”submit” value=”<%=containsFilter%>”
class=”filterButton” /> <input name=”logNameClear”
type=”button” value=”Clear”
onmousedown=’javascript:document.logFilterForm.logNameFilter.value=”";’ />
<input name=”logNameReset” type=”reset” value=”Reset”
class=”filterButton” />
<param name=”operation” value=”changeLogLevel” />
</form>
</div>
<table cellspacing=”1″>
<tr>
<th width=”25%”>Logger</th>
<th width=”25%”>Parent Logger</th>
<th width=”15%”>Current Level</th>
<th width=”35%”>Change Log Level To</th>
</tr>
<%
Enumeration loggers = LogManager.getCurrentLoggers();
HashMap loggersMap = new HashMap(128);
Logger rootLogger = LogManager.getRootLogger();
if (!loggersMap.containsKey(rootLogger.getName())) {
loggersMap.put(rootLogger.getName(), rootLogger);
}
while (loggers.hasMoreElements()) {
Logger logger = (Logger) loggers.nextElement();
if (logNameFilter == null || logNameFilter.trim().length() == 0) {
loggersMap.put(logger.getName(), logger);
} else if (containsFilter.equals(logNameFilterType)) {
if (logger.getName().toUpperCase()
.indexOf(logNameFilter.toUpperCase()) >= 0) {
loggersMap.put(logger.getName(), logger);
}
} else {
// Either was no filter in IF, contains filter in ELSE IF, or begins with in ELSE
if (logger.getName().startsWith(logNameFilter)) {
loggersMap.put(logger.getName(), logger);
}
}
}
Set loggerKeys = loggersMap.keySet();
String[] keys = new String[loggerKeys.size()];
keys = (String[]) loggerKeys.toArray(keys);
Arrays.sort(keys, String.CASE_INSENSITIVE_ORDER);
for (int i = 0; i < keys.length; i++) {
Logger logger = (Logger) loggersMap.get(keys[i]);
// MUST CHANGE THE LOG LEVEL ON LOGGER BEFORE GENERATING THE LINKS AND THE
// CURRENT LOG LEVEL OR DISABLED LINK WON’T MATCH THE NEWLY CHANGED VALUES
if (“changeLogLevel”.equals(targetOperation)
&& targetLogger.equals(logger.getName())) {
Logger selectedLogger = (Logger) loggersMap
.get(targetLogger);
selectedLogger.setLevel(Level.toLevel(targetLogLevel));
}
String loggerName = null;
String loggerEffectiveLevel = null;
String loggerParent = null;
if (logger != null) {
loggerName = logger.getName();
loggerEffectiveLevel = String.valueOf(logger
.getEffectiveLevel());
loggerParent = (logger.getParent() == null ? null : logger
.getParent().getName());
}
%>
<tr>
<td><%=loggerName%></td>
<td><%=loggerParent%></td>
<td><%=loggerEffectiveLevel%></td>
<td>
<%
for (int cnt = 0; cnt < logLevels.length; cnt++) {
String url = “configureLogging.jsp?operation=changeLogLevel&logger=”
+ loggerName
+ “&newLogLevel=”
+ logLevels[cnt]
+ “&logNameFilter=”
+ (logNameFilter != null ? logNameFilter : “”)
+ “&logNameFilterType=”
+ (logNameFilterType != null ? logNameFilterType
: “”);
if (logger.getLevel() == Level.toLevel(logLevels[cnt])
|| logger.getEffectiveLevel() == Level
.toLevel(logLevels[cnt])) {
%> [<%=logLevels[cnt].toUpperCase()%>] <%
} else {
%> <a href=’<%=url%>’>[<%=logLevels[cnt]%>]</a> <%
}
}
%>
</td>
</tr>
<%
}
%>
</table>
</div>
</body>
</html>
Once you copy this JSP under root of your web app, you can access it by entering http://[host]:[port]/[context root]/configureLogging.jsp
You should see something like this on your screen:
