Dynamic/Runtime Log level configuration

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 : \server\\tmp\deploy\\

In a typical WAS installation this would be placed under : \AppServer\profiles\\installedApps\\\

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:&nbsp;&nbsp; <input name="logNameFilter" type="text"
                                               size="50″ value="<%=(logNameFilter == null ? "" : logNameFilter)%>"
            class="filterText" /> <input name="logNameFilterType" type="submit"
                                         value="<%=beginsWithFilter%>"/>&nbsp; <input
                name="logNameFilterType" type="submit" value="<%=containsFilter%>"
                class="filterButton"/>&nbsp; <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>&nbsp; <%}}%>
        </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

发表评论

电子邮件地址不会被公开。 必填项已用*标注