diff --git a/examples/src/main/java/group/rxcloud/capa/examples/log/DemoLog.java b/examples/src/main/java/group/rxcloud/capa/examples/telemetry/DemoLog.java similarity index 90% rename from examples/src/main/java/group/rxcloud/capa/examples/log/DemoLog.java rename to examples/src/main/java/group/rxcloud/capa/examples/telemetry/DemoLog.java index 20ac7e2..93ef506 100644 --- a/examples/src/main/java/group/rxcloud/capa/examples/log/DemoLog.java +++ b/examples/src/main/java/group/rxcloud/capa/examples/telemetry/DemoLog.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package group.rxcloud.capa.examples.log; +package group.rxcloud.capa.examples.telemetry; import lombok.extern.slf4j.Slf4j; @@ -30,6 +30,11 @@ public class DemoLog { public static void main(String[] args) { - log.info("test"); + try { + log.info("test"); + }catch (Exception e){ + System.out.println(); + } + } } diff --git a/pom.xml b/pom.xml index 5fb5bf2..9b98361 100644 --- a/pom.xml +++ b/pom.xml @@ -414,5 +414,4 @@ - \ No newline at end of file diff --git a/sdk-component/pom.xml b/sdk-component/pom.xml index a669e53..370c378 100644 --- a/sdk-component/pom.xml +++ b/sdk-component/pom.xml @@ -35,6 +35,9 @@ 1.4.10 2.8.2 1.1.7 + 19.0 + 3.11 + 3.2.2 @@ -98,7 +101,13 @@ true ${logback.version} - + + ch.qos.logback + logback-classic + + true + ${logback.version} + org.junit.jupiter junit-jupiter-engine @@ -109,6 +118,21 @@ mockito-core test + + com.google.guava + guava + ${guava-version} + + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + + + commons-collections + commons-collections + ${commons-collections-version} + diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLog4jAppenderAgent.java b/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLog4jAppenderAgent.java index e05cd68..2957661 100644 --- a/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLog4jAppenderAgent.java +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLog4jAppenderAgent.java @@ -16,6 +16,8 @@ */ package group.rxcloud.capa.component.log.agent; +import group.rxcloud.capa.component.log.enums.CapaLogLevel; +import group.rxcloud.capa.component.log.manager.LogManager; import group.rxcloud.capa.infrastructure.CapaClassLoader; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Filter; @@ -28,6 +30,7 @@ import org.apache.logging.log4j.core.config.plugins.PluginFactory; import java.io.Serializable; +import java.util.Optional; /** * The abstract log4j appender. Extend this and provide your specific impl. @@ -97,7 +100,12 @@ public static CapaLog4jAppender buildCapaLog4jAppender() { @Override public void append(LogEvent event) { - logAppender.appendLog(event); + if (event != null && event.getLevel() != null) { + Optional capaLogLevel = CapaLogLevel.toCapaLogLevel(event.getLevel().name()); + if (capaLogLevel.isPresent() && LogManager.whetherLogsCanBeOutput(capaLogLevel.get())) { + logAppender.appendLog(event); + } + } } /** diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgent.java b/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgent.java index c4c0d54..fb9d86a 100644 --- a/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgent.java +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgent.java @@ -16,13 +16,18 @@ */ package group.rxcloud.capa.component.log.agent; +import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.UnsynchronizedAppenderBase; +import group.rxcloud.capa.component.log.enums.CapaLogLevel; +import group.rxcloud.capa.component.log.manager.LogManager; import group.rxcloud.capa.infrastructure.CapaClassLoader; +import java.util.Optional; + /** * The agent of the logback impl. */ -public class CapaLogbackAppenderAgent extends UnsynchronizedAppenderBase { +public class CapaLogbackAppenderAgent extends UnsynchronizedAppenderBase { /** * The log component type. @@ -58,20 +63,25 @@ public static CapaLogbackAppender buildCapaLogbackAppender() { * @param event The log event. */ @Override - protected void append(EVENT event) { - logbackAppender.appendLog(event); + protected void append(ILoggingEvent event) { + if (event != null && event.getLevel() != null) { + Optional capaLogLevel = CapaLogLevel.toCapaLogLevel(event.getLevel().levelStr); + if (capaLogLevel.isPresent() && LogManager.whetherLogsCanBeOutput(capaLogLevel.get())) { + logbackAppender.appendLog(event); + } + } } /** * The abstract api of the logback appender impl.Implement this and provide your specific impl. */ - public interface CapaLogbackAppender { + public interface CapaLogbackAppender { /** * Deal with the log. * * @param event The log event. */ - void appendLog(EVENT event); + void appendLog(ILoggingEvent event); } } diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/log/configuration/LogSwitchConfiguration.java b/sdk-component/src/main/java/group/rxcloud/capa/component/log/configuration/LogSwitchConfiguration.java new file mode 100644 index 0000000..9d8d3f2 --- /dev/null +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/log/configuration/LogSwitchConfiguration.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 group.rxcloud.capa.component.log.configuration; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import group.rxcloud.capa.infrastructure.hook.ConfigurationHooks; +import group.rxcloud.capa.infrastructure.hook.Mixer; +import group.rxcloud.cloudruntimes.domain.core.configuration.SubConfigurationResp; +import group.rxcloud.cloudruntimes.utils.TypeRef; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import reactor.core.publisher.Flux; + +import java.util.Map; +import java.util.Optional; + +/** + * Log switch configuration + */ +public class LogSwitchConfiguration { + + /** + * Capa configuration hooks. + */ + private static final Optional configurationHooks; + /** + * Log switch config file name. + */ + private static final String LOGS_SWITCH_CONFIG_FILE_NAME = "log-level-switch.properties"; + /** + * Log switch config's value. + */ + private static Map logsSwitchConfig = Maps.newHashMap(); + + /** + * Init configuration hooks and subscribe configuration. + */ + static { + configurationHooks = Mixer.configurationHooksNullable(); + configurationHooks.ifPresent(configurationHooks -> { + subscribeConfiguration(configurationHooks); + }); + } + + /** + * Subscribe configuration. + * + * @param configurationHooks + */ + private static void subscribeConfiguration(ConfigurationHooks configurationHooks) { + String storeName = configurationHooks.registryStoreNames().get(0); + String appId = configurationHooks.defaultConfigurationAppId(); + Flux> configFlux = configurationHooks.subscribeConfiguration( + storeName, + appId, + Lists.newArrayList(LOGS_SWITCH_CONFIG_FILE_NAME), + null, + StringUtils.EMPTY, + StringUtils.EMPTY, + TypeRef.get(Map.class)); + configFlux.subscribe(resp -> { + if (CollectionUtils.isNotEmpty(resp.getItems())) { + logsSwitchConfig = resp.getItems().get(0).getContent(); + } + }); + } + + /** + * Get the log switch config's values. + * + * @return the log switch config's values. + */ + public static Map getLogsSwitchConfig() { + return logsSwitchConfig; + } +} diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/log/enums/CapaLogLevel.java b/sdk-component/src/main/java/group/rxcloud/capa/component/log/enums/CapaLogLevel.java new file mode 100644 index 0000000..099fac3 --- /dev/null +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/log/enums/CapaLogLevel.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 group.rxcloud.capa.component.log.enums; + +import java.util.Arrays; +import java.util.Optional; + +/** + * Capa log level. + */ +public enum CapaLogLevel { + /** + * Standard order of log priorities:ALL,TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF + */ + ALL(1, "ALL"), + TRACE(2, "TRACE"), + DEBUG(3, "DEBUG"), + INFO(4, "INFO"), + WARN(5, "WARN"), + ERROR(6, "ERROR"), + FATAL(7, "FATAL"), + OFF(8, "OFF"); + + final int level; + final String levelName; + + CapaLogLevel(int level, String levelName) { + this.level = level; + this.levelName = levelName; + } + + /** + * Convert logLevelArg to {@link CapaLogLevel} + * + * @param logLevelArg + * @return + */ + public static Optional toCapaLogLevel(String logLevelArg) { + return Arrays.stream(CapaLogLevel.values()) + .filter(logLevel -> logLevel.levelName.equalsIgnoreCase(logLevelArg)) + .findAny(); + } + + /** + * Get level. + * + * @return + */ + public int getLevel() { + return level; + } + + public String getLevelName() { + return levelName; + } +} diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/log/manager/LogManager.java b/sdk-component/src/main/java/group/rxcloud/capa/component/log/manager/LogManager.java new file mode 100644 index 0000000..fba8605 --- /dev/null +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/log/manager/LogManager.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 group.rxcloud.capa.component.log.manager; + +import group.rxcloud.capa.component.log.configuration.LogSwitchConfiguration; +import group.rxcloud.capa.component.log.enums.CapaLogLevel; + +import java.util.Map; + +/** + * LogManager, to manage log output levels. + */ +public class LogManager { + + /** + * Dynamically adjust the log level switch name. + */ + private static final String LOG_LEVEL_SWITCH_NAME = "logLevelSwitch"; + /** + * All level switch name. + */ + private static final String ALL_LEVEL_SWITCH_NAME = "allLevelSwitch"; + /** + * Trace level switch name. + */ + private static final String TRACE_LEVEL_SWITCH_NAME = "traceLevelSwitch"; + /** + * Debug level switch name. + */ + private static final String DEBUG_LEVEL_SWITCH_NAME = "debugLevelSwitch"; + /** + * Info level switch name. + */ + private static final String INFO_LEVEL_SWITCH_NAME = "infoLevelSwitch"; + /** + * Warn level switch. + */ + private static final String WARN_LEVEL_SWITCH_NAME = "warnLevelSwitch"; + /** + * Error level switch. + */ + private static final String ERROR_LEVEL_SWITCH_NAME = "errorLevelSwitch"; + /** + * Fatal level switch + */ + private static final String FATAL_LEVEL_SWITCH_NAME = "fatalLevelSwitch"; + /** + * Off level switch. + */ + private static final String OFF_LEVEL_SWITCH_NAME = "offLevelSwitch"; + + /** + * Whether logs can be output. + * If there is no corresponding configuration information or the switch of dynamic configuration log level is set to false, + * then only logs of info level and above will be output. + *

+ * If the value of the dynamic configuration log level switch is true, only the log with the log level configured as true will be output. + *

+ * If the log level is not in the {@link CapaLogLevel#values()}, the log is not output. + * + * @param capaLogLevel + * @return If the log can be output, it is true, otherwise it is false. + */ + public static Boolean whetherLogsCanBeOutput(CapaLogLevel capaLogLevel) { + Map logsSwitchConfigs = LogSwitchConfiguration.getLogsSwitchConfig(); + //no configuration instance or logs switch configuration, then follow the default logic. + if (logsSwitchConfigs == null + || logsSwitchConfigs.isEmpty() + || Boolean.FALSE.equals(logsSwitchConfigs.get(LOG_LEVEL_SWITCH_NAME))) { + return isLogsLevelClosedWithDefault(capaLogLevel); + } + + switch (capaLogLevel) { + case ALL: + return logsSwitchConfigs.get(ALL_LEVEL_SWITCH_NAME) == null + ? Boolean.FALSE + : logsSwitchConfigs.get(ALL_LEVEL_SWITCH_NAME); + case TRACE: + return logsSwitchConfigs.get(TRACE_LEVEL_SWITCH_NAME) == null + ? Boolean.FALSE + : logsSwitchConfigs.get(TRACE_LEVEL_SWITCH_NAME); + case DEBUG: + return logsSwitchConfigs.get(DEBUG_LEVEL_SWITCH_NAME) == null + ? Boolean.FALSE + : logsSwitchConfigs.get(DEBUG_LEVEL_SWITCH_NAME); + case INFO: + return logsSwitchConfigs.get(INFO_LEVEL_SWITCH_NAME) == null + ? Boolean.TRUE + : logsSwitchConfigs.get(INFO_LEVEL_SWITCH_NAME); + case WARN: + return logsSwitchConfigs.get(WARN_LEVEL_SWITCH_NAME) == null + ? Boolean.TRUE + : logsSwitchConfigs.get(WARN_LEVEL_SWITCH_NAME); + case ERROR: + return logsSwitchConfigs.get(ERROR_LEVEL_SWITCH_NAME) == null + ? Boolean.TRUE + : logsSwitchConfigs.get(ERROR_LEVEL_SWITCH_NAME); + case FATAL: + return logsSwitchConfigs.get(FATAL_LEVEL_SWITCH_NAME) == null + ? Boolean.TRUE + : logsSwitchConfigs.get(FATAL_LEVEL_SWITCH_NAME); + case OFF: + return logsSwitchConfigs.get(OFF_LEVEL_SWITCH_NAME) == null + ? Boolean.TRUE + : logsSwitchConfigs.get(OFF_LEVEL_SWITCH_NAME) == null; + default: + return Boolean.FALSE; + } + } + + /** + * Logs of the {@link CapaLogLevel#INFO} level or higher are normally output, but logs of the {@link CapaLogLevel#INFO} level lower are not output. + * + * @param capaLogLevel + * @return whether the capaLogLevel's priority is equal or more then {@link CapaLogLevel#INFO}. + */ + private static Boolean isLogsLevelClosedWithDefault(CapaLogLevel capaLogLevel) { + return capaLogLevel.getLevel() >= CapaLogLevel.INFO.getLevel(); + } +} diff --git a/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgentTest.java b/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgentTest.java index 16b61fc..e8f3759 100644 --- a/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgentTest.java +++ b/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/CapaLogbackAppenderAgentTest.java @@ -16,8 +16,7 @@ */ package group.rxcloud.capa.component.log.agent; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.message.Message; +import ch.qos.logback.classic.spi.ILoggingEvent; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -33,10 +32,8 @@ void testBuildCapaLogbackAppender() { @Test void testAppend() { CapaLogbackAppenderAgent.CapaLogbackAppender capaLogbackAppender = CapaLogbackAppenderAgent.buildCapaLogbackAppender(); - LogEvent logEvent = Mockito.mock(LogEvent.class); - Message message = Mockito.mock(Message.class); - Mockito.when(logEvent.getMessage()).thenReturn(Mockito.mock(Message.class)); - Mockito.when(message.getFormattedMessage()).thenReturn("TEST"); + ILoggingEvent logEvent = Mockito.mock(ILoggingEvent.class); + Mockito.when(logEvent.getFormattedMessage()).thenReturn("TEST"); capaLogbackAppender.appendLog(logEvent); } } \ No newline at end of file diff --git a/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/TestCapaLogbackAppender.java b/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/TestCapaLogbackAppender.java index af58bcd..67f911f 100644 --- a/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/TestCapaLogbackAppender.java +++ b/sdk-component/src/test/java/group/rxcloud/capa/component/log/agent/TestCapaLogbackAppender.java @@ -16,19 +16,19 @@ */ package group.rxcloud.capa.component.log.agent; -import org.apache.logging.log4j.core.LogEvent; +import ch.qos.logback.classic.spi.ILoggingEvent; /** * The capa logback appender used in tests only. */ -public class TestCapaLogbackAppender implements CapaLogbackAppenderAgent.CapaLogbackAppender { +public class TestCapaLogbackAppender implements CapaLogbackAppenderAgent.CapaLogbackAppender { public TestCapaLogbackAppender() { } @Override - public void appendLog(LogEvent event) { - System.out.println("test logback log and content is " + event.getMessage().getFormattedMessage()); + public void appendLog(ILoggingEvent event) { + System.out.println("test logback log and content is " + event.getFormattedMessage()); } } diff --git a/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLog4jAppender.java b/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLog4jAppender.java index ccf07cc..f94df0f 100644 --- a/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLog4jAppender.java +++ b/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLog4jAppender.java @@ -23,6 +23,6 @@ public class DemoLog4jAppender implements CapaLog4jAppenderAgent.CapaLog4jAppend @Override public void appendLog(LogEvent event) { - System.out.println("test log log4j and content is " + event.getMessage().getFormattedMessage()); + System.out.println("Test log log4j and content is " + event.getMessage().getFormattedMessage()); } } diff --git a/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLogbackAppender.java b/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLogbackAppender.java index c6029cd..8e5ee40 100644 --- a/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLogbackAppender.java +++ b/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/log/DemoLogbackAppender.java @@ -19,13 +19,13 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import group.rxcloud.capa.component.log.agent.CapaLogbackAppenderAgent; -public class DemoLogbackAppender implements CapaLogbackAppenderAgent.CapaLogbackAppender { +public class DemoLogbackAppender implements CapaLogbackAppenderAgent.CapaLogbackAppender { public DemoLogbackAppender() { } @Override public void appendLog(ILoggingEvent event) { - System.out.println("test logback log and content is " + event.getFormattedMessage()); + System.out.println("Test logback log and content is " + event.getFormattedMessage()); } }