Solve the conflict between the custom Log4j configuration file and the log file under RocketMQ-Client.jar

The project jar is normal. The root log level of our project log4j has been configured as info, but after starting the project, the custom logger log can only print the error level.

When starting the service, the log level of the root logger is not set.

2018-05-09 16:24:34,309 main WARN No Root logger was configured, 
creating default ERROR-level Root logger with Console appender

But our log file has set info level

 <Root level="INFO">
      <AppenderRef ref="ConsoleAppend"/>
    </Root>

analysis

After debugging, the loaded log file is not the log file we configured, but the log file configured under rocketmq.
Effective configuration
Open the configuration file

<!DOCTYPE xml>
<Configuration status="warn" name="RocketmqClient">
    <Appenders>
        <Console name="STDOUT-APPENDER">
            <PatternLayout pattern="%-5p %c{2} , %m%n"/>
        </Console>
        <RollingFile name="RocketmqClientAppender" fileName="${sys:client.logRoot}/rocketmq_client.log"
                     filePattern="${sys:client.logRoot}/rocketmq_client-%d{yyyy-MM-dd}-%i.log">
            <PatternLayout pattern="%d{yyy-MM-dd HH\:mm\:ss,SSS} %p %c{1}(%L) - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="1 GB"/>
            </Policies>
            <DefaultRolloverStrategy max="${sys:client.logFileMaxIndex}"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <logger name="RocketmqClient" level="${sys:client.logLevel}" additivity="false">
            <appender-ref ref="RocketmqClientAppender"/>
        </logger>

        <logger name="RocketmqCommon" level="${sys:client.logLevel}" additivity="false">
            <appender-ref ref="RocketmqClientAppender"/>
        </logger>

        <logger name="RocketmqRemoting" level="${sys:client.logLevel}" additivity="false">
            <appender-ref ref="RocketmqClientAppender"/>
        </logger>
    </Loggers>
</Configuration>

The analysis does not exist root level configuration.

  • Our custom log configuration file
    Custom log files
  • Currently we are using rocketmq-4.2.0 version
    rocketmq log file
  • Analysis of mq log configuration source code ClientLogger
public class ClientLogger {
    public static final String CLIENT_LOG_ROOT = "rocketmq.client.logRoot";
    public static final String CLIENT_LOG_MAXINDEX = "rocketmq.client.logFileMaxIndex";
    public static final String CLIENT_LOG_LEVEL = "rocketmq.client.logLevel";

    private static Logger log;

    private static Logger createLogger(final String loggerName) {
        //System.getProperty获取logConfigFilePath
        String logConfigFilePath = System.getProperty("rocketmq.client.log.configFile", System.getenv("ROCKETMQ_CLIENT_LOG_CONFIGFILE"));
        //是否加载rocketmq.client.log.loadconfig--默认为true
        Boolean isloadconfig =
            Boolean.parseBoolean(System.getProperty("rocketmq.client.log.loadconfig", "true"));
        //log4J日志资源配置
        final String log4JResourceFile =
            System.getProperty("rocketmq.client.log4j.resource.fileName", "log4j_rocketmq_client.xml");
        //logback日志资源配置
        final String logbackResourceFile =
            System.getProperty("rocketmq.client.logback.resource.fileName", "logback_rocketmq_client.xml");
        //log4J2日志资源配置
        final String log4J2ResourceFile =
            System.getProperty("rocketmq.client.log4j2.resource.fileName", "log4j2_rocketmq_client.xml");

        String clientLogRoot = System.getProperty(CLIENT_LOG_ROOT, System.getProperty("user.home") + "/logs/rocketmqlogs");
        System.setProperty("client.logRoot", clientLogRoot);
        String clientLogLevel = System.getProperty(CLIENT_LOG_LEVEL, "INFO");
        System.setProperty("client.logLevel", clientLogLevel);
        String clientLogMaxIndex = System.getProperty(CLIENT_LOG_MAXINDEX, "10");
        System.setProperty("client.logFileMaxIndex", clientLogMaxIndex);
        //允许加载配置
        if (isloadconfig) {
            try {
                ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory();
                Class classType = iLoggerFactory.getClass();
                if (classType.getName().equals("org.slf4j.impl.Log4jLoggerFactory")) {
                    Class<?> domconfigurator;
                    Object domconfiguratorobj;
                    domconfigurator = Class.forName("org.apache.log4j.xml.DOMConfigurator");
                    domconfiguratorobj = domconfigurator.newInstance();
                    if (null == logConfigFilePath) {
                        Method configure = domconfiguratorobj.getClass().getMethod("configure", URL.class);
                        URL url = org.apache.rocketmq.client.log.ClientLogger.class.getClassLoader().getResource(log4JResourceFile);
                        configure.invoke(domconfiguratorobj, url);
                    } else {
                        Method configure = domconfiguratorobj.getClass().getMethod("configure", String.class);
                        configure.invoke(domconfiguratorobj, logConfigFilePath);
                    }

                } else if (classType.getName().equals("ch.qos.logback.classic.LoggerContext")) {
                    Class<?> joranConfigurator;
                    Class<?> context = Class.forName("ch.qos.logback.core.Context");
                    Object joranConfiguratoroObj;
                    joranConfigurator = Class.forName("ch.qos.logback.classic.joran.JoranConfigurator");
                    joranConfiguratoroObj = joranConfigurator.newInstance();
                    Method setContext = joranConfiguratoroObj.getClass().getMethod("setContext", context);
                    setContext.invoke(joranConfiguratoroObj, iLoggerFactory);
                    if (null == logConfigFilePath) {
                        URL url = org.apache.rocketmq.client.log.ClientLogger.class.getClassLoader().getResource(logbackResourceFile);
                        Method doConfigure =
                            joranConfiguratoroObj.getClass().getMethod("doConfigure", URL.class);
                        doConfigure.invoke(joranConfiguratoroObj, url);
                    } else {
                        Method doConfigure =
                            joranConfiguratoroObj.getClass().getMethod("doConfigure", String.class);
                        doConfigure.invoke(joranConfiguratoroObj, logConfigFilePath);
                    }

                } else if (classType.getName().equals("org.apache.logging.slf4j.Log4jLoggerFactory")) {
                    Class<?> joranConfigurator = Class.forName("org.apache.logging.log4j.core.config.Configurator");
                    Method initialize = joranConfigurator.getDeclaredMethod("initialize", String.class, String.class);
                    if (null == logConfigFilePath) {
                        initialize.invoke(joranConfigurator, "log4j2", log4J2ResourceFile);
                    } else {
                        initialize.invoke(joranConfigurator, "log4j2", logConfigFilePath);
                    }
                }
            } catch (Exception e) {
                System.err.println(e);
            }
        }
        return LoggerFactory.getLogger(LoggerName.CLIENT_LOGGER_NAME);
    }

    public static Logger getLog() {
        if (log == null) {
            log = createLogger(LoggerName.CLIENT_LOGGER_NAME);
            return log;
        } else {
            return log;
        }
    }

    public static void setLog(Logger log) {
        org.apache.rocketmq.client.log.ClientLogger.log = log;
    }

}
After analysis, we can see that we can System.setPropertyset some properties to shield the mq log configuration, so we set it in the mq configuration bean:
RocketMQConfiguration(){
   System.setProperty("rocketmq.client.log.loadconfig","false");
}

Insert picture description here

Published 41 original articles · Liked 14 · Visitors 10,000+

Guess you like

Origin blog.csdn.net/Yunwei_Zheng/article/details/104018244