log4j2 - duplicating logs in Console & RollingFile - log4j2

hey I was wondering if it possible to have the same output in Console as in the file output.
Here is my XML config.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="log4j2 Logs">
<Properties>
<Property name="basePath">./logs</Property>
</Properties>
<Appenders>
<RollingFile name="file" fileName="${basePath}/ActivateMaintenancePage.logs"
filePattern="${basePath}/ActivateMaintenancePage-%d{yyyy-MM-dd}">
<PatternLayout header="LOGGING START%n%n" footer="%n%nLOGGING END"
pattern="%3sn %30d{DEFAULT} [%M] %-7level %c{30} - %m%n" />
<Policies>
<OnStartupTriggeringPolicy minSize="0"/>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="500 MB"/>
</Policies>
</RollingFile>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout header="LOGGING START%n%n" footer="%n%nLOGGING END"
pattern="%3sn %30d{DEFAULT} [%M] %-7level %c{30} - %m%n" />
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="console" level="error"/>
<AppenderRef ref="file" level="trace"/>
</Root>
</Loggers>
</Configuration>
Output in RollingFile
1 2017-07-25 11:16:36,762 [initializeChrome] INFO class testNG.SimSettings - Web Chrome driver is now initilized.
2 2017-07-25 11:16:36,762 [lambda$0] INFO class testNG.SimSettings - Opening... http://msrvaq11vm.technomedia.ca/sigal_60/2017sp1/sp_polymont/_sim/PROD Sp2 2016 Sim...
3 2017-07-25 11:16:47,926 [initilizeAllElements] INFO class testNG.SimSettings - All #FindBy elements have been initilized.
4 2017-07-25 11:16:48,006 [change1stLevelFrame] INFO class testNG.SimSettings - Changing target to 1st level frame.
5 2017-07-25 11:16:49,719 [enterCredentials] INFO class testNG.SimSettings - UserName & Password: Success!
and empty in Console. But now if I change
<AppenderRef ref="console" level="error"/>
to "trace"
It will be 2,4,6....in console and in my file it will be 1,3,5,7... which is easily understandable.
But my question is how can we have both the same log-level (trace) output in Console and File?
(adding tag with package name and level did not work)
Related to this question: log4j2 xml configuration - Log to file and console (with different levels)

I'm not sure if I read your question correctly but it seems that you want to render some unique value in the log output, such that the same log event has the same unique value in the Console log and the File log output.
The sequence number pattern converter will increment every time a log event is rendered. The same log event is rendered separately for each Appender, so different Appenders will never have the same sequence number.
There are a number of alternatives. One idea is to include %nano nanotime in the pattern layout. This value is captured when the application makes the logging call and will be the same for all appenders. An alternative is to create a custom Log4j2 pattern converter or lookup.

Related

Using RoutingAppender in commerical product programmatically

I have a commerical product, using log4j2 internally.
I can add java/groovy script as an internal api. Here I can also use log4j2 as logger
Each script is running within a thread.
The logging for each of the scripts, I want have a own logfile (and all subordinate loggers)
Before I start within the product, I was playing with Log4J2 locally, using the RoutingAppender examples.
RoutingAppender: it works as expected when I have a log4j2.xml during startup.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout
pattern="myCONSOLE - [%d] [%-5p] [%-7t] - %m%n" />
</Console>
<Routing name="Routing">
<Routes pattern="$${ctx:ROUTINGKEY}">
<Route>
<RollingFile name="Rolling-${ctx:ROUTINGKEY}"
fileName="logs/test-${ctx:ROUTINGKEY}.log"
filePattern="./logs/test-${ctx:ROUTINGKEY}-%d{yyyyMMdd}-%i.log.gz">
<PatternLayout>
<pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="6"
modulate="true" />
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
</RollingFile>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="ALL">
<AppenderRef ref="STDOUT" />
<AppenderRef ref="Routing" />
</Root>
</Loggers>
</Configuration>
In the code I use parts as:
In the script script (simulated), I do ThreadContext.put("ROUTINGKEY", "exampleA"); , in a second script I use "exampleB".
In main programm I set:
static {
System.setProperty("isThreadContextMapInheritable", "true"); // So all objects/loggers in same thread will inherit the ThreadC
}
Other classes/objects are created as usual with normal logger technique: private static Logger logger = LogManager.getLogger(Grassfrosch.class);; and using logger.info....
All logging was in correct logfile including the subordinate elements.
Back to the commerical product. Here I want to add the RoutingAppender (and the RollingFileAppender) dynamically with programming code in the groovy scripts.
Script "exampleA" should add the route for the own part by itself
Script "exampleB" should add the route for the own part by itself
I don't want to use the product config file itself due to product upgrades/patches, overwritten by the manufacturer.
So, I also implemented locally such logic "programmatically approach".
I create a FileAppender/RollingFileAppender
I create a Routes plus Route(s) object
I create a RoutingAppender, adding the routes etc.
Simplified code is:
private void fragment() {
Configuration cfg;
org.apache.logging.log4j.core.Logger rl = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger();
cfg = rl.getContext().getConfiguration();
String name = "exampleA";
PatternLayout layout = PatternLayout.newBuilder().withPattern("DYNAMIC[" + name + "] - %d [%p] - %m%n").build();
FileAppender fileAppender = FileAppender.newBuilder() //
.setName("FileAppender-" + name).withFileName("logs/FileAppender-" + name + ".log") //
.withAppend(true).setLayout(layout) //
// .setConfiguration(cfg)
.build();
fileAppender.start();
rl.addAppender(fileAppender);
Route route01 = Route.createRoute("FileAppender-" + name , name, null);
Routes routes = Routes.newBuilder().withPattern("$${ctx:ROUTINGKEY}").withRoutes(new Route[] { route01}).build();
RoutingAppender routingAppender = RoutingAppender.newBuilder().setName("EPI-Routing").withRoutes(routes) //
.setConfiguration(cfg) //
.build();
routingAppender.start();
rl.addAppender(routingAppender);
rl.getContext().updateLoggers();
}
With this code, both scripts "exampleA" and "exampleB", will written to both logfiles "FileAppender-exampleA" and "FileAppender-exampleB" and not as expected in the "log4j2.xml" example.
I guess, the problem is:
I have to add a FileAppender to existing configuration
due to I have to "reference" Route.createRoute.
Finally the FileAppender I have added to rootlogger (wrong).
I also try to add to script logger, but no success.
I stuck. Any hints?
Uwe

log4j2 Delete on Rollover

I read the official document of log4j2 and get a question about RollingFileAppender.
That's what the document says:
Below is a sample configuration that uses a RollingFileAppender with both the time and size based triggering policies, will create up to 100 archives on the same day (1-100) that are stored in a directory based on the current year and month, and will compress each archive using gzip and will roll every hour. During every rollover, this configuration will delete files that match "/app-.log.gz" and are 30 days old or older, but keep the most recent 100 GB or the most recent 10 files, whichever comes first.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Properties>
<Property name="baseDir">logs</Property>
</Properties>
<Appenders>
<RollingFile name="RollingFile" fileName="${baseDir}/app.log"
filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
<DefaultRolloverStrategy max="100">
<!--
Nested conditions: the inner condition is only evaluated on files
for which the outer conditions are true.
-->
<Delete basePath="${baseDir}" maxDepth="2">
<IfFileName glob="*/app-*.log.gz">
<IfLastModified age="30d">
<IfAny>
<IfAccumulatedFileSize exceeds="100 GB" />
<IfAccumulatedFileCount exceeds="10" />
</IfAny>
</IfLastModified>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
I think this configuration will create up to 100 archives on the same hour of the day, not 100 archives on the same day, can anybody who give me a hand? Thanks!
Yes, it will keep up to 100 files in the hour but in reality it will never get that high since it is only keeping a maximum of 10 files overall.

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.

Log4j2 (beta9) How to configure custom layout for FileAppender?

Can someone tell me, How to configure custom layout for FileAppender?
Can anyone tell me, how to configure custom layout for FileAppender?
I'm created copy of HTMLLayout and made some changes there (it's cannot be extends because it's final class) and now I want use this layout, but I don't know how :(
This error is showed with bellow listed configuration:
ERROR File contains an invalid element or attribute "ibtrader.log4j2.MYHTMLLayout"
Here is my log4j2.xml configuration file
<?xml version="1.0" encoding="UTF-8"?>
<configuration strict="true" monitorInterval="30">
<appenders>
<appender name="Console" type="Console" target="SYSTEM_OUT">
<layout type="PatternLayout" pattern="%highlight{%d{ISO8601} [%t] %-5level %logger{36} - %msg%n}" />
</appender>
<appender name="DEBUG_FILE" type="File" fileName="logs/errors.txt" >
<layout type="PatternLayout" pattern="%d{ISO8601} [%t] %-5level %logger{36} - %msg%n}" />
</appender>
<appender name="HTMLAppender" type="File" fileName="logs/mainlog.html">
<layout type="ibtrader.log4j2.MYHTMLLayout" charset="UTF-8" title="IBTRader logs" locationInfo="true" />
</appender>
</appenders>
<loggers>
<root level="trace">
<appender-ref ref="Console"/>
<appender-ref ref="DEBUG_FILE" level="WARN" />
<appender-ref ref="HTMLAppender" />
</root>
</loggers>
</configuration>
Thanks for help!
The comments mention this is already fixed but just for completeness, a (simplified) configuration with a custom MYHTMLLayout plugin could look like this:
<?xml version="1.0" encoding="UTF-8"?>
<!-- the packages attribute contains a comma-separated list
of the packages that Log4J2 will scan for custom plugins. -->
<configuration packages="ibtrader.log4j2">
<appenders>
<appender name="HTMLAppender" type="File" fileName="logs/mainlog.html">
<!-- Each plugin has a *name*, declared with annotation on the
plugin implementation class.
The plugin name does not need to match the class name.
The plugin name needs to match the *type* attribute in the config.
For example:
package ibtrader.log4j2;
import ...;
#Plugin(name="MYHTMLLayout", category="Core",
elementType="layout", printObject=true)
public class MyHTMLLayoutImpl extends AbstractStringLayout {...
-->
<layout type="MYHTMLLayout" charset="UTF-8" title="IBTRader logs" locationInfo="true" />
</appender>
</appenders>
<loggers>
<root level="trace">
<appender-ref ref="HTMLAppender" />
</root>
</loggers>
</configuration>
You have to extend AbstractStringLayout, setting the #Plugin properties with category = "Core", elementType = "layout" and name="The name of the class itself that should be refered from the configuration file" (i.e.: "ExtHtmlLayout")
You could just copy the whole class HtmlLayout from the sources and change whatever you want, for example, the time in millis column to the time in hours.
Define the package property in "Configuration" tag to use the package to the extended class you have created.
Finally, just call the new layout from the configuration file:
<ExtHtmlLayout/>

Log4j2 Appender attributes with strict xml config

I'm using log4j2-beta9 and want to configure it using a log4j2.xml in strict mode.
My issue is: how do I specify attributes that are not in the shipped schema file?
An Example:
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration
status="DEBUG"
strict="true"
monitorInterval="5"
name="TestingAttributes"
verbose="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Log4j-config.xsd">
<Properties>
</Properties>
<Appenders>
<Appender
type="Console"
name="SYSERR"
target="SYSTEM_ERR"> <!-- cvc-complex-type.3.2.2: Attribute 'target' is not allowed to appear in element 'Appender'. -->
<Layout Type="PatternLayout">
<Pattern>%date{dd.MM.yyyy HH:mm:ss,SSS} %5p %logger %m%n</Pattern>
</Layout>
<Filters>
<Filter
type="MarkerFilter"
marker="FLOW"
onMatch="DENY"
onMismatch="NEUTRAL" />
<Filter
type="MarkerFilter"
marker="EXCEPTION"
onMatch="DENY"
onMismatch="NEUTRAL" />
</Filters>
</Appender>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="SYSERR" />
</Root>
</Loggers>
</Configuration>
Notice that I want to set the appender to have the target SYSTEM_ERR but the attribute is not allowed in strict mode.
target="SYSTEM_ERR"> <!-- cvc-complex-type.3.2.2: Attribute 'target' is not allowed to appear in element 'Appender'. -->
I could always edit the Log4j-config.xsd and allow that attribute there but that would be kind of wrong also because not all appenders have a target attribute.
As searching the web didn't help me so far, I'm asking you:
Is there anything I'm missing in configuring Log4j2 in strict XML mode?
Do I have to "patch" the XMLConfiguration and the schema file and commit a change to log4j or is there another way besides not using strict mode?
Thanks in advance.
Can you ask this on the log4j-user mailing list? It could be a bug in the schema, but I suspect the schema can do with more improvements and your feedback would be valuable.

Resources