Display only selected Log4j debug statements - java

Is it possible to display only those statements in console, which are having certain words.
For eq:
logger.debug ( "java: hello " );
logger.debug ( "groovy: hello " );
logger.debug ( "ruby: hello " );
Now, by doing some configuration or whatever, all statements which are starting with groovy: should display.

You want to use the log4j StringMatchFilter which is part of the "extras" package from apache logging.
Here is a quick example found online:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CustomAppender" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="custom.log"/>
<param name="Append" value="true"/>
<param name="MaxFileSize" value="5000KB"/>
<param name="maxBackupIndex" value="5"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.StringMatchFilter">
<param name="StringToMatch" value="Here is DEBUG" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender>
<root>
<appender-ref ref="CustomAppender"/>
</root>
</log4j:configuration>

What about create your customs Levels
public class Groovy extends Level
And then in the log properties file set those levels as your configuration
Hope this helps,
David.

One can use different loggers (say a logger for "java" messages and one for "groovy" messages). The Log4J configuration can be set with different levels for each logger.
You can read more here

One could use a tool to filter out messages. For Windows you could do this with BareTail. Filtering of messages is only possible with the pro (paid) version. Perhaps there are others tools that do the same job.

SLF4J markers are perhaps suitable for your purposes. All printing methods such as debug and info in org.slf4j.Logger admit a Marker as a first parameter. Moreover, logback-classic, a native SLF4J implementation, ships with a filter called MarkerFilter which I think does what you want.

Related

Adding $USER to Log4J's log file name

I have a standalone Java application myApp.jar running on Linux/bash and its Log4J.xml is configured like the following:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
...
<appender name="DEFAULT_APPENDER" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="/apps/my-app/logs/server.log"/>
<param name="MaxFileSize" value="10MB"/>
<param name="MaxBackupIndex" value="10"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss,SSS} [%t] %c %x %-5p %m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="TRACE" />
<param name="LevelMax" value="FATAL" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
It is currently working fine with log files produced as server.log, server.log.1, server.log.2, etc...
However, I have recently found out that, other than me running the application manually with java -jar myApp.jar, the application is also run by cron job (by root). When I try to run myApp.jar manually on terminal using my account, say user123 at the same time when the crob job is running it, my command fails because I lose over file permission when generating the log files. The cron job is generating the log files with owner root and permission 664.
I am wondering if it is possible to change log4j.xml alone so that myApp.jar will produce log files with file names in such fashion: server-{$USER}.log, server-{$USER}.log.1, server-{$USER}.log.2, etc... So for example, the cron job will produce its log files like server-root.log and I, using account user123, will produce my log files in the same directory like server-user123.log
Note: I myself don't have access to root on the server.
Note: I am using Log4J version 1.x

Use system properties OR variables in log4j

I want to to do like this:
<appender name="ErrorLog" class="org.apache.log4j.FileAppender">
<param name="File" value="${error.log.path}"/>
<param name="Append" value="true" />
<param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%C{1} %L [%t] %d{dd MMM,yyyy HH:mm:ss.SSS} %-5p - %m%n" />
</layout>
</appender>
Notice this line: <param name="File" value="${error.log.path}"/>
I tried to set the values like this:
public static void main(String[] args) {
System.setProperty("error.log.path", "/test/crm/log/error.log");
ApplicationContext context = new ClassPathXmlApplicationContext("blah.xml");
..........
..........
}
But I don't see any effect.
Is log4j gets configured before calling the main method?
Is there any other way to do this?
Look at this thread
It looks like you did everything right. I don't think there is any difference between setting the property inside your main class with System.setProperty() and specifying it via the command line as long as it happens befor actual log4j initialization.
I think your issue is that your logging framework gets loaded before you specify the property.
I can say that the logging framework (log4j) will get configured when you call the configurator. Stuff like BasicConfigurator.configure() (in your case its xml configurator).
Otherwise the first attempt to use the logging will cause message like "log4j is not configured properly".
The real question is whether your code snippet with 'main' is not oversimplified.
With this in mind, another question that I have to ask - whether you're running inside some container or you're running a real vanilla method main and configure everything by yourself? I'm asking because if you're running in container, the chances are that container will by itself somehow configure its logging, for example JBoss will do so. In this case more investigation is required.
Hope this helps
You can do it by configure appender pragmatically
FileAppender fa = new FileAppender();
fa.setFile("/test/crm/log/error.log");
fa.setLayout(new
PatternLayout("%C{1} %L [%t] %d{dd MMM,yyyy HH:mm:ss.SSS} %-5p - %m%n"));
fa.setThreshold(Level.ERROR);
fa.setAppend(true);
fa.activateOptions();
Logger.getRootLogger().addAppender(fa);
// similarly you can add all appenders.
// or just append file name alone
Logger log = Logger.getLogger(YourClass.class);
FileAppender appender = (FileAppender) log.getAppender("ErrorLog");
appender.setFile("appender");
System Properties can be used as ${user.home}, pick required from here http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
example :
<appender name="errorLog" class="com.qait.logger.IOPFileAppender">
<param name="Threshold" value="ERROR" />
<param name="File"
value="${user.home}/Harvestors/IOP Error Logs/error.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d%-5p [%c{1}] %m %n" />
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="ERROR" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>
Access to your property via "sys:" prefix.
Example:
<param name="File" value="${sys:error.log.path}"/>
For more information follow this link: https://logging.apache.org/log4j/2.x/manual/lookups.html
maven document:
System properties. The formats are ${sys:some.property} and ${sys:some.property:-default_value}.
from Maven Property Substitution
Setting the system property does not come into affect here. You'll need to pass it as a argument to java while executing. Try
java -Derror_log_path=/test/crm/log/error.log
Note: I am not sure if dot . works in there so replaced it with underscore _.

Rolling logs by both size and time

I use RollingFileAppender of log4j 1.2.16, which rolls log files, when they reach a certain size. Now I would like to roll log files daily and when they reach a certain size. Thus there will be one or more log files per day.
For example,
myapp.log
myapp-17.12.2013.log
myapp-16.12.2012.log
myapp-16.12.2012.1.log
myapp-16.12.2012.2.log
Is there an off-the-shelf appender, which does it already?
There are indeed two options:
use LogBack with its size and time triggering policy: http://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedFNATP
there is TimeAndSizeRollingAppender for Log4J from here: http://www.simonsite.org.uk/
Keep in mind that both options use file renames. Consider this carefully if there's another script automatically moving these files. File rename is risky when two processes deal with the same file.
My suggestion is to directly write to immutable log file name in the pattern: myapp-{dd.MM.yyyy}.{X}.log. That way "rolling" is simply closing one file and opening a new one. No renames. No background threads.
The quick answer is "no". Looking at log4j's javadoc: https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/FileAppender.html
There are only two out-of-the-box file appenders: DailyRollingFileAppender and RollingFileAppender (and the first one is not recommended because it has synchronization issues).
To achieve what you want, you should create your own appender, extending RollingFileAppender and modifying it to roll the file if the day changes. The modification would be in method:
protected void subAppend(LoggingEvent event)
You can see its source here: http://www.docjar.com/html/api/org/apache/log4j/RollingFileAppender.java.html (line 274).
You just need to copy and paste the code and change the if calling rollOver to suit your needs.
Below configuration xml will do the job:
JAR required: log4j-rolling-appender-20150607-2059
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="true"
xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="file"
class="uk.org.simonsite.log4j.appender.TimeAndSizeRollingAppender">
<param name="File" value="D:\\App.log" />
<param name="Threshold" value="DEBUG" />
<param name="DatePattern" value=".yyyy-MM-dd" />
<param name="MaxFileSize" value="1KB" />
<param name="MaxRollFileCount" value="100" />
<param name="ScavengeInterval" value="30000" />
<param name="BufferedIO" value="false" />
<param name="CompressionAlgorithm" value="GZ" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %-23d{ISO8601} [%t] %x: %c{1} - %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="file" />
</root>
</log4j:configuration>

Logging different Level messages in different Logs using Log4j

I want to maintain two Log Files in my web-application using apache Log4j.jar:
1) One log will contain all the Log messages of every level
2) Second log file will contain the Log messages of specific class
This is the configuration XML that I am using: (Not much aware of the tags used in the XML, was just trying out)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="FILE1" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="D:/CSVExportLogs/CSVExportLogFile-ERROR.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c (%F:%L) - %m%n"/>
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="D:/CSVExportLogs/CSVExportLogFile-INFO.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c (%F:%L) - %m%n"/>
</layout>
</appender>
<category name="com.taxware.mgmt.CustomerManager" additivity="false">
<priority value="warn"/>
<appender-ref ref="FILE"/>
</category>
<root>
<priority value="info"/>
<appender-ref ref="FILE1"/>
</root>
</log4j:configuration>
By the above xml I am getting only info messages in the FILE1, I want messages of all levels as well as the message of warn level that are going in the separate file in this file. Is there any solution available for this.
# Create ROOT logger(main logger) with level INFO, and add to it 2 appenders:
# FILE_INFO, FILE_WARN. This means that all loggers by default will writes messages
# in this 2 file appenders, with level INFO or higher
log4j.rootLogger=INFO, FILE_INFO, FILE_WARN
######## LEVELS:
# Set logging level to WARN for all classes and subclasses in package
# com.taxware.mgmt.CustomerManager
log4j.category.com.taxware.mgmt.CustomerManager=WARN
######## APPENDERS:
# FILE_INFO
# Type of appender
log4j.appender.FILE_INFO=org.apache.log4j.RollingFileAppender
# File where to save all messages
log4j.appender.FILE_INFO.File=D:/CSVExportLogs/CSVExportLogFile-INFO.log
# Max file size, after that will be created new log file, and old file will be renamed
log4j.appender.FILE_INFO.MaxFileSize=100KB
# Maximum amount of old log files.
log4j.appender.FILE_INFO.MaxBackupIndex=100
# Patter of messages.
log4j.appender.FILE_INFO.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE_INFO.layout.ConversionPattern=%d{ISO8601} [%-5p][%-24.24t][%32.32c] - %m%n
# Custom level for appender. In this file will be add only messages with level INFO or highter
log4j.appender.FILE_INFO.Threshold=INFO
# FILE_WARN file appender
log4j.appender.FILE_WARN=org.apache.log4j.RollingFileAppender
log4j.appender.FILE_WARN.File=D:/CSVExportLogs/CSVExportLogFile-WARN.log
log4j.appender.FILE_WARN.MaxFileSize=50KB
log4j.appender.FILE_WARN.MaxBackupIndex=10
log4j.appender.FILE_WARN.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE_WARN.layout.ConversionPattern=%d{ISO8601} [%-5p][%-24.24t][%32.32c] - %m%n
# Custom level for appender. In this file will be add only messages with level WARN or highter
log4j.appender.FILE_WARN.Threshold=WARN
For logging the messages of specific class you could do following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="myClassAppender" class="org.apache.log4j.FileAppender">
<param name="File" value="../logs/myClassLogs.log"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n"/>
</layout>
</appender>
.............
<logger name="com.my.package.MySpecificClass">
<!--
all log messages of level "debug" or higher will be logged, unless defined otherwise
all log messages for "MySpecificClass" will be logged to the appender "myClassAppender"
-->
<level value="DEBUG"/>
<appender-ref ref="myClassAppender"/>
</logger>
.............
</log4j:configuration>
Here is the link.
http://veerasundar.com/blog/2011/05/log4j-tutorial-writing-different-log-levels-in-different-log-files/
I say this act in log4j levels:
All < Debug < Info < Warn < Error < Fatal < Off
With your configuration, happen thease:
All logs with "com.taxware.mgmt.CustomerManager" category and "Warn" and smaller level("Error" < Fatal) send for "FILE" appender and don't send for "FILE" appender because you set additivity attribute to false for it.
All logs with any category except "com.taxware.mgmt.CustomerManager" send for "FILE1" appender.
3.You say:"By the above xml I am getting only info messages in the FILE1". You trying logging log with "Warn" or smaller levels(Such as "Error") and "com.taxware.mgmt.CustomerManager" category, you will see result in "FILE" appender and also trying logging with another category and you will see result in "FILE1" appender, except this result is wrong. please do this and say result.
I also suggest you use SLF4J for decoupling API and implementation.

Log4j: How to configure simplest possible file logging?

My story:
I want to make a thing which is as simple as a simplest possible log4j logger that logs rows to a file. I have found several examples with some functionality, but not a basic, general one that really works, and not one with an explanation how the each row work.
Question:
Could anybody provide one?
Prerequisites:
I already know where to put the file and I have the log4j configured and working for console logging.
Now I want to log to a file and also find the file from file system once the program has run.
Rows needed to be added to the existing log4j.properties file are the desired output.
I have one generic log4j.xml file for you:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="false">
<appender name="default.console" class="org.apache.log4j.ConsoleAppender">
<param name="target" value="System.out" />
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
</layout>
</appender>
<appender name="default.file" class="org.apache.log4j.FileAppender">
<param name="file" value="/log/mylogfile.log" />
<param name="append" value="false" />
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
</layout>
</appender>
<appender name="another.file" class="org.apache.log4j.FileAppender">
<param name="file" value="/log/anotherlogfile.log" />
<param name="append" value="false" />
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
</layout>
</appender>
<logger name="com.yourcompany.SomeClass" additivity="false">
<level value="debug" />
<appender-ref ref="another.file" />
</logger>
<root>
<priority value="info" />
<appender-ref ref="default.console" />
<appender-ref ref="default.file" />
</root>
</log4j:configuration>
with one console, two file appender and one logger poiting to the second file appender instead of the first.
EDIT
In one of the older projects I have found a simple log4j.properties file:
# For the general syntax of property based configuration files see
# the documentation of org.apache.log4j.PropertyConfigurator.
# The root category uses two appenders: default.out and default.file.
# The first one gathers all log output, the latter only starting with
# the priority INFO.
# The root priority is DEBUG, so that all classes can be logged unless
# defined otherwise in more specific properties.
log4j.rootLogger=DEBUG, default.out, default.file
# System.out.println appender for all classes
log4j.appender.default.out=org.apache.log4j.ConsoleAppender
log4j.appender.default.out.threshold=DEBUG
log4j.appender.default.out.layout=org.apache.log4j.PatternLayout
log4j.appender.default.out.layout.ConversionPattern=%-5p %c: %m%n
log4j.appender.default.file=org.apache.log4j.FileAppender
log4j.appender.default.file.append=true
log4j.appender.default.file.file=/log/mylogfile.log
log4j.appender.default.file.threshold=INFO
log4j.appender.default.file.layout=org.apache.log4j.PatternLayout
log4j.appender.default.file.layout.ConversionPattern=%-5p %c: %m%n
For the description of all the layout arguments look here: log4j PatternLayout arguments
<?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 name="fileAppender" class="org.apache.log4j.RollingFileAppender">
<param name="Threshold" value="INFO" />
<param name="File" value="sample.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" />
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="fileAppender" />
</root>
</log4j:configuration>
Log4j can be a bit confusing. So lets try to understand what is going on in this file:
In log4j you have two basic constructs appenders and loggers.
Appenders define how and where things are appended. Will it be logged to a file, to the console, to a database, etc.? In this case you are specifying that log statements directed to fileAppender will be put in the file sample.log using the pattern specified in the layout tags. You could just as easily create a appender for the console or the database. Where the console appender would specify things like the layout on the screen and the database appender would have connection details and table names.
Loggers respond to logging events as they bubble up. If an event catches the interest of a specific logger it will invoke its attached appenders. In the example below you have only one logger the root logger - which responds to all logging events by default. In addition to the root logger you can specify more specific loggers that respond to events from specific packages. These loggers can have their own appenders specified using the appender-ref tags or will otherwise inherit the appenders from the root logger. Using more specific loggers allows you to fine tune the logging level on specific packages or to direct certain packages to other appenders.
So what this file is saying is:
Create a fileAppender that logs to
file sample.log
Attach that appender to the root
logger.
The root logger will respond to any
events at least as detailed as
'debug' level
The appender is configured to only
log events that are at least as
detailed as 'info'
The net out is that if you have a logger.debug("blah blah") in your code it will get ignored. A logger.info("Blah blah"); will output to sample.log.
The snippet below could be added to the file above with the log4j tags. This logger would inherit the appenders from <root> but would limit the all logging events from the package org.springframework to those logged at level info or above.
<!-- Example Package level Logger -->
<logger name="org.springframework">
<level value="info"/>
</logger>
Here's a simple one that I often use:
# Set up logging to include a file record of the output
# Note: the file is always created, even if there is
# no actual output.
log4j.rootLogger=error, stdout, R
# Log format to standard out
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %5p\t[%d] [%t] (%F:%L)\n \t%m%n\n
# File based log output
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=owls_conditions.log
log4j.appender.R.MaxFileSize=10000KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern= %5p\t[%d] [%t] (%F:%L)\n \t%m%n\n
The format of the log is as follows:
ERROR [2009-09-13 09:56:01,760] [main] (RDFDefaultErrorHandler.java:44)
http://www.xfront.com/owl/ontologies/camera/#(line 1 column 1): Content is not allowed in prolog.
Such a format is defined by the string %5p\t[%d] [%t] (%F:%L)\n \t%m%n\n. You can read the meaning of conversion characters in log4j javadoc for PatternLayout.
Included comments should help in understanding what it does. Further notes:
it logs both to console and to file; in this case the file is named owls_conditions.log: change it according to your needs;
files are rotated when they reach 10000KB, and one back-up file is kept
Here is a log4j.properties file that I've used with great success.
logDir=/var/log/myapp
log4j.rootLogger=INFO, stdout
#log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.DailyRollingFileAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{MM/dd/yyyy hh:mm:ss a}|%-5p|%-30c{1}| %m%n
log4j.appender.stdout.DatePattern='.'yyyy-MM-dd
log4j.appender.stdout.File=${logDir}/myapp.log
log4j.appender.stdout.append=true
The DailyRollingFileAppender will create new files each day with file names that look like this:
myapp.log.2017-01-27
myapp.log.2017-01-28
myapp.log.2017-01-29
myapp.log <-- today's log
Each entry in the log file will will have this format:
01/30/2017 12:59:47 AM|INFO |Component1 | calling foobar(): userId=123, returning totalSent=1
01/30/2017 12:59:47 AM|INFO |Component2 | count=1 > 0, calling fooBar()
Set the location of the above file by using -Dlog4j.configuration, as mentioned in this posting:
java -Dlog4j.configuration=file:/home/myapp/config/log4j.properties com.foobar.myapp
In your Java code, be sure to set the name of each software component when you instantiate your logger object. I also like to log to both the log file and standard output, so I wrote this small function.
private static final Logger LOGGER = Logger.getLogger("Component1");
public static void log(org.apache.log4j.Logger logger, String message) {
logger.info(message);
System.out.printf("%s\n", message);
}
public static String stackTraceToString(Exception ex) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
return sw.toString();
}
And then call it like so:
LOGGER.info(String.format("Exception occurred: %s", stackTraceToString(ex)));

Categories

Resources