Question
How to parse the unstructured Log4J log in Java/Scala.
Background
There are multiple questions on how to parse Log4J logs but mostly they recommend using XML or JSON appender to output structured outputs to parse. However need to parse already generated unstructured log files programmatically, not using tools such as logstash, chainsaws GUI.
Help with LogFilePatternReceiver shows the way but it requires "plugin" support which was supposed to be implemented in Log4J 1.3 but Log4J 1.x discontinued with 1.2.x. It looks Log4J 2 does not have LogFilePatternReceiver.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration >
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.SimpleLayout"/>
<filter class="org.apache.log4j.filter.ExpressionFilter">
<param name="Expression" value="msg ~= 'SPECIFY CASE-INSENSITIVE MSG MATCH HERE'" />
<param name="AcceptOnMatch" value="true"/>
</filter>
<filter class="org.apache.log4j.filter.DenyAllFilter"/>
</appender>
<plugin name="LOGFILE" class="org.apache.log4j.varia.LogFilePatternReceiver">
<param name="fileURL" value="file:///c:/some.log"/>
<param name="timestampFormat" value="yyyy-MM-dd HH:mm:ss,SSS"/>
<param name="logFormat" value="TIMESTAMP LEVEL [LOGGER] MESSAGE"/>
<param name="name" value="my log file"/>
<param name="tailing" value="true"/>
</plugin>
<root>
<level value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</root>
</log4j:configuration>
There is a class LogFileParser in org.apache.log4j.lf5.util.LogFileParse package but not sure how to use it. There is a tool OtrosLogViewer but prefer not having 3rd party dependencies if possible.
Options
Re: Extract log info from each output log line on the console suggests refering to the Chainsaw code. Read the code and implement similar would be the option but if there is already a known way to parse logs, would like to know it first.
References
Parse a log4j log file
Class LogFilePatternReceiver
Found a way by using log4j and extras 1.2 jars, although not work with Log4J 2.
Java
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.receivers.varia.LogFilePatternReceiver;
public class LogParser extends LogFilePatternReceiver {
final static Logger logger = Logger.getLogger(LogParser.class);
public void doPost(LoggingEvent event) {
System.out.println(event.getTimeStamp());
System.out.println(event.getMessage());
}
public static void main(String[] args) {
(new LogParser()).run();
}
private void run(){
LogFilePatternReceiver r = new LogParser();
r.setLogFormat("TIMESTAMP LEVEL [THREAD] CLASS (FILE:LINE) - MESSAGE");
r.setFileURL("file:///tmp/log");
r.setTimestampFormat("yyyy-MM-dd HH:mm:ss,SSS");
r.setTailing(true);
r.setLoggerRepository(logger.getLoggerRepository());
r.activateOptions();
}
}
log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
Sample log file
2017-12-02 16:53:42,618 DEBUG [main] LogParser (LogParser.java:15) - message 1
2017-12-02 16:53:42,624 DEBUG [main] LogParser (LogParser.java:16) - message 2
Result
2017-12-02 19:21:31,633 INFO [main] spi.Log4JULogger (Log4JULogger.java:104) - activateOptions
2017-12-02 19:21:31,652 DEBUG [LogFilePatternReceiver-plugin] spi.Log4JULogger (Log4JULogger.java:58) - regexp is (\S+-\S+-\S+ \S+:\S+:\S+,\S+)[ ]+(\S*\s*?)[ ]+\[(.*?)\][ ]+(.*?)[ ]+\((.*?):(.*?)\)[ ]+\-[ ]+(.*)
2017-12-02 19:21:31,652 INFO [LogFilePatternReceiver-plugin] spi.Log4JULogger (Log4JULogger.java:104) - attempting to load file: file:///tmp/log
1512194022618
message 1
1512194022624
message 2
2017-12-02 19:21:33,656 DEBUG [LogFilePatternReceiver-plugin] spi.Log4JULogger (Log4JULogger.java:58) - tailing file
2017-12-02 19:21:35,660 DEBUG [LogFilePatternReceiver-plugin] spi.Log4JULogger (Log4JULogger.java:58) - tailing file
Related
I am using log4j2
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
and a very basic configuration xml file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
<category name="org.apache.log4j.xml">
<priority value="info" />
</category>
<Root>
<priority value ="debug" />
<appender-ref ref="STDOUT" />
</Root>
</log4j:configuration>
For some reason logging is not working. I am getting
ERROR StatusLogger Error parsing /home/sfalk/workspace/java/lazy-model-access/lamoa-parent/lamoa-server/target/classes/log4j2.xml
ERROR StatusLogger No logging configuration
What am I doing wrong here?
Your configuration file is for log4j 1.x, not 2.5
I have an unpacked EAR deployed at $JBOSS_HOME/standalone/deployments in Wildfly-8.2.0.Final AS. It contains unpacked WAR and application jar files.
HelloWorldEar-0.0.1-SNAPSHOT.ear
-HelloWorldServlet-0.0.1-SNAPSHOT.war
-lib
-META-INF
-aspectjrt-1.8.6.jar
-HelloWorldAnnotation-0.0.1-SNAPSHOT.jar
-HelloWorldAspect-0.0.1-SNAPSHOT.jar
-HelloWorldCommonLib-0.0.1-SNAPSHOT.jar
-HelloWorldEJB-0.0.1-SNAPSHOT.jar
-log4j2.xml
lib folder of EAR contains log4j2 related APIs for providing logging feature.
lib
-commons-logging-1.2.jar
-HelloWorldLog4jPlugin-0.0.1-SNAPSHOT.jar (Jar containing custom log4j2 plugins)
-log4j-api-2.4.1.jar
-log4j-core-2.4.1.jar
-log4j-jcl-2.4.1.jar
-log4j-web-2.4.1.jar
I am initializing log4j2 configuration by initializing log4j2.xml using in a startup singleton bean in HelloWorldEJB-0.0.1-SNAPSHOT.jar.
String path = System.getProperty("jboss.home.dir")
+ "/standalone/deployments/HelloWorldEar-0.0.1-SNAPSHOT.ear/log4j2.xml";
ConfigurationSource source;
File configFile = new File(path);
try {
source = new ConfigurationSource(new FileInputStream(configFile), configFile);
Configurator.initialize(null, source);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
log4j2.xml content
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace">
<Appenders>
<RollingFile name="SERVER_FILE" fileName="${sys:LOGS}/sample.log" filePattern="${sys:LOGS}/sample.log.%i" append="true">
<PatternLayout>
<pattern>%d %-5p [%c{1}] [EventId: %e] [%t] %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="500 KB" />
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout>
<pattern>%d{ABSOLUTE} %-5p [%c{1}] %m%n</pattern>
</PatternLayout>
</Console>
</Appenders>
<Loggers>
<Logger name="com.test.prototype.log4j" level="debug">
<AppenderRef ref="SERVER_FILE"/>
</Logger>
<Root level="debug" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Root>
</Loggers>
</Configuration>
All the sub-packages and classes are defined under the package com.test.prototype.log4j.
Log statements added in the classes of HelloWorldEJB-0.0.1-SNAPSHOT.jar gets logged in the log file.
My issue is that 1. log statements from other application jars and WAR are not getting logged into the log file.
2. Logging not working through commons-logging API though required system parameters for log4j2 is added.
System.setProperty("org.apache.commons.logging.Log",
"org.apache.commons.logging.impl.Log4JLogger");
I have tried adding the class-path in the application jars and below listener in the web.xml of WAR file but nothing worked.
org.apache.logging.log4j.web.Log4jServletContextListener
I need to have log4j2.xml under EAR and it should server for the all the application jars and WARs added in the EAR. Could anyone please help me about how to resolve this issue.
Have you tried specifying the log4j2.xml config file location with system property -Dlog4j.configurationFile=path/to/log4j2.xml?
I suspect that the way you're initializing log4j now is not visible from other WARs.
If this fails, please raise this issue on the log4j2 Jira issue tracker. https://issues.apache.org/jira/browse/LOG4J2
I'm trying to stream a basic hello world log message to show up in chainsaw from log4j2. I don't care if it uses "Zeroconf" or not, I just want something that works. I know that my test program is logging messages since they show on the console, and I know it's finding my config file because I can change the format of the messages that get printed in the console, but that's all I know.
My config file (containing various failed guesses):
<?xml version="1.0" encoding="UTF-8"?>
<configuration advertiser="org.apache.logging.log4j.core.net.MulticastDNSAdvertiser">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n"/>
</Console>
<File name="testFile" fileName="logs/test.log" bufferedIO="false" advertiseURI="file://localhost/home/matt/code/ade/logs/test.log" advertise="true">
<XMLLayout />
</File>
<SocketAppender name="socketTest" host="localhost" immediateFlush="true" port="4560" protocol="TCP" advertiseURI="http://localhost" advertise="true">
<XMLLayout />
</SocketAppender>
</appenders>
<loggers>
<root level="TRACE">
<appender-ref ref="Console"/>
<appender-ref ref="testFile"/>
<appender-ref ref="socketTest"/>
</root>
</loggers>
</configuration>
I've tried various combinations of: including jmdns.jar on the classpath, restarting chainsaw at various points, and getting frustrated, but nothing has helped.
Any ideas?
Edit: I figured out why it couldn't read the log files I was saving to disk, (I hadn't been using XMLLayout) so I've updated the question to reflect that I now only need to get streaming working.
The 'advertiser' uses the log4j2 plugin mechanism, so you must provide the 'name' defined on the Advertiser in the configuration - not the fully-qualified class name.
The log4j2 advertisement mechanism currently supports advertisement of FileAppenders and SocketAppenders. However, Chainsaw only supports discovery of log4j2 FileAppenders which are advertised with a PatternLayout. XMLLayout support will show up in the near future.
The latest developer snapshot of Chainsaw must be used in order to leverage log4j2's advertiser mechanism. Chainsaw tarball and DMG available at: http://people.apache.org/~sdeboy/
Chainsaw will discover the advertised fileappender configuration and parse (and tail if you get the latest Chainsaw developer build) the log file - no Chainsaw configuration required.
Note, you need to use a PatternLayout, and JMDNS must be on the classpath of the application using this appender configuration.
Here is an example Log4j2 -appender- configuration that will advertise a fileappender configuration:
<?xml version="1.0" encoding="UTF-8"?>
<configuration advertiser="multicastdns">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n"/>
</Console>
<File name="testFile" fileName="logs/test.log" bufferedIO="false" advertiseURI="file:///localhost/home/matt/code/ade/logs/test.log" advertise="true">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %m%n"/>
</File>
</appenders>
<loggers>
<root level="TRACE">
<appender-ref ref="Console"/>
<appender-ref ref="testFile"/>
</root>
</loggers>
</configuration>
Once you have started your app that is using the appender
configuration, open the 'Zeroconf' tab in Chainsaw.
You should see a row with your appender's name (assuming you added
jmdns to the classpath for the app using the fileappender
configuration).
You can click 'Autoconnect' if you'd like to always start Chainsaw
with this configuration if it is available.
Next, double-click
on the row with the appender name and Chainsaw will start parsing and tailing your log file.
The advertised URL provided in your file appender
configuration must be accessible network-wise to Chainsaw (looks like you are working
locally with Chainsaw and your fileappender, so file:/// paths will
work fine - note the three slashes).
Chainsaw will work best if there are delimiters around each field - square brackets, dashes, etc. as long as that character won't be present in the field you are delimiting.
I have a simple Netbeans 7.1.2 (NON MAVEN) project that use glassfish 3.1 server for testing.
I created a log4j2.xml file and placed it on the classpath
here it is
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="debug"/>
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} [%t] %-5p %c{1} - %m%n"/>
</layout>
</appender>
<appender name="rolling-file" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="c:\tmp\Program-Name.log"/>
<param name="MaxFileSize" value="500KB"/>
<param name="MaxBackupIndex" value="4"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %l - %m%n"/>
</layout>
</appender>
<logger name="org.hibernate">
<level value="info" />
</logger>
<root>
<priority value ="debug" />
<appender-ref ref="console" />
<appender-ref ref="rolling-file" />
</root>
</log4j:configuration>
the project uses hibernate to store data from a web service to a database.
However I am not able to log anything. I can see the logs of hibernate into the Netbeans IDE but I cannot see the created on the filesystem file.
I have this error when calling the web service
SEVERE: ERROR StatusLogger Unknown object "logger" of type org.apache.logging.log4j.core.config.LoggerConfig is ignored
SEVERE: ERROR StatusLogger root contains an invalid element or attribute "priority"
SEVERE: ERROR StatusLogger Unknown object "root" of type org.apache.logging.log4j.core.config.LoggerConfig is ignored
could someone pls help or give some advice I googled and stackoverflowed but without chance.
Paolo
I think that your log4j2.xml file is mixed with the old log4j style xml.
I'm having the same trouble as you when it comes to appending hibernate log to my application's log file. But I think that I can help with the logger error.
Try this file instead (and note the changes that I made):
<?xml version="1.0" encoding="UTF-8" ?>
<configuration name="SOME_PROJ_NAME" status="OFF">
<appenders>
<RollingFile name="rolling-file" fileName="c:/tmp/Program-Name.log" filePattern="c:/tmp/$${date:yyyy-MM}/Program-Name-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout>
<pattern>%d{ABSOLUTE} [%t] %-5p %c{1} - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="6" modulate="true"/>
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingFile>
</appenders>
<loggers>
<root level="info"
<appender-ref ref="rolling-file"/>
</root>
<logger name="org.hibernate level="info">
<appender-ref ref="rolling-file"/>
</logger>
</loggers>
</configuration>
It is quite similar to the one that I'm using. Note that this file should be on classpath for log4j2 auto configuration to kick in.
The most important thing you should do when using the net to configure log4j2 is that you're looking at log4j2 and not log4j style configuration.
I suggest that you look in http://logging.apache.org/log4j/2.x/ for further info. They have a good downloadable pdf that you can check out.
In addition, check out my question about a similar problem.
I tried to run simple example(Hello wold) in struts-2.3.4.1 with tomcat server 7.0.
But when i run this sample application i got following exception :
java.lang.NullPointerException
org.apache.struts2.impl.StrutsActionProxy.getErrorMessage(StrutsActionProxy.java:69)
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:501)
org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:432)
used Log4j.xml Configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender class="org.apache.log4j.rolling.RollingFileAppender" name="FixedWindowRollingFile">
<param name="Append" value="true"/>
<param name="ImmediateFlush" value="true"/>
<rollingPolicy class="org.apache.log4j.rolling.FixedWindowRollingPolicy">
<param name="fileNamePattern" value="c:/logs/HelloExample/HelloExample.%i.log"/>
<param name="minIndex" value="1"/>
<param name="maxIndex" value="10"/>
</rollingPolicy>
<triggeringPolicy class="org.apache.log4j.rolling.SizeBasedTriggeringPolicy">
<param name="MaxFileSize" value="1002400"/>
</triggeringPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %p %c{1}:%L - %m%n"/>
</layout>
</appender>
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.SimpleLayout"/>
</appender>
<root>
<priority value="DEBUG"/>
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="FixedWindowRollingFile"/>
</root>
</log4j:configuration>
Also I have used my own log4j.xml configuration file to configure web application but i got this exception regularly(generated log file https://gist.github.com/3851738).