i want to implement spring 5 with log4j2 profile, like dev, qa and prod.
At present, This is how i run my spring 5 with log4j2, i load the log4j2 properties in command line:
mvn tomcat8:run -Dlog4j.configurationFile=file:%path_to_log4j2_prop%/log4j2.properties
and this is my log4j2 properties:
status = debug
name = PropertiesConfig
#Make sure to change log file path as per your need
property.environment=D:/WhiteCoats-New-Workspace/spring-5
property.servicesfilename = ${environment}/wc.out
filters = threshold
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
appenders = services
appender.services.type = RollingFile
appender.services.name = ServiceFile
appender.services.fileName = ${servicesfilename}
appender.services.filePattern = ${environment}/wc.out-%d{yyyy-MM-dd}-%i
appender.services.layout.type = PatternLayout
appender.services.layout.pattern = [ %d{yyyy-MMM-dd HH:mm:ss a} ] - [%t] %-5level %logger{36} - %msg%n
appender.services.policies.type = Policies
appender.services.policies.time.type = TimeBasedTriggeringPolicy
appender.services.policies.time.interval = 1
appender.services.policies.time.modulate = true
appender.services.policies.size.type = SizeBasedTriggeringPolicy
appender.services.policies.size.size=5MB
appender.services.strategy.type = DefaultRolloverStrategy
appender.services.strategy.max = 10
loggers = services
#services logs
logger.services.name = com.vm
logger.services.level = debug
logger.services.additivity = false
logger.services.appenderRef.services.ref = ServiceFile
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = ServiceFile
In spring 3, i used log4j and configured the path in web.xml.
how do i implement profiles for log4j2 for spring 5?
In Spring Boot, if you need to change the property log4j.configurationFile it is very simple within the application.yml. You define the default, and the override value in case you use a profile. For example:
log4j:
configurationFile: %path_to_log4j2_prop%
---
spring:
profiles: development
log4j:
configurationFile: %path_to_dev_log4j2_prop%
---
spring:
profiles: production
log4j:
configurationFile: %path_to_prod_log4j2_prop%
If you use Spring only, than you can use #Configuration with #Profile and #PropertySource to load different property files according to your profile, and in those files you can set your log4j.configurationFile property based on your needs.
Related
I am implementing log4j2 in my java application where I trying to write data to console using log4j2 configuration file. I have created a jar called Interface.jar . Soft Links are created for this jar and are run with different arguments . 2 soft links created are Interface1 and Interface2 with different arguments . Interface1 and Interface2 have different log4j2 configuration file path.
System.setProperty("log4j.configurationFile", System.getenv("LOG4J_INTERFACE1"));
System.setProperty("log4j.configurationFile", System.getenv("LOG4J_INTERFACE2"));
Log4j Configuration File For Interface1 is :
status = warn
appenders=console
property.LOG_PATTERN = %d{yyyy-MM-dd} %d{HH:mm:ss,SSS zzz}|%p|INTERFACE1||||||%m%n
appender.console.type = Console
appender.console.name = LogToConsole
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = ${LOG_PATTERN}
logger.Log4JExample.name = Log4JExample
logger.Log4JExample.level = debug
logger.Log4JExample.additivity = false
logger.Log4JExample.appenderRef.console.ref = LogToConsole
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = LogToConsole
Log4j Configuration File For Interface2 is :
status = warn
appenders=console
property.LOG_PATTERN = %d{yyyy-MM-dd} %d{HH:mm:ss,SSS zzz}|%p|INTERFACE2||||||%m%n
appender.console.type = Console
appender.console.name = LogToConsole2
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = ${LOG_PATTERN}
logger.Log4JExample.name = Log4JExample
logger.Log4JExample.level = debug
logger.Log4JExample.additivity = false
logger.Log4JExample.appenderRef.console.ref = LogToConsole2
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = LogToConsole2
The issue is that when I start both the process , Interface1 is able to write to console but Interface2 is not able to do so. Both the process are running fine. One challenge I see is that both these jars have save main class Interface.class .
LogManager.getLogger(Interface.class);
Can anyone shed some light on how can I stream the data to console from multiple processes using soft links.
Need to have 2 appenders. You can use give all the appenders with comma separated.
I can see both loggers have different format and both needs to write the console. In those cases you need to use Marker filter for different loggers.
below is the sample log4j2.properties file
appenders = console, console1
appender.console.type = Console
appender.console.name = LogToConsole
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd} %d{HH:mm:ss,SSS zzz}|%p|INTERFACE1||||||%m%n
appender.console1.type = Console
appender.console1.name = LogToConsole2
appender.console1.layout.type = PatternLayout
appender.console1.layout.pattern = %d{yyyy-MM-dd} %d{HH:mm:ss,SSS zzz}|%p|INTERFACE2||||||%m%n
loggers = rolling, interface2
logger.rolling.name = org.apache.logging.log4j.core.appender.rolling
#configure rootLogger and attach all the appenders to it
rootLogger.level = info
rootLogger.appenderRef.console.ref = LogToConsole
logger.interface2.name = Interface2
logger.interface2.additivity = false
logger.interface2.level = debug
logger.interface2.appenderRef.console1.ref = LogToConsole2
It seems you are setting a system property like so:
System.setProperty("log4j.configurationFile", System.getenv("LOG4J_INTERFACE1"));
while you should be setting log4j2.configurationFile.
Notice the log4j2 prefix.
I also recommend setting another system property
java -Dlog4j2.debug=true ...
just to see more what log4j2 is doing. You can turn it off once you are happy.
I created a custom appender and it's not getting called when I run my test. Here's what the properties look like:
name=config
appenders=console, myCustomAppender
appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=PatternLayout
#appender.console.layout.pattern =%d{HH:mm:ss} [%t] %c{1} [%-5level] - %msg%n
appender.console.layout.pattern=%d{dd-MM-yyyy HH:mm:ss} [%-5p] (%F:%L) - %m%n
appender.myCustomAppender = com.myCompany.logging.log4j.WindowsEventLogAppender
appender.myCustomAppender.name = WindowsEventLogAppender
appender.myCustomAppender.type = WindowsEventLogAppender
rootLogger.level=info
rootLogger.appenderRefs=stdout, myCustomAppender
rootLogger.appenderRef.stdout.ref=STDOUT
My appender is called a WindowsEventLogAppender. Any idea what's wrong with my properties file? I see the console test messages but none of the messages from my appender. Right now I'm just doing a System.out.println in my custom appender to verify it's getting called.
BTW, I've found lot's of XML examples out there for log4j2 configurations with custom appenders but none for using a properties file for configuration.
Thanks,
-Mike
I might be quite late here, but I think my answer can help other people looking for answers. Please accept this as an answer if this is correct!
If you have created a custom appender having annotation like this:
#Plugin(name = "MyCustomAppender", category = "Core",
elementType = "appender", printObject = true)
public final class MyCustomAppenderImpl extends AbstractAppender {
// other code for the plugin....
}
The log4j2 manual about Configuring Appenders states that:
"An appender is configured either using the specific appender plugin's name or with an appender element and the type attribute containing the appender plugin's name"
Meaning the type for appender should be Appender Plugin's Name attribute value.
Which in above case is MyCustomAppender (appender.identifierName.type=MyCustomAppender)
So, the Properties file configuration for this to work should be:
(Note : I have added a stdout(console) appender just to show
relevance/similarity of usage with OOTB appenders, and 2 example
usages with RootLogger and a custom logger)
# this packages attribute is important, please put comma seperated package(s) to the
# plugin(s) you have created
packages = com.package.to.your.plugin
# Example: Declare and Define OOTB Console appender, which sends log events to stdout
appender.console.name = stdout
appender.console.type = Console
# Declare and define the custom appender like this
# Note that the "abc" in "appender.abc.type" can be anything
# and the value for "appender.abc.type" should be the same as
# "Name" attribute value given in custom appender plugin which is "MyCustomAppender"
appender.abc.name=arbitrary_name
appender.abc.type=MyCustomAppender
rootLogger.appenderRef.stdout.ref = stdout
rootLogger.appenderRef.abc.ref = arbitrary_name
logger.loggeridentifier.name = com.test.SomeClass
logger.loggeridentifier.appenderRef.stdout.ref = stdout
logger.loggeridentifier.appenderRef.abc.ref = arbitrary_name
# Also note that the value of appenderRef should be the same name given to your
# appender in properties file, which in this case is "arbitrary_name" (as given above)
Try adding the packages property.
Like: packages = com.myCompany
You haven't included the package info
try the below configuration.
name=config
appenders=console, myCustomAppender
appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=PatternLayout
#appender.console.layout.pattern =%d{HH:mm:ss} [%t] %c{1} [%-5level] - %msg%n
appender.console.layout.pattern=%d{dd-MM-yyyy HH:mm:ss} [%-5p] (%F:%L) - %m%n
appender.myCustomAppender = com.myCompany.logging.log4j.WindowsEventLogAppender
appender.myCustomAppender.name = WindowsEventLogAppender
appender.myCustomAppender.type = WindowsEventLogAppender
rootLogger.level=info
rootLogger.appenderRefs=stdout, myCustomAppender
rootLogger.appenderRef.stdout.ref=STDOUT
rootLogger.com.mycompany.example=INFO,STDOUT
After upgrading to Log4j2, error logs are printing to console during unit tests execution.
I tried to add status=FATAL in the configuration file to avoid error printing on console.
# ----------------------------------------------------------------
# LOGGING
# ----------------------------------------------------------------
# Note - this section is similar to the log4j2 properties syntax
# https://logging.apache.org/log4j/2.x/manual/configuration.html#Properties
status=FATAL;
test.*.log4j2.rootLogger.level=INFO;
*.*.log4j2.rootLogger.level=INFO;
*.*.log4j2.rootLogger.appenderRefs=(APPLICATION);
*.*.log4j2.appenders=(APPLICATION);
*.*.log4j2.appender.APPLICATION.type=AmazonRollingRandomAccessFile;
*.*.log4j2.appender.APPLICATION.name=APPLICATION;
*.*.log4j2.appender.APPLICATION.filePattern="var/output/logs/$APP.%d{yyyy-MM-dd-HH}";
*.*.log4j2.appender.APPLICATION.layout.type=PatternLayout;
# Standard log format but with the purchase id appended after the message.
# This location is to not break rtla processing, which parses everything up-to & including the logger (%c)
*.*.log4j2.appender.APPLICATION.layout.pattern="%d{DATE} [%p] %X{RequestId} (%t) %c: %m [Purchase: %X{PurchaseId}]%n";
The reference doc.
But seems it is not taking status into consideration and it is still printing logs on console.
I tried with all the options below as well, but no luck:
status=FATAL; ..log4j2.status=INFO; ..log4j2.status=ERROR;
The status of the Configuration only relates to the internal logging of log4j2 itself, i.e. you can use it to debug your configuration of log4j2, but it is not used for your actual application.
If you want to disable all logging for your application, you can set the ThresholdFilter of your configuration to off:
filter.threshold.type = ThresholdFilter
filter.threshold.level = off
or you can set your root logger to level = off (provided you don't have any other loggers defined):
rootLogger.level = off
A complete example of something that would work:
status = warn
name = TestConfig
filter.threshold.type = ThresholdFilter
filter.threshold.level = off
appender.list.type = List
appender.list.name = List
appender.list.filter.threshold.type = ThresholdFilter
appender.list.filter.threshold.level = trace
logger.whatever.name = com.relentlesscoding.logging
logger.whatever.level = trace
logger.whatever.additivity = false
logger.whatever.appenderRef.whatever.ref = List
rootLogger.level = trace
Introduction
I've been looking for this fix for some time now but no luck so far. I'm building a Java webapp which uses embedded Tomcat as servlet. I have set log4j as my main logger and the logs post to the file specified successfully. Because the Tomcat is embedded I cannot find this catalina.out file that I've seen in so many answers through SO and other forums.
Problem
What I want is to make Tomcat log with log4j to the same file I use for logging for the whole webapp. How can I do this? Is there a way to do this programmatically?
P.S. :
I'm using Windows as an OS and the Tomcat version is 8.0.30
By default tomcat uses [CATALINA_HOME]/conf/logging.properties. In there edit the below properties:
1catalina.org.apache.juli.AsyncFileHandler.level = FINE
1catalina.org.apache.juli.AsyncFileHandler.directory = **YOUR_PATH_HERE**
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.
Turns out it was way simpler than I thought, so I'm just leaving the answer here for anyone who might have the same problem.
I made a function initializeLogging()
private static void initializeLogging()
{
//Getting the current timestamp to use in log file naming
Calendar calendar = Calendar.getInstance();
java.text.DateFormat df = new java.text.SimpleDateFormat("yyMMddHHmmss");
String timestamp = df.format(calendar.getTime());
ConfigurationBuilder< BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setStatusLevel(Level.ALL);
builder.setConfigurationName("RollingBuilder");
// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout")
.addAttribute("pattern", "<%d{yyyy/MM/dd HH:mm:ss}> %p (%t). %m%n"));
builder.add(appenderBuilder);
// create a rolling file appender
LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
.addAttribute("pattern", "<%d{yyyy/MM/dd HH:mm:ss}> %p (%t). %m%n");
ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
.addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "100M"));
//specifying log file name as well ss log file name if the first exceeds maximum size => 100M
appenderBuilder = builder.newAppender("rolling", "RollingFile")
.addAttribute("fileName", "logs/myLogging" + "_" + timestamp + ".log")
.addAttribute("FilePattern","logs/myLogging"+"_"+ timestamp + "%d{yyyyMMddHHmmss}" + ".log")
.add(layoutBuilder)
.addComponent(triggeringPolicy);
builder.add(appenderBuilder);
// create the new logger
builder.add(builder.newLogger("myLogger", Level.ALL)
.add(builder.newAppenderRef("rolling"))
.addAttribute("additivity", false));
builder.add(builder.newRootLogger(Level.ALL)
.add(builder.newAppenderRef("rolling")));
LoggerContext ctx = Configurator.initialize(builder.build());
}
so what this function does is to give a pattern at each entry to the logs and direct the logs to a file specified by me. Now every time I want to log something I just have to call Logger logger = LogManager.getLogger('myLogger)
So there it is a quick programmatic only log4j initialization.
I have two log4j loggers in each of my classes in my code :
logA = Logger.getLogger(com.some.class.in.my.project);
logB = Logger.getLogger('perf');
I want these two loggers to output data into two COMPLETELY different files. I can't seem to get it to work.
Here are my log4j properties :
log4j.rootLogger = myAppenderA
# A
log4j.appender.myAppenderA=org.apache.log4j.RollingFileAppender
log4j.appender.myAppenderA.File=../logs/mylogfileA.log
log4j.appender.myAppenderA.additivity=false
log4j.appender.myAppenderA.Threshold=DEBUG
log4j.appender.myAppenderA.layout=org.apache.log4j.PatternLayout
log4j.appender.myAppenderA.layout.ConversionPattern=%d{ISO8601} %-5p 0 %m%n
# perf
log4j.appender.perf=org.apache.log4j.RollingFileAppender
log4j.appender.perf.File=..logs/perf.log
log4j.appender.perf.additivity=false
log4j.appender.perf.Threshold=DEBUG
log4j.appender.perf.layout=org.apache.log4j.PatternLayout
log4j.appender.perf.layout.ConversionPattern=%d{ISO8601} %-5p 0 %m%n
log4j.logger.myAppenderB = perf
Both myLogfileA.log and perf.log contain the same data. Supposedly setting additivity to false fixes this, but i have tried it and it has little affect.
Additivity is a property of the logger not the appender so you have to remove additivity property from appender and add it to your loggers configuration.
Currently you have only the rootLogger configuration in the file (and you are not defining the logging level for it) so all your loggers will extend the appenders from it. To stop logging messages propagation to ancestors you have to use the additivity property on the logger. So to achieve what you want you have:
Define one more appender (root) for rootLogger. It will be the default one and inherited by other loggers which don't have additivity = false
Assign myAppenderA appender to mypackage.MyClass logger
Assign pref appender to pref logger
Set additivity of myAppenderA and pref loggers to false to stop log message propagation to ancestor loggers.
There is the hole properties file:
log4j.rootLogger = DEBUG, root
# Root
log4j.appender.root=org.apache.log4j.RollingFileAppender
log4j.appender.root.File=logs/mainLogInheritable.log
log4j.appender.root.Threshold=DEBUG
log4j.appender.root.layout=org.apache.log4j.PatternLayout
log4j.appender.root.layout.ConversionPattern=%d{ISO8601} %-5p 0 %m%n
# A
log4j.appender.myAppenderA=org.apache.log4j.RollingFileAppender
log4j.appender.myAppenderA.File=logs/mylogfileA.log
#log4j.appender.myAppenderA.additivity=false
log4j.appender.myAppenderA.Threshold=DEBUG
log4j.appender.myAppenderA.layout=org.apache.log4j.PatternLayout
log4j.appender.myAppenderA.layout.ConversionPattern=%d{ISO8601} %-5p 0 %m%n
# perf
log4j.appender.perf=org.apache.log4j.RollingFileAppender
log4j.appender.perf.File=logs/perf.log
#log4j.appender.perf.additivity=false
log4j.appender.perf.Threshold=DEBUG
log4j.appender.perf.layout=org.apache.log4j.PatternLayout
log4j.appender.perf.layout.ConversionPattern=%d{ISO8601} %-5p 0 %m%n
log4j.logger.mypackage.MyClass = DEBUG, myAppenderA
log4j.logger.perf = DEBUG, perf
log4j.additivity.perf = false
log4j.additivity.mypackage.MyClass = false
To test if it is logging to three different files you can try this:
Logger.getLogger("mypackage.MyClass").debug("1111");
Logger.getLogger("perf").debug("2222");
Logger.getLogger("anyName").debug("3333");