Enhancing your expertise in Java, Kubernetes, Spring Boot, AWS, BTC, and ETH can significantly elevate your career prospects in the ever-evolving tech industry. Welcome to my blog, where I share insights and resources to help you master these key technologies and stay ahead of the curve. Enhance your tech skills with insights on Java, Kubernetes, Spring Boot, AWS, BTC, and ETH. Master advanced topics and stay updated with practical tips and tutorials!
Tuesday, May 27, 2008
Code Analysis
Friday, May 02, 2008
Log4j PatternLayout
Conversion Character | Effect |
---|---|
c | Used to output the category of the logging event. The category conversion specifier can be optionally followed by precision specifier, that is a decimal constant in brackets. If a precision specifier is given, then only the corresponding number of right most components of the category name will be printed. By default the category name is printed in full. For example, for the category name "a.b.c" the pattern %c{2} will output "b.c". |
C | Used to output the fully qualified class name of the caller issuing the logging request. This conversion specifier can be optionally followed by precision specifier, that is a decimal constant in brackets. If a precision specifier is given, then only the corresponding number of right most components of the class name will be printed. By default the class name is output in fully qualified form. For example, for the class name "org.apache.xyz.SomeClass", the pattern %C{1} will output "SomeClass". WARNING Generating the caller class information is slow. Thus, it's use should be avoided unless execution speed is not an issue. |
d | Used to output the date of the logging event. The date conversion specifier may be followed by a date format specifier enclosed between braces. For example, %d{HH:mm:ss,SSS} or %d{dd MMM yyyy HH:mm:ss,SSS}. If no date format specifier is given then ISO8601 format is assumed. The date format specifier admits the same syntax as the time pattern string of the For better results it is recommended to use the log4j date formatters. These can be specified using one of the strings "ABSOLUTE", "DATE" and "ISO8601" for specifying These dedicated date formatters perform significantly better than |
F | Used to output the file name where the logging request was issued. WARNING Generating caller location information is extremely slow. It's use should be avoided unless execution speed is not an issue. |
l | Used to output location information of the caller which generated the logging event. The location information depends on the JVM implementation but usually consists of the fully qualified name of the calling method followed by the callers source the file name and line number between parentheses. The location information can be very useful. However, it's generation is extremely slow. It's use should be avoided unless execution speed is not an issue. |
L | Used to output the line number from where the logging request was issued. WARNING Generating caller location information is extremely slow. It's use should be avoided unless execution speed is not an issue. |
m | Used to output the application supplied message associated with the logging event. |
M | Used to output the method name where the logging request was issued. WARNING Generating caller location information is extremely slow. It's use should be avoided unless execution speed is not an issue. |
n | Outputs the platform dependent line separator character or characters. This conversion character offers practically the same performance as using non-portable line separator strings such as "\n", or "\r\n". Thus, it is the preferred way of specifying a line separator. |
p | Used to output the priority of the logging event. |
r | Used to output the number of milliseconds elapsed from the construction of the layout until the creation of the logging event. |
t | Used to output the name of the thread that generated the logging event. |
x | Used to output the NDC (nested diagnostic context) associated with the thread that generated the logging event. |
X | Used to output the MDC (mapped diagnostic context) associated with the thread that generated the logging event. The X conversion character must be followed by the key for the map placed between braces, as in %X{clientNumber} where See |
% | The sequence %% outputs a single percent sign. |
ref
Is it possible to direct log output to different appenders by level?
- Is it possible to direct log output to different appenders by level?
-
Yes it is. Setting the Threshold option of any appender extending AppenderSkeleton, (most log4j appenders extend AppenderSkeleton) to filter out all log events with lower level than the value of the threshold option.
ref
Rolling File and errors to email
Log messages with Level info to fatal to a file and send messages from error to fatal by email. The file should be rolled every 100 KB.
You need mail.jar and activation.jar libraries from J2EE to send emails. Further properties of the SmtpAppender are described here:
http://logging.apache.org/log4j/docs/api/org/apache/log4j/net/SMTPAppender.html
log4j.properties
### file appender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.maxFileSize=100KB
log4j.appender.file.maxBackupIndex=5
log4j.appender.file.File=test.log
log4j.appender.file.threshold=info
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
#email appender
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
#defines how othen emails are send
log4j.appender.mail.BufferSize=1
log4j.appender.mail.SMTPHost="smtp.myservername.xx"
log4j.appender.mail.From=fromemail@myservername.xx
log4j.appender.mail.To=toemail@myservername.xx
log4j.appender.mail.Subject=Log ...
log4j.appender.mail.threshold=error
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
log4j.appender.mail.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=warn, file, mail
ref
Reconfigure a running log4j configuration
If you analyse a problem you frequently want to change the log level of a running application server. This chapter explains how you can do this. I used Tomcat as example server but you can use any application server you like.
The XML actually offers a method to watch changes in config files.
http://logging.apache.org/log4j/docs/api/org/apache/log4j/xml/DOMConfigurator.html#configureAndWatch(java.lang.String)
The problem is that it seems not to work in some situations. But this is no problem as it is quite easy to develop a short tool by yourself. We have two options. We could change the log level during runtime:
Logger root = Logger.getRootLogger();
root.setLevel(Level.WARN);
or we can reload the configuration:
// PropertyConfigurator.configure(url);
DOMConfigurator.configure(url);
The following example will check the configuration file in defined intervals and reconfigure log4j if any changes are found.
We need to create three things:
a) a monitor thread, monitoring the configuration file and reconfiguring log4j if needed
b) a servlet starting and stopping the monitor thread
c) an entry in the web.xml, to initialize the servlet
The following class monitors the logj4 configuration file and checks with the last change date has changed:
package de.laliluna.logexample;
import java.io.File;
import java.net.URL;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;
public class MonitorThread implements Runnable {
private static Logger log = Logger.getLogger(MonitorThread.class);
boolean interruped;
private long checkIntervalMillis = 10000;
private URL url;
private File file;
// stores the last modification time of the file
private long lastModified = 0;
public void run() {
System.out.println("Initialize " + url.getPath());
file = new File(url.getPath());
// PropertyConfigurator.configure(url);
DOMConfigurator.configure(url);
lastModified = file.lastModified();
monitor();
}
private void monitor() {
log.info("Starting log4j monitor");
while (!interruped) {
// check if File changed
long temp = file.lastModified();
if (lastModified != temp) {
log.info("Initialize log4j configuration " + url.getPath());
// PropertyConfigurator.configure(url);
DOMConfigurator.configure(url);
lastModified = temp;
} else
log.debug("Log4j configuration is not modified");
try {
Thread.currentThread().sleep(checkIntervalMillis);
} catch (InterruptedException e) {
interruped = true;
}
}
log.info("Shutting down log4j monitor");
}
public URL getUrl() {
return url;
}
public void setUrl(URL url) {
this.url = url;
}
public long getCheckIntervalMillis() {
return checkIntervalMillis;
}
/**
* Sets the interval for checking the url for changes. Unit is
* milliseconds, 10000 = 10 seconds
*
* @param checkIntervalMillis
*/
public void setCheckIntervalMillis(long checkIntervalMillis) {
this.checkIntervalMillis = checkIntervalMillis;
}
public boolean isInterruped() {
return interruped;
}
public void setInterruped(boolean interruped) {
this.interruped = interruped;
}
}
The servlet starts and stops the monitor thread:
package de.laliluna.logexample;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class Log4jConfigLoader extends HttpServlet {
private Thread thread;
@Override
public void destroy() {
thread.interrupt();
super.destroy();
}
public void init() throws ServletException {
super.init();
MonitorThread monitorThread = new MonitorThread();
monitorThread.setCheckIntervalMillis(10000);
monitorThread.setUrl(Log4jConfigLoader.class.getResource("/log4j.xml"));
thread = new Thread(monitorThread);
thread.start();
}
}
We add the servlet to the web.xml to initialize it.
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
log4j-init
de.laliluna.logexample.Log4jConfigLoader
10
ref