Search code examples
javalogginglog4jopen-sourcelog4j2

Logging for simple java project


Hopefully this question is more clear than my previous question.

I have a Project A (PA) that has a simple Java API. I have a Project B (PB) that is simply a main() wrapper around PA. I then have a Project C (PC) that includes a custom classloader that calls PB as a utility. PC uses the STD_OUT and STD_ERR from PB.

Currently, PA is just returning values and PB is using System.out and System.err for value reporting and error reporting. I would like to change PA and PB to use log4j2.

PC is huge and has its own log4j2 configuration with many log files. How do I configure the logging for PA and PB so that PC's behavior can continue as is?

My guess:

  • PA should probably just call .getLogger(className()); and log things in that manner.
  • PB should programmatically add to PC's log4j configuration, adding the following.
    • Since PB has no idea what PC's log4j configuration is, add 2 new appenders to LoggerContext.getContext().getconfiguration(). One for sysout, one for syserr.
    • Create a logger with these 2 new appenders specifically for PB.

Is this the way this is typically done with smaller open source type projects?

The below code is directly from the log4j site and seems to do just that (although it currently does not compile anymore):

final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null,
    null,null, null);
Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
    "false", "false", "4000", layout, null, "false", null, config);
appender.start();
config.addAppender(appender);
AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
AppenderRef[] refs = new AppenderRef[] {ref};
LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j",
    "true", refs, null, config, null );
loggerConfig.addAppender(appender, null, null);
config.addLogger("org.apache.logging.log4j", loggerConfig);
ctx.updateLoggers();

Solution

  • Have you tried pointing your A and B projects to a separate Log4j2 configuration file with system property -Dlog4j.configurationFile=path/to/log4j2.xml?


    Update:

    If you have to share a Log4j2 configuration file, you could consider using XInclude to include some special configuration needed by the A/B projects.

    See https://logging.apache.org/log4j/2.x/manual/configuration.html#XInclude

    Additionally, you can specify multiple configuration files and let Log4j2 merge them. This is documented here: https://logging.apache.org/log4j/2.x/manual/configuration.html#CompositeConfiguration