Nacos导致Log4j2配置失效不打印日志

Nacos导致Log4j2配置失效不打印日志

1. 问题:

我们项目之前用的是logback日志框架,
后面说Log4j2性能更优越于是就换了。
所有的配置均正确,就是不打印日志。

到这里就停住了:

restartedMain WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender

在这里插入图片描述

2. 解决方案

在启动类里面加上:

// 关闭nacos日志
System.setProperty("nacos.logging.default.config.enabled", "false");

在这里插入图片描述

3. 原因

可以看到nacos的日志工具类先加载logback,
如果成功直接使用,
失败就去加载log4j2


package com.alibaba.nacos.client.utils;

import com.alibaba.nacos.client.logging.AbstractNacosLogging;
import com.alibaba.nacos.client.logging.log4j2.Log4J2NacosLogging;
import com.alibaba.nacos.client.logging.logback.LogbackNacosLogging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogUtils {
    public static final Logger NAMING_LOGGER;

    public LogUtils() {
    }

    public static Logger logger(Class<?> clazz) {
        return LoggerFactory.getLogger(clazz);
    }

    static {
        try {
            boolean isLogback = false;

            Object nacosLogging;
            try {
                Class.forName("ch.qos.logback.classic.Logger");
                nacosLogging = new LogbackNacosLogging();
                isLogback = true;
            } catch (ClassNotFoundException var3) {
                nacosLogging = new Log4J2NacosLogging();
            }

            try {
                ((AbstractNacosLogging)nacosLogging).loadConfiguration();
            } catch (Throwable var4) {
                if (isLogback) {
                    LoggerFactory.getLogger(LogUtils.class).warn("Load Logback Configuration of Nacos fail, message: {}", var4.getMessage());
                } else {
                    LoggerFactory.getLogger(LogUtils.class).warn("Load Log4j Configuration of Nacos fail, message: {}", var4.getMessage());
                }
            }
        } catch (Throwable var5) {
            LoggerFactory.getLogger(LogUtils.class).warn("Init Nacos Logging fail, message: {}", var5.getMessage());
        }

        NAMING_LOGGER = LoggerFactory.getLogger("com.alibaba.nacos.client.naming");
    }
}

加载log4j2时:
可以看到是加载classpath:nacos-log4j2.xml这个文件


package com.alibaba.nacos.client.logging.log4j2;

import com.alibaba.nacos.client.logging.AbstractNacosLogging;
import com.alibaba.nacos.client.utils.StringUtils;
import com.alibaba.nacos.common.util.ClassUtils;
import com.alibaba.nacos.common.util.ResourceUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
import org.apache.logging.log4j.core.lookup.Interpolator;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.util.PropertiesUtil;

public class Log4J2NacosLogging extends AbstractNacosLogging {
    private static final String NACOS_LOG4J2_LOCATION = "classpath:nacos-log4j2.xml";
    private static final String FILE_PROTOCOL = "file";
    private static final String YAML_PARSER_CLASS_NAME = "com.fasterxml.jackson.dataformat.yaml.YAMLParser";
    private static final String JSON_PARSER_CLASS_NAME = "com.fasterxml.jackson.databind.ObjectMapper";
    private final StrSubstitutor strSubstitutor = new StrSubstitutor(new Interpolator());
    private Set<String> locationList = new HashSet();

    public Log4J2NacosLogging() {
        String location = this.getLocation("classpath:nacos-log4j2.xml");
        if (!StringUtils.isBlank(location)) {
            this.locationList.add(location);
        }

    }

    public void loadConfiguration() {
        if (!this.locationList.isEmpty()) {
            List<String> configList = this.findConfig(this.getCurrentlySupportedConfigLocations());
            if (configList != null) {
                this.locationList.addAll(configList);
            }

            List<AbstractConfiguration> configurations = new ArrayList();
            LoggerContext loggerContext = (LoggerContext)LogManager.getContext(false);
            Iterator var4 = this.locationList.iterator();

            while(var4.hasNext()) {
                String location = (String)var4.next();

                try {
                    Configuration configuration = this.loadConfiguration(loggerContext, location);
                    if (configuration instanceof AbstractConfiguration) {
                        configurations.add((AbstractConfiguration)configuration);
                    }
                } catch (Exception var7) {
                    throw new IllegalStateException("Could not initialize Log4J2 Nacos logging from " + location, var7);
                }
            }

            CompositeConfiguration compositeConfiguration = new CompositeConfiguration(configurations);
            loggerContext.start(compositeConfiguration);
        }
    }

    private Configuration loadConfiguration(LoggerContext loggerContext, String location) {
        try {
            URL url = ResourceUtils.getResourceURL(location);
            ConfigurationSource source = this.getConfigurationSource(url);
            return ConfigurationFactory.getInstance().getConfiguration(loggerContext, source);
        } catch (Exception var5) {
            throw new IllegalStateException("Could not initialize Log4J2 logging from " + location, var5);
        }
    }

    private ConfigurationSource getConfigurationSource(URL url) throws IOException {
        InputStream stream = url.openStream();
        return "file".equals(url.getProtocol()) ? new ConfigurationSource(stream, ResourceUtils.getResourceAsFile(url)) : new ConfigurationSource(stream, url);
    }

    private String[] getCurrentlySupportedConfigLocations() {
        List<String> supportedConfigLocations = new ArrayList();
        if (ClassUtils.isPresent("com.fasterxml.jackson.dataformat.yaml.YAMLParser")) {
            Collections.addAll(supportedConfigLocations, new String[]{"log4j2.yaml", "log4j2.yml", "log4j2-test.yaml", "log4j2-test.yml"});
        }

        if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper")) {
            Collections.addAll(supportedConfigLocations, new String[]{"log4j2.json", "log4j2.jsn", "log4j2-test.json", "log4j2-test.jsn"});
        }

        supportedConfigLocations.add("log4j2.xml");
        supportedConfigLocations.add("log4j2-test.xml");
        return (String[])supportedConfigLocations.toArray(new String[supportedConfigLocations.size()]);
    }

    private List<String> findConfig(String[] locations) {
        String configLocationStr = this.strSubstitutor.replace(PropertiesUtil.getProperties().getStringProperty("log4j.configurationFile"));
        if (configLocationStr != null) {
            return Arrays.asList(configLocationStr.split(","));
        } else {
            String[] var3 = locations;
            int var4 = locations.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                String location = var3[var5];
                ClassLoader defaultClassLoader = ClassUtils.getDefaultClassLoader();
                if (defaultClassLoader != null && defaultClassLoader.getResource(location) != null) {
                    List<String> list = new ArrayList();
                    list.add("classpath:" + location);
                    return list;
                }
            }

            return null;
        }
    }
}

于是我就产生了一个不好的想法:
将配置文件修改名称,然后放到resources下面
在这里插入图片描述
事就这样成了!
不过没有配置info打印,
疯狂在打印,
如果不想打印需要配置为warn级别
在这里插入图片描述
PS:
如果配置的是logback,
启动之后疯狂打印info日志
需要如下配置:

# nacos疯狂打印
logging:
  level:
    com:
      alibaba:
        nacos:
          client:
            naming: warn

参考文档:[SpringCloud] 使用 Nacos 作为注册中心日志不打印

是的,可以将 log4j2.xml 配置文件放到 Nacos 注册中心上实现动态部署。下面是一个简单的实例,假设已经安装了 Nacos 并且启动了一个示例应用程序。 1. 创建 log4j2.xml 配置文件,放置到本地文件系统上,例如在应用程序的 conf 目录下。 ```xml <?xml version="1.0" encoding="UTF-8"?> <Configuration status="INFO"> <Appenders> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Logger name="com.example" level="DEBUG"/> <Root level="INFO"> <AppenderRef ref="console"/> </Root> </Loggers> </Configuration> ``` 2. 在 Nacos 控制台上创建一个配置。打开 Nacos 控制台,进入配置管理页面,点击“新建配置”按钮,填写配置信息,如下: - Data ID: log4j2.xml - Group: DEFAULT_GROUP - Content: 将步骤1中的 log4j2.xml 配置文件的内容复制到这里 - 配置格式: XML 点击“发布”按钮,即可将配置保存到 Nacos 注册中心上。 3. 在应用程序中配置 Nacos 配置源。在应用程序中引入 Nacos 的 Java 客户端库,例如使用 Maven 引入以下依赖: ```xml <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.4.1</version> </dependency> ``` 在应用程序启动时,配置 Nacos 配置源,如下: ```java import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; 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.builder.api.ConfigurationBuilderFactory; import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Properties; public class Log4j2NacosConfiguration { public static void init(String serverAddr, String dataId, String group) throws Exception { // 创建 Nacos 配置服务 Properties properties = new Properties(); properties.setProperty("serverAddr", serverAddr); ConfigService configService = NacosFactory.createConfigService(properties); // 从 Nacos 获取配置内容 String content = configService.getConfig(dataId, group, 5000); if (content != null) { // 解析配置内容,创建 Log4j2 配置对象 ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder(); ConfigurationSource source = new ConfigurationSource(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))); Configuration configuration = builder.setConfigurationSource(source).build(); // 配置 Log4j2 LoggerContext context = (LoggerContext) LogManager.getContext(false); Configurator.initialize(context, configuration); context.updateLoggers(configuration); } // 监听配置变化,支持动态更新配置 configService.addListener(dataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { try { if (configInfo != null) { // 解析配置内容,创建 Log4j2 配置对象 ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder(); ConfigurationSource source = new ConfigurationSource(new ByteArrayInputStream(configInfo.getBytes(StandardCharsets.UTF_8))); Configuration configuration = builder.setConfigurationSource(source).build(); // 配置 Log4j2 LoggerContext context = (LoggerContext) LogManager.getContext(false); Configurator.initialize(context, configuration); context.updateLoggers(configuration); } } catch (Exception e) { e.printStackTrace(); } } @Override public Executor getExecutor() { return null; } }); } } ``` 在应用程序启动时调用该方法,例如: ```java public class MyApp { public static void main(String[] args) throws Exception { Log4j2NacosConfiguration.init("localhost:8848", "log4j2.xml", "DEFAULT_GROUP"); // ... } } ``` 4. 测试动态更新配置。修改 Nacos 上的 log4j2.xml 配置文件内容,保存并发布,等待几秒钟后,应用程序的日志记录行为应该发生相应的变化,即按照新的配置进行日志记录。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jack魏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值