Archive

Archive for March, 2009

The Logging Saga

March 30, 2009 Leave a comment

Took me a whole day, so was worth blogging it. This is jboss-4.2.2 specific. WAR files in JBoss are scoped by default.EAR files are not.
Lets look into the two cases:
1. WARIn case of WAR file, you can have the log4j.xml in the conf folder and things would work out. But, you cannot control the logging levels at runtime using Log4jService. The reason being, Log4JService controls the Logger in the jboss lib folder. To achieve this, I guess you might need a EAR or sthg. What we can do is write a JSP/Servlet and have it as part of your application logger. This gives you the reference of your logger and hence runtime control to configure logging level

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String loggerName = (String) request.getParameter("loggerName");
    String level = (String) request.getParameter("level");
    String actionType = (String) request.getParameter("submit");
    System.out.println("loggerName=" + loggerName + "/level=" + level);
    if (loggerName != null && loggerName.trim().length() > 0) {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      Level origLevelObj = Logger.getLogger(loggerName).getLevel();
      String origLevel = "UNKNOWN";
      if (origLevelObj == null) {
        System.out.println(Logger.getRootLogger().getLevel());
        origLevel = Logger.getRootLogger().getLevel().toString();
      }
      if (actionType.equalsIgnoreCase("getloggerlevel")) {
        out.println("Log level for " + loggerName + " is <b>" + origLevel + "</b>");
      } else if (actionType.equalsIgnoreCase("setloggerlevel")) {
        setLogLevel(loggerName, level);
        out.println("Log level for " + loggerName + " is changed from <b>" + origLevel
            + "</b> to <b>" + level + "</b>");
      }
      out.flush();
      out.close();
    }
  }

  private void setLogLevel(String loggerName, String level) {
    if ("debug".equalsIgnoreCase(level)) {
      Logger.getLogger(loggerName).setLevel(Level.DEBUG);
    } else if ("info".equalsIgnoreCase(level)) {
      Logger.getLogger(loggerName).setLevel(Level.INFO);
    } else if ("error".equalsIgnoreCase(level)) {
      Logger.getLogger(loggerName).setLevel(Level.ERROR);
    } else if ("fatal".equalsIgnoreCase(level)) {
      Logger.getLogger(loggerName).setLevel(Level.FATAL);
    } else if ("warn".equalsIgnoreCase(level)) {
      Logger.getLogger(loggerName).setLevel(Level.WARN);
    }
  }

And this could be your JSP:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<h2>Log Level Controller</h2>
<br>
<FORM METHOD=POST ACTION="logy">
	<table border=1>
		<th colspan=2 bgcolor="YELLOW">Get Logger level</th>
		<tr>
			<td>LoggerName</td>
			<td><INPUT TYPE=TEXT NAME="loggerName" SIZE=20>
			</td>
		</tr>
		<tr>
			<td colspan=2 align=right><INPUT TYPE=SUBMIT name=submit
				value=getloggerlevel>
			</td>
		</tr>
	</table>
	<br>
	<br>
	<table border=1>
		<th colspan=2 bgcolor="YELLOW">Set Logger level</th>
		<tr>
			<td>LoggerName</td>
			<td><INPUT TYPE=TEXT NAME="loggerName" SIZE=20>
			</td>
		</tr>
		<tr>
			<td>LogLevel</td>
			<td><select name="level">
					<option value=DEBUG>DEBUG</option>
					<option value=INFO>INFO</option>
					<option value=WARN>WARN</option>
					<option value=ERROR>ERROR</option>
					<option value=FATAL>FATAL</option>
			</select>
			</td>
		</tr>
		<tr>
			<td colspan=2 align=right><INPUT TYPE=SUBMIT name=submit
				value=setloggerlevel>
			</td>
		</tr>
	</table>
</FORM>

2. EARMake changes in jboss-log4j.xml.To have application specific logging:
1. Write an appender – You can give your application specific filename.
2. Write a logger and refer to that appender.

You do ->

 Logger.getLogger(x.class); 

This takes the complete package name into the logger hierarchy. So you can name you logger in log4j as “com.abc”. This will route all your requests to your selected appender’s file. and then specify the additivity to false. When you specify the additivity to false, then you dont log into the root appenders. And also, dont add your appender into the root logger.

<appender name="InfoAppender"
	class="org.apache.log4j.RollingFileAppender"> <errorHandler
	class="org.jboss.logging.util.OnlyOnceErrorHandler" />
<param name="File" value="${jboss.server.log.dir}/pos-server.log" />
<param name="Append" value="true" />
<param name="ImmediateFlush" value="true" />
<param name="MaxFileSize" value="200MB" />
<param name="MaxBackupIndex" value="10" />
<param name="Threshold" value="DEBUG" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
	value="%d %X{SERVER_NAME} [%t] %-5p (%c{1}) - %m%n" />
</layout> 
</appender>

And then do this: Very important

<logger name="com.boo" additivity="false"> <level
		value="DEBUG" /> <appender-ref ref="InfoAppender" /> </logger>
	Check out the root:
	<root> <priority value="debug" /> <appender-ref ref="CONSOLE" />
	<appender-ref ref="FILE" /> 
Categories: Tech stuff