Log4J2 Nested Property Substitution - log4j2

I am attempting to use Log4J2 property substitution to simplify my deployed log4j2.xml file. I want to share it between three deployed WAR files, so I've defined a system property detailing the external location of that file.
Now I've run into a different issue. I've added the following to my web.xml:
<context-param>
<param-name>loggingPrefix</param-name>
<param-value>app1</param-value>
</context-param>
In the log4j2.xml, I've created the following:
<Console name="CONSOLE_LOG" target="SYSTEM_OUT">
<PatternLayout pattern="$upper{${web:loggingPrefix}}> %d{dd MMM HH:mm:ss} %5p [%t] (%F:%L) - %m%n" />
</Console>
What happens is that the loggingPrefix is properly output, but the log entry only prints out as $upper{app1}. I have also attempted to specify the $upper as $$upper.
Have I simply made a dumb mistake in the pattern?
(Note: I can't just put the uppercase in the web.xml, I need the lowercase value when I start implementing the RollingFileAppender entries.)

Related

log4j2 and slf4j/logback differ in output in anylogic

I inherited an anylogic project where parts of the model logic have been implemented in a java project, from which this model is also launched.
This project has multiple logger configurations since in most parts of the project log4j2 is used, in few parts it is slf4j which uses the logback backend.
In the anylogic UI/Browser-Window, you can view some Console in which some output is printed:
Interestingly there are no logs printed, that haven been recorded with the log4j-library.
Those beeing recorded with slf4j and logback however, are also shown in the Console.
The appender configurations read like this:
# log4j2 appender
appender.console.type = Console
appender.console.name = consoleLogger
appender.console.target = SYSTEM_OUT
appender.console.layout.type = PatternLayout
<!--- logback.xml appender --->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%highlight(%d{yyyy.MM.dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}:%L - %msg%n)</pattern>
</encoder>
</appender>
Now for the question: What is difference between the two logging frameworks/appenders, that can cause the observed behavior?
It seems, the SYSTEM_OUT is reassigned after configuration.
If I set the Log4J2 Console Appender to follow
appender.console.follow = true
The log is also appended to the console in the AnyLogic UI.
Apparently logback follows by default.

Modify existing log4j2 FileAppender configuration during runtime

I am migrating application (huge web application) from log4j1.x to log4j 2.11.0.
I need help/clarification to migrate following scenarios -
--------scenario1
log4j1.x:
<appender name="import_log_file" class="xxxx">
During runtime i want to change the file so i would just do appender.setFile(...new file...). And done.
log4j2:
how do I migrate above code?
Few ideas but not a straight answer:
Creating brand new appender via LoggerContext, Configuration might be a way but i want to update an existing appender's configuration and reload the log4j2 xml. How do I do that?
Another way could be redefining something like this
<appender name="import_log_file" class="xxxx">
And then setup "dynamic_name" property in threadcontext. But I am loosing original default file import.log
Any help is appreciated. Let me know if you have ideas.
During runtime i want to change the file
You can use the RoutingAppender together with a lookup to do this. See the log4j2 FAQ page for details.
Here is a very simple example of how to change the log file name at runtime:
package pkg;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
public class Log4j2DiffFilePerCtxVarMain {
private static final Logger LOG = LogManager.getLogger();
public static void main(String[] args){
ThreadContext.put("myFileNameVar", "file1");
LOG.info("This should appear in file1.log");
ThreadContext.put("myFileNameVar", "file2");
LOG.info("This should appear in file2.log");
}
}
The configuration looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Routing name="myAppender">
<Routes pattern="$${ctx:myFileNameVar}">
<Route>
<File
fileName="logs/${ctx:myFileNameVar}.log"
name="myAppender-${ctx:myFileNameVar}">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="myAppender" />
</Root>
</Loggers>
</Configuration>
The result of running the above code will be two files - file1.log an file2.log each with a single entry. The file1.log will contain the first log message and file2.log will contain the second message.
Hope this helps!

DefaultRolloverStrategy does not delete any file

I used the following Log4j2 configuration to test the behavior. It rotates the file every 10 seconds and should keep only 3 files. However no file is deleted. What am I missing?
Please don't suggest to use the delete action.
<RollingFile name="File" fileName="/var/log/mylog.log" filePattern="/var/log/mylog-%d{yyyy-MM-dd-HH-mm-ss}.log.gz">
<PatternLayout>
<Pattern>${LOG_PATTERN}</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="10"/>
</Policies>
<DefaultRolloverStrategy max="3"/>
</RollingFile>
I realise this is an old question, but I had the same problem.
I also realise the OP said "Please don't suggest to use the delete action" so this may mean there are version restrictions on using Delete.
However I found this feature request which sheds some light on this behaviour - a comment there indicates.
DefaultRolloverStrategy max attribute only applies if you have a %i in
the file pattern.
The manual, under "Default Rollover Strategy", indicates
The default rollover strategy accepts both a date/time pattern and an
integer from the filePattern attribute specified on the
RollingFileAppender itself
and
max : integer : "The maximum value of the counter. Once this values is
reached older archives will be deleted on subsequent rollovers. The
default value is 7."
A bit a mix of "counter" and "integer" - but think (now) that it means this only applies to "%i" pattern. If the manual used "integer counter" it may be clearer.
A solution I got working (using 2.10.0 and days rather than seconds) using Delete (sorry OP) was:
<RollingFile name="MyLog" fileName="${sys:dataDir}/mylog.log" append="true">
<FilePattern>./mylog-%d{yyyy-MM-dd}.log.zip</FilePattern>
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level - %msg %logger{36}%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${sys:dataDir}" maxDepth="1">
<IfFileName glob="mylog-*.log.zip" />
<IfLastModified age="7d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile >

Lo4j config - Log to different files based on type of mesasge prefix

Hello I am using Log4j2 for my logging and I am little confused as to how I can log message to a different file based on the message prefix.
For example, currently all messages are logged in a single logs folder.
A set of my messages look like this:
'com.project.latency: ProjectName=[MooPointProject].......'
Some of my other log messages are of the format:
'com.project.latency: ProjectName=[DataPlaneProject].......'
I want to log the messages which contain the MooPointProject in a specific file and one containing DataPlaneProject in a separate log file.
Is there a specific way I can do that other than changing the logging level itself?
Set up several appenders one for each project name. For example:
<RollingFile name="RollingFile" fileName="logs/MooPointProject.log"
filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
<RegexFilter regex=".*MooPointProject.*" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<TimeBasedTriggeringPolicy />
</RollingFile>
and
<RollingFile name="RollingFile" fileName="logs/DataPlaneProject.log"
filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
<RegexFilter regex=".*DataPlaneProject.*" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<TimeBasedTriggeringPolicy />
</RollingFile>
Then assign both the appenders to your logger(s). Since your RegexpFilter accepts only a project-spcific lines you will get them to the appropriate files separately.
P.S. - Find the detail on other types of filters here.

Disable freemarker logs from logs4j

Similar question but i'm using log4j2.
I need a way to disable All logs from freemarker, in their documentation they say we can do it by calling Logger.selectLoggerLibrary(Logger.LIBRARY_NONE) but they say
selectLoggerLibrary must be called early, before FreeMarker could log anything, or else it will not have (consistent) effect.
Where do I call this in a struts2 application? (I tried calling it in prepare() method in my action class but its not working.) or is there any other way to disable the logs?
Question is, why do you need to disable it like that?
You shouldn't need that, so I guess that's where the real problem lies. Is there some kind of malfunction? Because if there isn't, why not just set the freemarker logger category to be ignored in your logger configuration? That's the normal way of doing this, FreeMarker or not.
Anyway, in 2.3.22 (release expected in early 2015) you can use the -Dorg.freemarker.loggerLibrary=none where you start the JVM (that is, you set the org.freemarker.loggerLibrary system property). Otherwise, if you could call that method in a ServletContextListener that's certainly early enough.
Update:
Reacting to the comments... in most applications you will have 3rd party libraries that use various logging "frameworks", like SLF4J, commons-logging, JUL, Log4j, Log4j2. Thus you have to ensure that all these get redirected into the same logger library, which is certainly Log4j2 in your case. I suspect that wasn't properly done in your case, so now multiple logger libraries log to the console, each with its own configuration settings.
FreeMarker 2.3.x uses Log4j 1.x if it detects that org.apache.log4j.Logger is present. Other logger libraries that it also can detect and use (Log4j2 is not amongst them) have lower priority. (FreeMarker 2.4.x will always use SLF4J if it's present.) Thus, if you add org.apache.logging.log4j:log4j-1.2-api to your dependencies, then FM will use org.apache.log4j.Logger, and so log4j-1.2.-api will redirect the FM log messages to Log4j2. That worked for me, with this Log4j2 configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console" />
</Root>
<Logger name="freemarker" level="off">
<AppenderRef ref="Console" />
</Logger>
</Loggers>
</Configuration>
This came up as the first search result for "disable freemarker logging" which I searched for because I got double error logs for template errors, one from within the Freemarker library and one from my own code catching the same exception and logging it. The solution to this is simple and different from the answers already given: call setLogTemplateExceptions(false) on the Freemarker Configuration. In full:
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
configuration.setLogTemplateExceptions(false);
The default behavior of logging the exception even though it propagates out of the Freemarker library is mentioned as a quirk on the Freemarker Logging documentation.
Use this statement:
freemarker.log.Logger.selectLoggerLibrary(freemarker.log.Logger.LIBRARY_NONE);

Resources