1

We are using the log4j1 to log4j2 bridge,

log4j-1.2-api-2.17.1.jar

And our code uses the PropertyConfigu

System.getProperty( "appserver.Name" );
System.setProperty( "appserver.Name", "/usr/local/logs/server3" );
l4jprops.put( "appserver.Name", "/usr/local/logs/server3" );    

            
PropertyConfigurator.configure( l4jprops );
logger = Logger.getLogger(PfsSystemPropertiesServlet.class.getName());

Here is an example log4j setting.

log4j.appender.AuthAppender.File=${appserver.Name}/log4j_api_auth.log
log4j.appender.AuthAppender.DatePattern='.'yyyy-MM-dd

This currently doesnt seem to write the logs as we want, how can we get this code to work with the bridge. That class available.

Berlin Brown
  • 11,504
  • 37
  • 135
  • 203

1 Answers1

3

Until Log4j 2.17.1, PropertyConfigurator has been a no-op. That is going to change in the upcoming release (cf. source code): your code should work without any changes.

In order to test the new release, add the snapshots repository:

<repositories>
  <repository>
    <id>apache.snapshots</id>
    <name>Apache Snapshot Repository</name>
    <url>https://repository.apache.org/snapshots</url>
    <releases>
      <enabled>false</enabled>
    </releases>
  </repository>
</repositories>

and set the version of log4j-1.2-api to 2.17.2-SNAPSHOT:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-1.2-api</artifactId>
    <version>2.17.2-SNAPSHOT</version>
</dependency>

Edit: If you can't use snapshots or wait for the next release, the behavior of PropertyConfigurator can be emulated as follows:

import org.apache.log4j.config.PropertiesConfiguration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.NullConfiguration;

// PropertiesConfiguration only accepts an InputStream in 2.17.1
final ByteArrayOutputStream os = new ByteArrayOutputStream();
l4jprops.save(os, null);
final InputStream is = new ByteArrayInputStream(os.toByteArray());
// Initialize to prevent automatic configuration.
Configurator.initialize(new NullConfiguration());
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = new PropertiesConfiguration(ctx, new ConfigurationSource(is), 0);
Configurator.reconfigure(config);
Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43
  • Lets say I cant use the snapshots. Is there another way...just to get dynamic variables in the log4j property file. Also point to a different path. – Berlin Brown Jan 25 '22 at 20:07
  • Thanks, do you work on log4j? – Berlin Brown Jan 25 '22 at 22:52
  • Can I also populate dynamic properties within a file that isnt the standard log4j.properties. I will try. – Berlin Brown Jan 25 '22 at 22:53
  • What do you mean by _"standard `log4j.properties"_? The above snippet should work with any `Properties` containing Log4j related configuration. I don't work on Log4j, but we use Log4j 1.2 at work, so I've followed the recent changes. – Piotr P. Karwasz Jan 26 '22 at 04:14
  • One more question, is it possible to mix log4j2.xml and log4j.properties for same application – Berlin Brown Jan 26 '22 at 15:01
  • Yes, the `log4j2.configurationFile` property accepts a list of URLs, but you should probably post a separate question for it. – Piotr P. Karwasz Jan 26 '22 at 15:18
  • I tried this...didn't get the behavior I expected. try { final FileInputStream fis = new FileInputStream("/usr/local/pfs/conf/log4j_global.properties"); l4jprops.load(fis); l4jprops.put( "appserver.Name", "/usr/local/pfs/logs/server5/" ); Configurator.initialize(new NullConfiguration()); final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); final Configuration config = new PropertiesConfiguration(ctx, new ConfigurationSource(fis), 0); Configurator.reconfigure(config); – Berlin Brown Jan 26 '22 at 15:20
  • Yea, that code above didn't seem to work, I couldn't change the path of the file dynamically. This worked. -Dlog4j1.compatibility=true -Dlog4j.configuration=/usr/local/pfs/conf/log4j_global.properties – Berlin Brown Jan 26 '22 at 16:18
  • Did you check the log for errors? You can set `-Dlog4j2.debug=true` to see Log4j debug output on stderr. – Piotr P. Karwasz Jan 26 '22 at 17:30
  • Ok, it worked. One more question, is there a way to pick up Appenders outside of the standard list in log4j.properties. Say outside of the standard. Say Socket Appender? – Berlin Brown Jan 27 '22 at 13:34
  • If you copy the appender code from Log4j 1.x and add it to your application, it might work (`log4j-1.2.-api` uses an adapter if it does not recognise the appender class). A safer way would be to write an [`AppenderBuilder`](https://logging.apache.org/log4j/2.x/log4j-1.2-api/apidocs/org/apache/log4j/builders/appender/AppenderBuilder.html) that creates and configures a Log4j 2.x [`SocketAppender`](https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/appender/SocketAppender.html). – Piotr P. Karwasz Jan 27 '22 at 14:08
  • @PiotrP.Karwasz Does this mean that the 3 exceptions in the "Limitations of the Log4j 1.x bridge" section of https://logging.apache.org/log4j/2.x/manual/migration.html do not apply anymore? – golimar Mar 28 '22 at 07:34
  • The `log4j-1.2-api` will never have 100% binary compatibility with `log4j`. If you refer to classes other than `Logger`, `LogManager` in your code, your mileage might vary. As a rule of thumb: if your custom code does not work out-of-the-box with `log4j-1.2-api`, rewrite it using Log4j2 directly. If you think that the changes to `log4j-1.2-api` required are simple, you can also send a Github PR or open a JIRA issue. – Piotr P. Karwasz Mar 28 '22 at 08:39