[#11956] Refactor nacos client logging module, use SPI load current logger adapter. (#11964)

* Add NacosLoggingAdapter

* Refactor Logback Logging adapter to Nacos logging adapter.

* Refactor log4j2 Logging adapter to Nacos logging adapter.

* Remove useless abstract class

* Add and Adapt log4j2 impl to SPI.

* Remove useless method in NacosLogbackConfigurator

* Fix IT ClassNotFound problem
This commit is contained in:
杨翊 SionYang 2024-04-16 13:52:28 +08:00 committed by GitHub
parent 2005ca6f90
commit 5c19ac12ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 436 additions and 351 deletions

View File

@ -1,56 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.logging;
import com.alibaba.nacos.client.env.NacosClientProperties;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.StringUtils;
/**
* Abstract nacos logging.
*
* @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
* @since 0.9.0
*/
public abstract class AbstractNacosLogging {
private static final String NACOS_LOGGING_CONFIG_PROPERTY = "nacos.logging.config";
private static final String NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY = "nacos.logging.default.config.enabled";
protected String getLocation(String defaultLocation) {
String location = NacosClientProperties.PROTOTYPE.getProperty(NACOS_LOGGING_CONFIG_PROPERTY);
if (StringUtils.isBlank(location)) {
if (isDefaultConfigEnabled()) {
return defaultLocation;
}
return null;
}
return location;
}
private boolean isDefaultConfigEnabled() {
String property = NacosClientProperties.PROTOTYPE.getProperty(NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY);
// The default value is true.
return property == null || ConvertUtils.toBoolean(property);
}
/**
* Load logging configuration.
*/
public abstract void loadConfiguration();
}

View File

@ -16,10 +16,14 @@
package com.alibaba.nacos.client.logging;
import com.alibaba.nacos.client.logging.log4j2.Log4J2NacosLogging;
import com.alibaba.nacos.client.logging.logback.LogbackNacosLogging;
import org.slf4j.LoggerFactory;
import com.alibaba.nacos.common.executor.ExecutorFactory;
import com.alibaba.nacos.common.executor.NameThreadFactory;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* nacos logging.
@ -30,18 +34,41 @@ public class NacosLogging {
private static final Logger LOGGER = LoggerFactory.getLogger(NacosLogging.class);
private AbstractNacosLogging nacosLogging;
private NacosLoggingAdapter loggingAdapter;
private boolean isLogback = false;
private NacosLoggingProperties loggingProperties;
private NacosLogging() {
try {
Class.forName("ch.qos.logback.classic.Logger");
nacosLogging = new LogbackNacosLogging();
isLogback = true;
} catch (ClassNotFoundException e) {
nacosLogging = new Log4J2NacosLogging();
initLoggingAdapter();
}
private void initLoggingAdapter() {
Class<? extends Logger> loggerClass = LOGGER.getClass();
for (NacosLoggingAdapter each : NacosServiceLoader.load(NacosLoggingAdapter.class)) {
LOGGER.info("Nacos Logging Adapter: {}", each.getClass().getName());
if (each.isEnabled() && each.isAdaptedLogger(loggerClass)) {
LOGGER.info("Nacos Logging Adapter: {} match {} success.", each.getClass().getName(),
loggerClass.getName());
loggingProperties = new NacosLoggingProperties(each.getDefaultConfigLocation());
loggingAdapter = each;
}
}
if (null == loggingAdapter) {
LOGGER.warn("Nacos Logging don't find adapter, logging will print into application logs.");
return;
}
scheduleReloadTask();
}
private void scheduleReloadTask() {
ScheduledExecutorService reloadContextService = ExecutorFactory.Managed
.newSingleScheduledExecutorService("Nacos-Client",
new NameThreadFactory("com.alibaba.nacos.client.logging"));
reloadContextService.scheduleAtFixedRate(() -> {
if (loggingAdapter.isNeedReloadConfiguration()) {
loggingAdapter.loadConfiguration(loggingProperties);
}
}, 0, loggingProperties.getReloadInternal(), TimeUnit.SECONDS);
}
private static class NacosLoggingInstance {
@ -58,10 +85,12 @@ public class NacosLogging {
*/
public void loadConfiguration() {
try {
nacosLogging.loadConfiguration();
if (null != loggingAdapter) {
loggingAdapter.loadConfiguration(loggingProperties);
}
} catch (Throwable t) {
String loggerName = isLogback ? "Logback" : "Log4j";
LOGGER.warn("Load {} Configuration of Nacos fail, message: {}", loggerName, t.getMessage());
LOGGER.warn("Load {} Configuration of Nacos fail, message: {}", LOGGER.getClass().getName(),
t.getMessage());
}
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.logging;
/**
* Nacos client logging adapter.
*
* @author xiweng.yy
*/
public interface NacosLoggingAdapter {
/**
* Whether current adapter is adapted for specified logger class.
*
* @param loggerClass {@link org.slf4j.Logger} implementation class
* @return {@code true} if current adapter can adapt this {@link org.slf4j.Logger} implementation, otherwise {@code
* false}
*/
boolean isAdaptedLogger(Class<?> loggerClass);
/**
* Load Nacos logging configuration into log context.
*
* @param loggingProperties logging properties
*/
void loadConfiguration(NacosLoggingProperties loggingProperties);
/**
* Whether need reload configuration into log context.
*
* @return {@code true} when context don't contain nacos logging configuration. otherwise {@code false}
*/
boolean isNeedReloadConfiguration();
/**
* Get current logging default config location.
*
* @return default config location
*/
String getDefaultConfigLocation();
/**
* Whether current adapter enabled, design for users which want to log nacos client into app logs.
*
* @return {@code true} when enabled, otherwise {@code false}, default {@code true}
*/
default boolean isEnabled() {
return true;
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.logging;
import com.alibaba.nacos.client.env.NacosClientProperties;
import com.alibaba.nacos.common.utils.ConvertUtils;
import com.alibaba.nacos.common.utils.StringUtils;
/**
* Nacos Logging Properties, save some nacos logging properties.
*
* @author xiweng.yy
*/
public class NacosLoggingProperties {
private static final String NACOS_LOGGING_CONFIG_PROPERTY = "nacos.logging.config";
private static final String NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY = "nacos.logging.default.config.enabled";
private static final String NACOS_LOGGING_RELOAD_INTERVAL_PROPERTY = "nacos.logging.reload.interval.seconds";
private static final long DEFAULT_NACOS_LOGGING_RELOAD_INTERVAL = 10L;
private final String defaultLocation;
public NacosLoggingProperties(String defaultLocation) {
this.defaultLocation = defaultLocation;
}
/**
* Get the location of nacos logging configuration.
*
* @return location of nacos logging configuration
*/
public String getLocation() {
String location = NacosClientProperties.PROTOTYPE.getProperty(NACOS_LOGGING_CONFIG_PROPERTY);
if (StringUtils.isBlank(location)) {
if (isDefaultLocationEnabled()) {
return defaultLocation;
}
return null;
}
return location;
}
/**
* Is default location enabled.
*
* <p> It is judged when user don't set the location of nacos logging configuration. </p>
*
* @return {@code true} if default location enabled, otherwise {@code false}, default is {@code true}
*/
private boolean isDefaultLocationEnabled() {
String property = NacosClientProperties.PROTOTYPE.getProperty(NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY);
return property == null || ConvertUtils.toBoolean(property);
}
/**
* Get reload internal.
*
* @return reload internal
*/
public long getReloadInternal() {
String interval = NacosClientProperties.PROTOTYPE.getProperty(NACOS_LOGGING_RELOAD_INTERVAL_PROPERTY);
return ConvertUtils.toLong(interval, DEFAULT_NACOS_LOGGING_RELOAD_INTERVAL);
}
/**
* get property value.
*
* @param source source
* @param defaultValue defaultValue
* @return value
*/
public String getValue(String source, String defaultValue) {
return NacosClientProperties.PROTOTYPE.getProperty(source, defaultValue);
}
}

View File

@ -16,7 +16,8 @@
package com.alibaba.nacos.client.logging.log4j2;
import com.alibaba.nacos.client.logging.AbstractNacosLogging;
import com.alibaba.nacos.client.logging.NacosLoggingAdapter;
import com.alibaba.nacos.client.logging.NacosLoggingProperties;
import com.alibaba.nacos.common.utils.ResourceUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import org.apache.logging.log4j.LogManager;
@ -36,9 +37,10 @@ import java.util.Map;
* Support for Log4j version 2.7 or higher
*
* @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
* @author xiweng.yy
* @since 0.9.0
*/
public class Log4J2NacosLogging extends AbstractNacosLogging {
public class Log4J2NacosLoggingAdapter implements NacosLoggingAdapter {
private static final String NACOS_LOG4J2_LOCATION = "classpath:nacos-log4j2.xml";
@ -48,14 +50,51 @@ public class Log4J2NacosLogging extends AbstractNacosLogging {
private static final String NACOS_LOG4J2_PLUGIN_PACKAGE = "com.alibaba.nacos.client.logging.log4j2";
private final String location = getLocation(NACOS_LOG4J2_LOCATION);
private static final String APPENDER_MARK = "ASYNC_NAMING";
private static final String LOG4J2_CLASSES = "org.apache.logging.slf4j.Log4jLogger";
@Override
public void loadConfiguration() {
public boolean isAdaptedLogger(Class<?> loggerClass) {
Class<?> expectedLoggerClass = getExpectedLoggerClass();
return null != expectedLoggerClass && expectedLoggerClass.isAssignableFrom(loggerClass);
}
private Class<?> getExpectedLoggerClass() {
try {
return Class.forName(LOG4J2_CLASSES);
} catch (ClassNotFoundException e) {
return null;
}
}
@Override
public boolean isNeedReloadConfiguration() {
final LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
final Configuration contextConfiguration = loggerContext.getConfiguration();
for (Map.Entry<String, Appender> entry : contextConfiguration.getAppenders().entrySet()) {
if (APPENDER_MARK.equals(entry.getValue().getName())) {
return false;
}
}
return true;
}
@Override
public String getDefaultConfigLocation() {
return NACOS_LOG4J2_LOCATION;
}
@Override
public void loadConfiguration(NacosLoggingProperties loggingProperties) {
String location = loggingProperties.getLocation();
loadConfiguration(location);
}
private void loadConfiguration(String location) {
if (StringUtils.isBlank(location)) {
return;
}
final LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
final Configuration contextConfiguration = loggerContext.getConfiguration();

View File

@ -21,78 +21,110 @@ import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.CoreConstants;
import com.alibaba.nacos.client.logging.AbstractNacosLogging;
import com.alibaba.nacos.common.log.NacosLogbackConfigurator;
import com.alibaba.nacos.common.spi.NacosServiceLoader;
import com.alibaba.nacos.client.logging.NacosLoggingAdapter;
import com.alibaba.nacos.client.logging.NacosLoggingProperties;
import com.alibaba.nacos.common.utils.ResourceUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.LoggerFactory;
import java.util.Collection;
/**
* Support for Logback version 1.0.8 or higher
* Support for Logback version 1.0.8 to 1.2.X.
*
* @author <a href="mailto:huangxiaoyu1018@gmail.com">hxy1991</a>
* @author <a href="mailto:hujun3@xiaomi.com">hujun</a>
* @author xiweng.yy
* @since 0.9.0
*/
public class LogbackNacosLogging extends AbstractNacosLogging {
public class LogbackNacosLoggingAdapter implements NacosLoggingAdapter {
private static final String NACOS_LOGBACK_LOCATION = "classpath:nacos-logback.xml";
private Integer userVersion = 2;
private static final String LOGBACK_CLASSES = "ch.qos.logback.classic.Logger";
private final NacosLogbackConfigurator configurator;
/**
* logback use 'ch.qos.logback.core.model.Model' since 1.3.0, set logback version during initialization.
*/
public LogbackNacosLogging() {
public LogbackNacosLoggingAdapter() {
configurator = new NacosLogbackConfiguratorAdapterV1();
}
@Override
public boolean isAdaptedLogger(Class<?> loggerClass) {
Class<?> expectedLoggerClass = getExpectedLoggerClass();
if (null == expectedLoggerClass || !expectedLoggerClass.isAssignableFrom(loggerClass)) {
return false;
}
return !isUpperLogback13();
}
private Class<?> getExpectedLoggerClass() {
try {
return Class.forName(LOGBACK_CLASSES);
} catch (ClassNotFoundException e) {
return null;
}
}
private boolean isUpperLogback13() {
try {
Class.forName("ch.qos.logback.core.model.Model");
return true;
} catch (ClassNotFoundException e) {
userVersion = 1;
return false;
}
}
@Override
public void loadConfiguration() {
LoggerContext loggerContext = loadConfigurationOnStart();
if (loggerContext.getObject(CoreConstants.RECONFIGURE_ON_CHANGE_TASK) != null && !hasListener(loggerContext)) {
addListener(loggerContext);
}
}
private boolean hasListener(LoggerContext loggerContext) {
for (LoggerContextListener loggerContextListener : loggerContext.getCopyOfListenerList()) {
if (loggerContextListener instanceof NacosLoggerContextListener) {
return true;
}
}
public boolean isNeedReloadConfiguration() {
return false;
}
private LoggerContext loadConfigurationOnStart() {
String location = getLocation(NACOS_LOGBACK_LOCATION);
@Override
public String getDefaultConfigLocation() {
return NACOS_LOGBACK_LOCATION;
}
@Override
public void loadConfiguration(NacosLoggingProperties loggingProperties) {
String location = loggingProperties.getLocation();
LoggerContext loggerContext = loadConfigurationOnStart(location);
if (loggerContext.getObject(CoreConstants.RECONFIGURE_ON_CHANGE_TASK) != null && hasNoListener(loggerContext)) {
addListener(loggerContext, location);
}
}
private boolean hasNoListener(LoggerContext loggerContext) {
for (LoggerContextListener loggerContextListener : loggerContext.getCopyOfListenerList()) {
if (loggerContextListener instanceof NacosLoggerContextListener) {
return false;
}
}
return true;
}
private LoggerContext loadConfigurationOnStart(final String location) {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Collection<NacosLogbackConfigurator> nacosLogbackConfigurators = NacosServiceLoader.load(
NacosLogbackConfigurator.class);
nacosLogbackConfigurators.stream().filter(c -> c.getVersion() == userVersion).findFirst()
.ifPresent(nacosLogbackConfigurator -> {
nacosLogbackConfigurator.setContext(loggerContext);
if (StringUtils.isNotBlank(location)) {
try {
nacosLogbackConfigurator.configure(ResourceUtils.getResourceUrl(location));
} catch (Exception e) {
throw new IllegalStateException(
"Could not initialize Logback Nacos logging from " + location, e);
}
}
});
configurator.setContext(loggerContext);
if (StringUtils.isNotBlank(location)) {
try {
configurator.configure(ResourceUtils.getResourceUrl(location));
} catch (Exception e) {
throw new IllegalStateException("Could not initialize Logback Nacos logging from " + location, e);
}
}
return loggerContext;
}
class NacosLoggerContextListener implements LoggerContextListener {
private final String location;
NacosLoggerContextListener(String location) {
this.location = location;
}
@Override
public boolean isResetResistant() {
return true;
@ -100,27 +132,24 @@ public class LogbackNacosLogging extends AbstractNacosLogging {
@Override
public void onReset(LoggerContext context) {
loadConfigurationOnStart();
loadConfigurationOnStart(location);
}
@Override
public void onStart(LoggerContext context) {
}
@Override
public void onStop(LoggerContext context) {
}
@Override
public void onLevelChange(Logger logger, Level level) {
}
}
private void addListener(LoggerContext loggerContext) {
loggerContext.addListener(new NacosLoggerContextListener());
private void addListener(LoggerContext loggerContext, String location) {
loggerContext.addListener(new NacosLoggerContextListener(location));
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.logging.logback;
import com.alibaba.nacos.client.env.NacosClientProperties;
import com.alibaba.nacos.common.log.NacosLogbackProperties;
/**
* adapter to higher version of logback (>= 1.4.5).
*
* @author hujun
*/
public class NacosClientLogbackProperties implements NacosLogbackProperties {
@Override
public String getValue(String source, String defaultValue) {
return NacosClientProperties.PROTOTYPE.getProperty(source, defaultValue);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2022 Alibaba Group Holding Ltd.
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.alibaba.nacos.common.log;
package com.alibaba.nacos.client.logging.logback;
import java.net.URL;
@ -31,12 +31,6 @@ public interface NacosLogbackConfigurator {
*/
void configure(URL resourceUrl) throws Exception;
/**
* logback configurator will be sorted by version.
* @return version
*/
int getVersion();
/**
* set loggerContext.
* @param loggerContext loggerContext

View File

@ -22,7 +22,7 @@ import ch.qos.logback.core.joran.event.SaxEvent;
import ch.qos.logback.core.joran.spi.ElementSelector;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.joran.spi.RuleStore;
import com.alibaba.nacos.common.log.NacosLogbackConfigurator;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@ -52,11 +52,6 @@ public class NacosLogbackConfiguratorAdapterV1 extends JoranConfigurator impleme
rs.addRule(new ElementSelector("configuration/nacosClientProperty"), new NacosClientPropertyAction());
}
@Override
public int getVersion() {
return 1;
}
@Override
public void setContext(Object loggerContext) {
super.setContext((Context) loggerContext);

View File

@ -0,0 +1,18 @@
#
# Copyright 1999-2023 Alibaba Group Holding Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
com.alibaba.nacos.client.logging.logback.LogbackNacosLoggingAdapter
com.alibaba.nacos.client.logging.log4j2.Log4J2NacosLoggingAdapter

View File

@ -1,18 +0,0 @@
#
# Copyright 1999-2021 Alibaba Group Holding Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
com.alibaba.nacos.client.logging.logback.NacosLogbackConfiguratorAdapterV1

View File

@ -1,18 +0,0 @@
#
# Copyright 1999-2021 Alibaba Group Holding Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
com.alibaba.nacos.client.logging.logback.NacosClientLogbackProperties

View File

@ -1,39 +0,0 @@
/*
*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.alibaba.nacos.client.logging;
import org.junit.Assert;
import org.junit.Test;
public class AbstractNacosLoggingTest {
@Test
public void testGetLocation() {
AbstractNacosLogging logging = new AbstractNacosLogging() {
@Override
public void loadConfiguration() {
}
};
String defaultLocation = "aa";
String actual = logging.getLocation(defaultLocation);
Assert.assertEquals(defaultLocation, actual);
}
}

View File

@ -19,15 +19,36 @@
package com.alibaba.nacos.client.logging;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.lang.reflect.Field;
import static org.mockito.Mockito.doThrow;
@RunWith(MockitoJUnitRunner.class)
public class NacosLoggingTest {
@Mock
NacosLoggingAdapter loggingAdapter;
NacosLoggingProperties loggingProperties;
NacosLogging instance;
@Before
public void setUp() throws NoSuchFieldException, IllegalAccessException {
loggingProperties = new NacosLoggingProperties("");
instance = NacosLogging.getInstance();
Field loggingPropertiesField = NacosLogging.class.getDeclaredField("loggingProperties");
loggingPropertiesField.setAccessible(true);
loggingPropertiesField.set(instance, loggingProperties);
}
@Test
public void testGetInstance() {
NacosLogging instance = NacosLogging.getInstance();
@ -36,25 +57,23 @@ public class NacosLoggingTest {
@Test
public void testLoadConfiguration() throws NoSuchFieldException, IllegalAccessException {
NacosLogging instance = NacosLogging.getInstance();
AbstractNacosLogging mockLogging = Mockito.mock(AbstractNacosLogging.class);
Field nacosLogging = NacosLogging.class.getDeclaredField("nacosLogging");
instance = NacosLogging.getInstance();
Field nacosLogging = NacosLogging.class.getDeclaredField("loggingAdapter");
nacosLogging.setAccessible(true);
nacosLogging.set(instance, mockLogging);
nacosLogging.set(instance, loggingAdapter);
instance.loadConfiguration();
Mockito.verify(mockLogging, Mockito.times(1)).loadConfiguration();
Mockito.verify(loggingAdapter, Mockito.times(1)).loadConfiguration(loggingProperties);
}
@Test
public void testLoadConfigurationWithException() throws NoSuchFieldException, IllegalAccessException {
NacosLogging instance = NacosLogging.getInstance();
Field nacosLoggingField = NacosLogging.class.getDeclaredField("nacosLogging");
instance = NacosLogging.getInstance();
Field nacosLoggingField = NacosLogging.class.getDeclaredField("loggingAdapter");
nacosLoggingField.setAccessible(true);
AbstractNacosLogging cachedLogging = (AbstractNacosLogging) nacosLoggingField.get(instance);
NacosLoggingAdapter cachedLogging = (NacosLoggingAdapter) nacosLoggingField.get(instance);
try {
AbstractNacosLogging mockLogging = Mockito.mock(AbstractNacosLogging.class);
doThrow(new RuntimeException()).when(mockLogging).loadConfiguration();
nacosLoggingField.set(instance, mockLogging);
doThrow(new RuntimeException()).when(loggingAdapter).loadConfiguration(loggingProperties);
nacosLoggingField.set(instance, loggingAdapter);
instance.loadConfiguration();
// without exception thrown
} finally {

View File

@ -18,6 +18,7 @@
package com.alibaba.nacos.client.logging.log4j2;
import com.alibaba.nacos.client.logging.NacosLoggingProperties;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
@ -40,6 +41,8 @@ import java.net.URL;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@ -47,18 +50,21 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class Log4J2NacosLoggingTest {
public class Log4J2NacosLoggingAdapterTest {
private static final String NACOS_LOGGER_PREFIX = "com.alibaba.nacos";
@Mock
PropertyChangeListener propertyChangeListener;
Log4J2NacosLogging log4J2NacosLogging;
NacosLoggingProperties nacosLoggingProperties;
Log4J2NacosLoggingAdapter log4J2NacosLoggingAdapter;
@Before
public void setUp() throws Exception {
log4J2NacosLogging = new Log4J2NacosLogging();
log4J2NacosLoggingAdapter = new Log4J2NacosLoggingAdapter();
nacosLoggingProperties = new NacosLoggingProperties("classpath:nacos-log4j2.xml");
LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
loggerContext.addPropertyChangeListener(propertyChangeListener);
}
@ -67,16 +73,35 @@ public class Log4J2NacosLoggingTest {
public void tearDown() throws Exception {
LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
loggerContext.removePropertyChangeListener(propertyChangeListener);
loggerContext.setConfigLocation(loggerContext.getConfigLocation());
System.clearProperty("nacos.logging.default.config.enabled");
System.clearProperty("nacos.logging.config");
}
@Test
public void testIsAdaptedLogger() {
assertTrue(log4J2NacosLoggingAdapter.isAdaptedLogger(org.apache.logging.slf4j.Log4jLogger.class));
assertFalse(log4J2NacosLoggingAdapter.isAdaptedLogger(ch.qos.logback.classic.Logger.class));
}
@Test
public void testIsNeedReloadConfiguration() {
assertTrue(log4J2NacosLoggingAdapter.isNeedReloadConfiguration());
log4J2NacosLoggingAdapter.loadConfiguration(nacosLoggingProperties);
assertFalse(log4J2NacosLoggingAdapter.isNeedReloadConfiguration());
}
@Test
public void testGetDefaultConfigLocation() {
assertEquals("classpath:nacos-log4j2.xml", log4J2NacosLoggingAdapter.getDefaultConfigLocation());
}
@Test
public void testLoadConfiguration() {
LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
Configuration contextConfiguration = loggerContext.getConfiguration();
assertEquals(0, contextConfiguration.getLoggers().size());
log4J2NacosLogging.loadConfiguration();
log4J2NacosLoggingAdapter.loadConfiguration(nacosLoggingProperties);
//then
verify(propertyChangeListener).propertyChange(any());
loggerContext = (LoggerContext) LogManager.getContext(false);
@ -92,30 +117,31 @@ public class Log4J2NacosLoggingTest {
@Test
public void testLoadConfigurationWithoutLocation() {
System.setProperty("nacos.logging.default.config.enabled", "false");
log4J2NacosLogging = new Log4J2NacosLogging();
log4J2NacosLogging.loadConfiguration();
log4J2NacosLoggingAdapter = new Log4J2NacosLoggingAdapter();
log4J2NacosLoggingAdapter.loadConfiguration(nacosLoggingProperties);
verify(propertyChangeListener, never()).propertyChange(any());
}
@Test(expected = IllegalStateException.class)
public void testLoadConfigurationWithWrongLocation() {
System.setProperty("nacos.logging.config", "http://localhost");
log4J2NacosLogging = new Log4J2NacosLogging();
log4J2NacosLogging.loadConfiguration();
log4J2NacosLoggingAdapter = new Log4J2NacosLoggingAdapter();
log4J2NacosLoggingAdapter.loadConfiguration(nacosLoggingProperties);
verify(propertyChangeListener, never()).propertyChange(any());
}
@Test
public void testGetConfigurationSourceForNonFileProtocol()
throws NoSuchMethodException, IOException, InvocationTargetException, IllegalAccessException {
Method getConfigurationSourceMethod = Log4J2NacosLogging.class
Method getConfigurationSourceMethod = Log4J2NacosLoggingAdapter.class
.getDeclaredMethod("getConfigurationSource", URL.class);
getConfigurationSourceMethod.setAccessible(true);
URL url = mock(URL.class);
InputStream inputStream = mock(InputStream.class);
when(url.openStream()).thenReturn(inputStream);
when(url.getProtocol()).thenReturn("http");
ConfigurationSource actual = (ConfigurationSource) getConfigurationSourceMethod.invoke(log4J2NacosLogging, url);
ConfigurationSource actual = (ConfigurationSource) getConfigurationSourceMethod
.invoke(log4J2NacosLoggingAdapter, url);
assertEquals(inputStream, actual.getInputStream());
assertEquals(url, actual.getURL());
}

View File

@ -23,6 +23,7 @@ import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.ReconfigureOnChangeTask;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.CoreConstants;
import com.alibaba.nacos.client.logging.NacosLoggingProperties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -36,24 +37,27 @@ import org.slf4j.impl.StaticLoggerBinder;
import java.lang.reflect.Field;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class LogbackNacosLoggingTest {
public class LogbackNacosLoggingAdapterTest {
LogbackNacosLogging logbackNacosLogging;
LogbackNacosLoggingAdapter logbackNacosLoggingAdapter;
@Mock
LoggerContextListener loggerContextListener;
ILoggerFactory cachedLoggerFactory;
NacosLoggingProperties loggingProperties;
@Before
public void setUp() throws NoSuchFieldException, IllegalAccessException {
logbackNacosLogging = new LogbackNacosLogging();
logbackNacosLoggingAdapter = new LogbackNacosLoggingAdapter();
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
if (loggerFactory instanceof LoggerContext) {
LoggerContext loggerContext = (LoggerContext) loggerFactory;
@ -64,6 +68,7 @@ public class LogbackNacosLoggingTest {
loggerContext.addListener(loggerContextListener);
setLoggerFactory(loggerContext);
}
loggingProperties = new NacosLoggingProperties("classpath:nacos-logback.xml");
}
@After
@ -88,7 +93,7 @@ public class LogbackNacosLoggingTest {
public void testLoadConfigurationSuccess() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.putObject(CoreConstants.RECONFIGURE_ON_CHANGE_TASK, new ReconfigureOnChangeTask());
logbackNacosLogging.loadConfiguration();
logbackNacosLoggingAdapter.loadConfiguration(loggingProperties);
for (Logger each : loggerContext.getLoggerList()) {
if (!"com.alibaba.nacos.client.naming".equals(each.getName())) {
continue;
@ -98,7 +103,7 @@ public class LogbackNacosLoggingTest {
boolean containListener = false;
LoggerContextListener listener = null;
for (LoggerContextListener each : loggerContext.getCopyOfListenerList()) {
if (each instanceof LogbackNacosLogging.NacosLoggerContextListener) {
if (each instanceof LogbackNacosLoggingAdapter.NacosLoggerContextListener) {
containListener = true;
listener = each;
break;
@ -106,10 +111,10 @@ public class LogbackNacosLoggingTest {
}
assertTrue(containListener);
// reload duplicate, without exception, listener not add again
logbackNacosLogging.loadConfiguration();
logbackNacosLoggingAdapter.loadConfiguration(loggingProperties);
containListener = false;
for (LoggerContextListener each : loggerContext.getCopyOfListenerList()) {
if (each instanceof LogbackNacosLogging.NacosLoggerContextListener) {
if (each instanceof LogbackNacosLoggingAdapter.NacosLoggerContextListener) {
assertEquals(listener, each);
containListener = true;
}
@ -117,17 +122,33 @@ public class LogbackNacosLoggingTest {
assertTrue(containListener);
}
@Test
public void testIsAdaptedLogger() {
assertTrue(logbackNacosLoggingAdapter.isAdaptedLogger(Logger.class));
assertFalse(logbackNacosLoggingAdapter.isAdaptedLogger(org.apache.logging.log4j.core.Logger.class));
}
@Test(expected = IllegalStateException.class)
public void testLoadConfigurationFailure() {
System.setProperty("nacos.logging.config", "http://localhost");
logbackNacosLogging.loadConfiguration();
logbackNacosLoggingAdapter.loadConfiguration(loggingProperties);
}
@Test
public void testIsNeedReloadConfiguration() {
assertFalse(logbackNacosLoggingAdapter.isNeedReloadConfiguration());
}
@Test
public void testGetDefaultConfigLocation() {
assertEquals("classpath:nacos-logback.xml", logbackNacosLoggingAdapter.getDefaultConfigLocation());
}
@Test
public void testLoadConfigurationReload() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.putObject(CoreConstants.RECONFIGURE_ON_CHANGE_TASK, new ReconfigureOnChangeTask());
logbackNacosLogging.loadConfiguration();
logbackNacosLoggingAdapter.loadConfiguration(loggingProperties);
loggerContext.reset();
verify(loggerContextListener).onReset(loggerContext);
for (Logger each : loggerContext.getLoggerList()) {
@ -142,7 +163,7 @@ public class LogbackNacosLoggingTest {
public void testLoadConfigurationStart() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.putObject(CoreConstants.RECONFIGURE_ON_CHANGE_TASK, new ReconfigureOnChangeTask());
logbackNacosLogging.loadConfiguration();
logbackNacosLoggingAdapter.loadConfiguration(loggingProperties);
loggerContext.start();
verify(loggerContextListener).onStart(loggerContext);
for (Logger each : loggerContext.getLoggerList()) {
@ -157,7 +178,7 @@ public class LogbackNacosLoggingTest {
public void testLoadConfigurationStop() {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.putObject(CoreConstants.RECONFIGURE_ON_CHANGE_TASK, new ReconfigureOnChangeTask());
logbackNacosLogging.loadConfiguration();
logbackNacosLoggingAdapter.loadConfiguration(loggingProperties);
loggerContext.stop();
verify(loggerContextListener).onReset(loggerContext);
verify(loggerContextListener, never()).onStop(loggerContext);

View File

@ -1,45 +0,0 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.client.logging.logback;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class NacosClientLogbackPropertiesTest {
NacosClientLogbackProperties nacosClientLogbackProperties;
@Before
public void setUp() throws Exception {
System.setProperty("nacos.logging.logback.test", "test");
nacosClientLogbackProperties = new NacosClientLogbackProperties();
}
@After
public void tearDown() throws Exception {
System.clearProperty("nacos.logging.logback.test");
}
@Test
public void testGetValue() {
assertEquals("test", nacosClientLogbackProperties.getValue("nacos.logging.logback.test", ""));
assertEquals("", nacosClientLogbackProperties.getValue("nacos.logging.logback.non.exist", ""));
}
}

View File

@ -1,32 +0,0 @@
/*
* Copyright 1999-2022 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.common.log;
/**
* nacos logback properties.
* @author hujun
*/
public interface NacosLogbackProperties {
/**
* get value.
*
* @param source source
* @param defaultValue defaultValue
* @return value
*/
String getValue(String source, String defaultValue);
}