0

I am trying to migrate log4j from 1 to 2 and logs are not generated. I removed actual path of writing and application able to write the logs the mentioned path since logs are not printing after upgrade only Legacy code contains Parent Pom

<!-- 
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
-->

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-1.2-api</artifactId>
    <version>2.16.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.16.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.16.0</version>
</dependency>

Child POM: - Updated version only

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-ext</artifactId>
    <!--  <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jcl</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>

<!-- 
<dependency> 
    <groupId>org.slf4j</groupId> 
    <artifactId>slf4j-log4j12</artifactId> 
    <version>1.7.5</version> 
    </dependency> 
-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.1</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <!-- <version>1.7.5</version> -->
    <version>1.7.25</version>
</dependency>

log4j -> xml

<log4j:configuration>
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
        </layout>
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <param name="LevelMin" value="DEBUG" />
            <param name="LevelMax" value="INFO" />
            <param name="AcceptOnMatch" value="true" />
        </filter>
    </appender>

    <appender name="errout" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.Err" />
        <param name="Threshold" value="WARN" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
        </layout>
    </appender>

    <appender name="userLog" class="com.test.RollingFileAppender">
        <param name="File" value="userlogs.log" />
        <param name="Threshold" value="INFO" />
        <param name="MaxFileSize" value="50MB" />
        <param name="MaxBackupIndex" value="5" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%m | [%d{ISO8601}] | [%t]%n" />
        </layout>
    </appender>

    <appender name="errorLog" class="com.test.RollingFileAppender">
        <param name="File" value="error.log" />
        <param name="Threshold" value="ERROR" />
        <param name="MaxFileSize" value="50MB" />
        <param name="MaxBackupIndex" value="10" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%d{ISO8601}] [%t] %-5p %c{1}: - %m%n" />
        </layout>
    </appender>

    <category name="REQUEST_LOG" additivity="false">
        <priority value="INFO" />
        <appender-ref ref="userLog" />
    </category>

    <root>
        <priority value="INFO" />
        <appender-ref ref="errorLog" />
    </root>

</log4j:configuration>

We initialized log4j programatically

import java.io.File;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.xml.DOMConfigurator;

import ApplicationContext;
import ResourceUtility;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.LogManager;

public class Initializer implements Startable {

    private static Log logger = null;
    private static boolean logsPathSet = false;

    private static String logsPath = "";

    static {
        BasicConfigurator.configure();
        logger = LogFactory.getLog(Initializer.class);
    }

    public static void initialize() {
        logsPath = System.getProperty("log4j.configuration","");
        logsPathSet = (logsPath != null && !logsPath.equals(""));
        initializeLogging();
        ApplicationContext.getInstance();
    }

    public static void initializeLogging() {
        String configFile = "";
        URL aURL  = null;
        
        if ( logsPathSet ) {
            configFile  = logsPath;
            aURL = ResourceUtility.geUrlResource(configFile);
        }
        
        if ( (!logsPathSet) || ( logsPathSet && aURL == null) ) {
            configFile = ApplicationContext.getInstance().getStringProperty("logging", "log4j", "configFile");
            aURL = ResourceUtility.geUrlResource(configFile);
        }
        DOMConfigurator.configure(aURL);
        logger = LogFactory.getLog(Initializer.class);
        logger.info("Configured Logging from: " + aURL);
    }
}


import java.io.File;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;

import ApplicationContext;
import Initializer;
import ResourceUtility;

    public class Startup extends HttpServlet {
    
        private static Log logger = LogFactory.getFactory().getInstance(Startup.class);
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
        
        public void init() throws ServletException {
            super.init();
            ApplicationContext.getInstance();
            Initializer.initialize();
            String loggingProperty = "/" + ApplicationContext.getInstance().getProperty("logging", "log4j", "configFile");
            loggingFile = ResourceUtility.getFileResource(loggingProperty);
            PropertyConfigurator.configure(loggingFile.toString());
        }
    
    }

I tried with couple of approach. Approach 1 -> Migrating log4j 1 to 2 directly and updated log4j connfig

System.out -> SYSTEM_OUT -> tried with bith target

Updated log4j xml file

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="console" target="System.out">
            <PatternLayout pattern="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
            <LevelRangeFilter minLevel="DEBUG" maxLevel="INFO" onMatch="ACCEPT" onMismatch="NEUTRAL" />
        </Console>
        <Console name="consoleError" target="System.Err" follow="true">
            <PatternLayout pattern="[%d{ISO8601}] [%t] %-5p %c{1}: %x - %m%n" />
            <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="NEUTRAL" />
        </Console>

        <RollingFile name="userLog" fileName="/userlogs.log"  filePattern="/userlogs.log.%d{yyyyMMdd}">
            <PatternLayout pattern="%m | [%d{ISO8601}] | [%t]%n" />
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY" />
        </RollingFile>
            
        <RollingFile name="errorLog" fileName="/error.log"  filePattern="/error.log.%d{yyyyMMdd}">
            <PatternLayout pattern="[%d{ISO8601}] [%t] %-5p %c{1}: - %m%n" />
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY" />
        </RollingFile>
    </Appenders>

    <Loggers>
        <Logger name="REQUEST_LOG" additivity="false">
            <AppenderRef  ref="userRequestLog" level="INFO" />
        </Logger>
        <Root  level="INFO">
            <AppenderRef  ref="errorLog"/>
        </Root >
    </Loggers>
</Configuration>

Updated Initalizer class

//BasicConfigurator.configure();
Configurator.initialize(new DefaultConfiguration());

// DOMConfigurator.configure(aURL);
        
LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
loggingFile = ResourceUtility.getFileResource(configFile);
context.setConfigLocation(loggingFile.toURI());
context.reconfigure();

ConfigurationFactory.setConfigurationFactory(new XmlConfigurationFactory());
Configurator.reconfigure(loggingFile.toURI());

Updated startup into

// PropertyConfigurator.configure(loggingFile.toString());
        ConfigurationFactory.setConfigurationFactory(new XmlConfigurationFactory());
        LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
        //Configurator.reconfigure(loggingFile.toURI());
        context.setConfigLocation(loggingFile.toURI());
        context.reconfigure();

Logs are not generated for the above approach

Approach 2 -> Same changes by adding bridge jar -> skipped log4j xml changes

Thanks in advance for any recommendation or changes or approach or can you please share steps you followed while migrate the same or share the approach with minimal code changes.

Abdul
  • 942
  • 2
  • 14
  • 32
  • Check the status logger's output (on standard output) to correct the errors in your configuration. E.g. the absolute file path `/error.log` is almost certainly not writable by your application. – Piotr P. Karwasz Apr 11 '22 at 18:25
  • I removed the actual path in the content. I can assure that path we are trying to write have access bec before migration logs are printing and not when moved to 2.x version. I think that log4j config file is not detected when we do by program and not sure that also – Abdul Apr 12 '22 at 15:22
  • this may help you https://stackoverflow.com/questions/71267326/logs-not-printing-after-migrating-from-log4j-1-2-17-to-log4j2-2-17-1 or this https://stackoverflow.com/questions/70578685/not-able-to-generate-log-when-migrate-from-log4j-1-x-to-log4j-2-x-using-bridge-j – Charfeddine Mohamed Ali Apr 13 '22 at 12:15
  • Let me check and update on this – Abdul Apr 13 '22 at 14:59
  • Can you run your application with `-Dlog4j2.debug=true` and check if your configuration file is read? BTW: you don't need to use programmatic configuration, just name your configuration file `log4j2.xml`. – Piotr P. Karwasz Apr 16 '22 at 14:00

1 Answers1

1

I'd advise to follow the second approach, but you have to use log4j 2.17.2+ version. The bridge jar has big issues in previous versions, but the devs made an effort at the start of this year to fix it. I would have made this a comment rather than an answer, but have low reputation.

In my case it was possible to make a simple jar file and overwrite the existing log4j version 1 jars with it on 200 running apps without changing any config files in the apps or on app server. How is that for an "approach with minimal code changes" :)

  • Thanks for your input. Let me check and update on this – Abdul Apr 13 '22 at 17:44
  • 1
    Good luck, even with 2.17.2 version you'll still face problems. There is a good chance that your config file is not parsed, also the appenders might not work as before. Here is a breakpoint that helps debugging the parsing: org.apache.logging.log4j.core.config.ConfigurationFactory.Factory.getConfiguration(LoggerContext, String, URI) - around line 396. I had to modify this ConfigurationFactory and hard code config location. Also made changes to this appender, log4j 2 with the bridge had different defaults to it then log4j 1: RollingFileAppenderBuilder.createAppender – András Devecsery Apr 13 '22 at 19:21
  • Thanks for you recommendations and Will check on this and update – Abdul Apr 14 '22 at 12:57