logging separate log files using log4j - log4j

i am trying to store my info level log amd error level log in separate files. My error messages are being dumped correctly but info messages contain both error as well as info messages. Following is my properties file:
log4j.rootLogger = DEBUG, inf, err
log4j.appender.inf = org.apache.log4j.FileAppender
log4j.appender.inf.layout = org.apache.log4j.PatternLayout
log4j.appender.inf.layout.ConversionPattern = %d{ISO8601} %-5p %c ~ %m%n
log4j.appender.inf.File = information.log
log4j.appender.inf.Threshold = INFO
log4j.appender.inf.filter = org.apache.log4j.varia.LevelMatchFilter
log4j.appender.inf.filter.levelToMatch = INFO
log4j.appender.inf.Append = false
log4j.appender.inf.AcceptOnMatch = true
log4j.appender.inf.filter = org.apache.log4j.varia.DenyAllFilter
log4j.appender.err = org.apache.log4j.FileAppender
log4j.appender.err.layout = org.apache.log4j.PatternLayout
log4j.appender.err.layout.ConversionPattern = %d{ISO8601} %-5p %c ~ %m%n
log4j.appender.err.File = errormsg.log
log4j.appender.err.Threshold = ERROR
log4j.appender.err.filter = org.apache.log4j.varia.LevelMatchFilter
log4j.appender.err.filter.levelToMatch = ERROR
log4j.appender.err.Append = false
and my .java file is as follows:
package test;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class HelloLogger {
private static Logger logger = Logger.getLogger(HelloLogger.class);
public static void main(String[] args) {
PropertyConfigurator.configure("log4jconfig.properties");
logger.error("This is error");
logger.info("This is info");
logger.debug("This is debug");
}
}
Pls help.. Thanx in advance

According to this answer, the properties file is not designed to handle filters, but it may work if you change your properties file to separate the first appender's filters with IDs (ie 1 and 2):
log4j.appender.inf.filter.1 = org.apache.log4j.varia.LevelMatchFilter
log4j.appender.inf.filter.1.levelToMatch = INFO
log4j.appender.inf.Append = false
log4j.appender.inf.AcceptOnMatch = true
log4j.appender.inf.filter.2 = org.apache.log4j.varia.DenyAllFilter

Related

how to configure KafkaAppender in log4j2 with Programmatic Configuration way?

code below is the example given by the apache log4j2 ,but how can i configure KafkaAppender in this way?
#Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
#Order(50)
public class CustomConfigurationFactory extends ConfigurationFactory {
static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
builder.setConfigurationName(name);
builder.setStatusLevel(Level.INFO);
// builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL).
// addAttribute("level", Level.DEBUG));
AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout").
addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
// appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY,
// Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
AppenderComponentBuilder kafkaAppender = builder.newAppender("Stdout", "CONSOLE").
addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
builder.add(appenderBuilder);
builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
add(builder.newAppenderRef("Stdout")).
addAttribute("additivity", false));
builder.add(builder.newRootLogger(Level.INFO).add(builder.newAppenderRef("Stdout")));
return builder.build();
}
}
i solved it ,
final AppenderComponentBuilder ddlKafkaAppender = builder.newAppender("ddl-kafka", "Kafka").addAttribute("topic", config.getDdlTopic());
ddlKafkaAppender.addComponent(builder.newProperty("bootstrap.servers", config.getHost()));
ddlKafkaAppender.add(builder.newLayout("PatternLayout").
addAttribute("pattern", "%message"));
builder.add(ddlKafkaAppender);
final AppenderComponentBuilder sqlKafkaAppender = builder.newAppender("sql-kafka", "Kafka").addAttribute("topic", config.getSqlTopic());
sqlKafkaAppender.addComponent(builder.newProperty("bootstrap.servers", config.getHost()));
sqlKafkaAppender.add(builder.newLayout("PatternLayout").
addAttribute("pattern", "%message"));
builder.add(sqlKafkaAppender);
builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
add(builder.newAppenderRef("Stdout")).
addAttribute("additivity", false));
builder.add(builder.newLogger("sql", Level.INFO).
add(builder.newAppenderRef("sql-kafka")));
builder.add(builder.newLogger("ddl", Level.INFO).
add(builder.newAppenderRef("ddl-kafka")));

log4j2 isThreadContextMapInheritable property usage

I am trying to log events of a Java application to separate log files based on a key set to the ThreadContext. But my key is not reaching the child thread (created on MouseEvent) even after setting "log4j2.isThreadContextMapInheritable" to "true" in system properties. Someone please help me to get this resolved.
My main method:
public class Application {
static {
System.setProperty("log4j2.isThreadContextMapInheritable","true");
}
private final static Logger LOGGER = LogManager.getLogger(Application.class);
public static void main(String[] args) throws Exception
{
ThreadContext.put("cfg","RLS");
LOGGER.info("New window opening!!!"+ThreadContext.get("cfg"));
newWindow();
}
private static void newWindow() throws Exception {
ButtonFrame buttonFrame = new ButtonFrame("Button Demo");
buttonFrame.setSize( 350, 275 );
buttonFrame.setVisible( true );
}
}
ButtonFrame class:
public class ButtonFrame extends JFrame{
private final static Logger LOGGER = LogManager.getLogger(NewWindow.class);
JButton bChange;
JFrame frame = new JFrame("Our JButton listener example");
public ButtonFrame(String title)
{
super( title );
setLayout( new FlowLayout() );
bChange = new JButton("Click Me!");
bChange.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
try {
LOGGER.info("Mouse clicked!!!"+ThreadContext.get("cfg"));
JDialog d = new JDialog(frame, "HI", true);
d.setLocationRelativeTo(frame);
d.setVisible(true);
} catch (Exception e1) {
e1.printStackTrace();
}
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
});
add( bChange );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
}
log4j2.properties file:
appenders = rls,otr,routing
appender.rls.type = RollingFile
appender.rls.name = RollingFile_Rls
appender.rls.fileName = D:\\RLS\\rls_%d{MMdd}.log
appender.rls.filePattern = D:\\RLS\\rls_%d{MMdd}.log
appender.rls.layout.type = PatternLayout
appender.rls.layout.pattern = %d{ABSOLUTE} %level{length=1}
%markerSimpleName [%C{1}:%L] %m%n
appender.rls.policies.type = Policies
appender.rls.policies.time.type = TimeBasedTriggeringPolicy
appender.rls.policies.time.interval = 1
appender.rls.policies.time.modulate = true
appender.rls.policies.size.type = SizeBasedTriggeringPolicy
appender.rls.policies.size.size = 100MB
appender.rls.strategy.type = DefaultRolloverStrategy
appender.rls.strategy.max = 5
appender.otr.type = RollingFile
appender.otr.name = RollingFile_Otr
appender.otr.fileName = D:\\RLS\\otr_%d{MMdd}.log
appender.otr.filePattern = D:\\RLS\\otr_%d{MMdd}.log
appender.otr.layout.type = PatternLayout
appender.otr.layout.pattern = %d{ABSOLUTE} %level{length=1}
%markerSimpleName [%C{1}:%L] %m%n
appender.otr.policies.type = Policies
appender.otr.policies.time.type = TimeBasedTriggeringPolicy
appender.otr.policies.time.interval = 1
appender.otr.policies.time.modulate = true
appender.otr.policies.size.type = SizeBasedTriggeringPolicy
appender.otr.policies.size.size = 100MB
appender.otr.strategy.type = DefaultRolloverStrategy
appender.otr.strategy.max = 5
appender.routing.type = Routing
appender.routing.name = Route_Finder
appender.routing.routes.type = Routes
appender.routing.routes.pattern = $${ctx:cfg}
appender.routing.routes.route1.type = Route
appender.routing.routes.route1.ref = RollingFile_Rls
appender.routing.routes.route1.key = RLS
appender.routing.routes.route2.type = Route
appender.routing.routes.route2.ref = RollingFile_Otr
appender.routing.routes.route2.key = $${ctx:cfg}
loggers = rls,otr
logger.rls.name = logging
logger.rls.level = info
logger.rls.additivity = false
logger.rls.appenderRefs=rls
logger.rls.appenderRef.rls.ref = Route_Finder
logger.rls.name = logging
logger.rls.level = info
logger.rls.additivity = false
logger.rls.appenderRefs=rls
logger.rls.appenderRef.rls.ref = Route_Finder
logger.otr.name = other
logger.otr.level = info
logger.otr.additivity = false
logger.otr.appenderRefs=otr
logger.otr.appenderRef.otr.ref = Route_Finder
rootLogger.level = trace
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = stdout
You can put log4j2.component.properties file in the classpath to control various aspects of Log4j 2 behavior.
For example content of log4j2.component.properties:
# https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties
# If true use an InheritableThreadLocal to implement the ThreadContext map.
# Otherwise, use a plain ThreadLocal.
# (Maybe ignored if a custom ThreadContext map is specified.)
# Default is false
# Modern 2.10+
log4j2.isThreadContextMapInheritable=true
# Legacy for pre-2.10
isThreadContextMapInheritable=true
This has priority over system properties, but it can be overridden by environment variable LOG4J_IS_THREAD_CONTEXT_MAP_INHERITABLE as described in the
documentation.
Adding OP's comment as answer
The ThreadContext map can be configured to use an InheritableThreadLocal by setting system property isThreadContextMapInheritable to true.
Set the system property as -DisThreadContextMapInheritable=true when we start our application, or in application code using the following piece of code: System.setProperty("isThreadContextMapInheritable", "true");
https://logging.apache.org/log4j/2.x/manual/thread-context.html
https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties

Not able to write any contain into log file though empty file created

Used the below configuration to log the message to both console and file. I could see only the console output. Though file created but it does not have any contain
status = error
name = PropertiesConfig
property.filename = C:/target/rolling/rollingtest.log
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd'T'hh:mm:ss.SSSXXX} %-5p [%t] %x %c %M - %m%n
appender.rolling.type = RollingFile
appender.rolling.name = RollingFile
appender.rolling.fileName = ${filename}
appender.rolling.filePattern = C:/target/rolling2/test1-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d{yyyy-MM-dd'T'hh:mm:ss.SSSXXX} %-5p [%t] %x %c %M - %m%n
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 2
appender.rolling.policies.time.modulate = true
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=1KB
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.max = 5
logger.rolling.name = com.example.my.app
logger.rolling.level = debug
logger.rolling.additivity = false
logger.rolling.appenderRef.rolling.ref = RollingFile
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = STDOUT
I have tested your properties and they seem okay to me. Consider the following:
To catch messages to file you need your code to produce debug messages
To catch messages to file your log messages have to be produced from the classes having fully qualified names starting from com.example.my.app
Here is the example that worked:
package com.example.my.app;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
Logger logger = LogManager.getLogger();
Logger getLogger(){
return logger;
}
public static void main(String[] args) {
Main mainObj = new Main();
mainObj.getLogger().debug("test debig");
}
}

How do you create SeqAppender programatically in log4net?

I tried the following code based on other responses on how to add custom appender programmatically. I do see log messages appear on the console, but I do not see them in a locally running Seq server. I verified the Seq URL was set http://localhost:5341/. I also tried a hosted version of Seq with API Key to see if I could catch anything being set via Fiddler, but nothing is sent. What am I missing?
public static void SetLevel(string loggerName, string levelName)
{
ILog log = LogManager.GetLogger(loggerName);
Logger l = (Logger)log.Logger;
l.Level = l.Hierarchy.LevelMap[levelName];
}
// Add an appender to a logger
public static void AddAppender(string loggerName, IAppender appender)
{
ILog log = LogManager.GetLogger(loggerName);
Logger l = (Logger)log.Logger;
l.AddAppender(appender);
l.Repository.Configured = true;
}
// Create a new file appender
public static IAppender CreateSeqAppender(string name)
{
var seqAppender = new SeqAppender();
seqAppender.ServerUrl = ConfigurationManager.AppSettings["Seq:Url"];
var seqApiKey = ConfigurationManager.AppSettings["Seq:ApiKey"];
if (seqApiKey != null)
{
seqAppender.ApiKey = seqApiKey;
}
PatternLayout patternLayout = new PatternLayout();
var LOG_PATTERN = "%d [%t] %-5p %m%n";
patternLayout.ConversionPattern = LOG_PATTERN;
patternLayout.ActivateOptions();
seqAppender.Name = name;
seqAppender.BufferSize = 1;
seqAppender.Layout = patternLayout;
seqAppender.ActivateOptions();
return seqAppender;
}
static void Main()
{
BasicConfigurator.Configure();
// In order to set the level for a logger and add an appender reference you
// can then use the following calls:
SetLevel("Log4net.MainForm", "ALL");
AddAppender("Log4net.MainForm", CreateSeqAppender("SeqAppender"));
//BasicConfigurator.Configure();
var logger = LogManager.GetLogger("MyLogger");
logger.Info("This is a test log message");
}
After a bit more investigation I figured out how to get this to work. Instead the code in AddAppender above I just did the following:
var root = ((Hierarchy)LogManager.GetRepository()).Root;
root.AddAppender(CreateSeqAppender());
Hopefully, this helps someone else out.

how to check the number of entries on local member

my prime member
public static void main(String[] args) throws InterruptedException {
Config config = new Config();
config.setProperty(GroupProperty.ENABLE_JMX, "true");
config.setProperty(GroupProperty.BACKPRESSURE_ENABLED, "true");
config.setProperty(GroupProperty.SLOW_OPERATION_DETECTOR_ENABLED, "true");
config.getSerializationConfig().addPortableFactory(1, new MyPortableFactory());
HazelcastInstance hz = Hazelcast.newHazelcastInstance(config);
IMap<Integer, Rule> ruleMap = hz.getMap("ruleMap");
// TODO generate rule map data ; more than 100,000 entries
generateRuleMapData(ruleMap);
logger.info("generate rule finised!");
// TODO rule map index
// health check
PartitionService partitionService = hz.getPartitionService();
LocalMapStats mapStatistics = ruleMap.getLocalMapStats();
while (true) {
logger.info("isClusterSafe:{},isLocalMemberSafe:{},number of entries owned on this node = {}",
partitionService.isClusterSafe(), partitionService.isLocalMemberSafe(),
mapStatistics.getOwnedEntryCount());
Thread.sleep(1000);
}
}
logs
2016-06-28 13:53:05,048 INFO [main] b.PrimeMember (PrimeMember.java:41) - isClusterSafe:true,isLocalMemberSafe:true,number of entries owned on this node = 997465
2016-06-28 13:53:06,049 INFO [main] b.PrimeMember (PrimeMember.java:41) - isClusterSafe:true,isLocalMemberSafe:true,number of entries owned on this node = 997465
2016-06-28 13:53:07,050 INFO [main] b.PrimeMember (PrimeMember.java:41) - isClusterSafe:true,isLocalMemberSafe:true,number of entries owned on this node = 997465
my slave member
public static void main(String[] args) throws InterruptedException {
Config config = new Config();
config.setProperty(GroupProperty.ENABLE_JMX, "true");
config.setProperty(GroupProperty.BACKPRESSURE_ENABLED, "true");
config.setProperty(GroupProperty.SLOW_OPERATION_DETECTOR_ENABLED, "true");
HazelcastInstance hz = Hazelcast.newHazelcastInstance(config);
IMap<Integer, Rule> ruleMap = hz.getMap("ruleMap");
PartitionService partitionService = hz.getPartitionService();
LocalMapStats mapStatistics = ruleMap.getLocalMapStats();
while (true) {
logger.info("isClusterSafe:{},isLocalMemberSafe:{},number of entries owned on this node = {}",
partitionService.isClusterSafe(), partitionService.isLocalMemberSafe(),
mapStatistics.getOwnedEntryCount());
Thread.sleep(1000);
}
}
logs
2016-06-28 14:05:53,543 INFO [main] b.SlaveMember (SlaveMember.java:31) - isClusterSafe:false,isLocalMemberSafe:false,number of entries owned on this node = 412441
2016-06-28 14:05:54,556 INFO [main] b.SlaveMember (SlaveMember.java:31) - isClusterSafe:false,isLocalMemberSafe:false,number of entries owned on this node = 412441
2016-06-28 14:05:55,563 INFO [main] b.SlaveMember (SlaveMember.java:31) - isClusterSafe:false,isLocalMemberSafe:false,number of entries owned on this node = 412441
2016-06-28 14:05:56,578 INFO [main] b.SlaveMember (SlaveMember.java:31) - isClusterSafe:false,isLocalMemberSafe:false,number of entries owned on this node = 412441
my question is :
why number of entries owned on prime member is not changed, after the cluster adds one slave member?
I should get statics per second.
while (true) {
LocalMapStats mapStatistics = ruleMap.getLocalMapStats();
logger.info(
"isClusterSafe:{},isLocalMemberSafe:{},rulemap.size:{}, number of entries owned on this node = {}",
partitionService.isClusterSafe(), partitionService.isLocalMemberSafe(), ruleMap.size(),
mapStatistics.getOwnedEntryCount());
Thread.sleep(1000);
}
Another option is to make use of localKeySet which returns the locally owned set of keys.
IMap::localKeySet.size()

Resources