This is an automated email from the ASF dual-hosted git repository.

gaoxihui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozhera.git


The following commit(s) were added to refs/heads/master by this push:
     new e9f14e23 feat: add log level filtering for collection (#549)
e9f14e23 is described below

commit e9f14e23cc577774d698eaa7bef4dee567dc3eb4
Author: Xue <[email protected]>
AuthorDate: Mon Mar 10 11:08:09 2025 +0800

    feat: add log level filtering for collection (#549)
    
    * feat: add log level filtering for collection
    
    - Implements a new feature to filter log collection based on log levels.
    - Allows users to specify the desired log levels for collection, enhancing 
the system's flexibility and user experience.
    - The implementation includes a configuration option to specify the desired 
log levels and corresponding filtering logic in the log collection module.
    
    * feat: add log level filtering for collection
    
    - Implements a new feature to filter log collection based on log levels.
    - Allows users to specify the desired log levels for collection, enhancing 
the system's flexibility and user experience.
    - The implementation includes a configuration option to specify the desired 
log levels and corresponding filtering logic in the log collection module.
    
    * feat: Add Nacos global log level configuration
    
    Implement a new feature to dynamically adjust the log level across the 
system via Nacos configuration. This allows centralized management of log 
levels, improving system observability and operational efficiency.
    
    * refactor(log): optimize log level filter configuration management
    
    - Fix potential NPEs in config handling
    - Improve error handling and retry mechanism
    - Enhance thread pool management
    - Add better logging
    
    * fix: Fixes the NPE and collection traversal issues in the global 
configuration of log filtering
    
    - Fixed null pointer exception caused by TailExtensionService dependency 
injection failure
    - Use a normal for loop to avoid concurrent modification exceptions for 
enhanced traversal
    - Optimize configuration update logic to ensure atomicity of collection 
operations
    
    * fix: Improve log collection and filtering logic to enhance reliability 
and reduce redundant logs
    
     -Refine log filtering logic for better reliability and performance
    
    * fix: remove non-standard comments
    
    -remove non-standard comments
    
    * feat: add log level filtering for collection
    
    - Implements a new feature to filter log collection based on log levels.
    - Allows users to specify the desired log levels for collection, enhancing 
the system's flexibility and user experience.
    - The implementation includes a configuration option to specify the desired 
log levels and corresponding filtering logic in the log collection module.
    
    * fix: fixed some issues in log filtering
    
    - fixed some issues in log filtering.
    
    * fix: fixed some issues in log filtering
    
    - fixed some issues in log filtering.
    
    ---------
    
    Co-authored-by: wtt <[email protected]>
    Co-authored-by: gaoxh <[email protected]>
---
 .../log/agent/channel/AbstractChannelService.java  |  20 ++
 .../ozhera/log/agent/channel/ChannelDefine.java    |   2 +
 .../log/agent/channel/ChannelServiceImpl.java      |   6 +-
 .../agent/channel/WildcardChannelServiceImpl.java  |   3 +-
 .../channel/locator/ChannelDefineRpcLocator.java   |   1 +
 .../log-agent/src/main/resources/config.properties |   4 +-
 .../src/main/resources/config/dev.properties       |   4 +-
 .../src/main/resources/config/open.properties      |   4 +-
 .../log/agent/channel/ChannelServiceTest.java      | 139 ++++++++++++
 .../ozhera/log/api/model/meta/LogPattern.java      |   5 +
 .../ozhera/log/manager/dao/MilogLogTailDao.java    |   8 +
 .../log/manager/job/LogLevelFilterConfig.java      |  25 +++
 .../job/extension/DefaultLogLevelFilterConfig.java |  38 ++++
 .../ozhera/log/manager/model/bo/LogTailParam.java  |   3 +
 .../log/manager/model/pojo/MilogLogTailDo.java     |   7 +
 .../extension/agent/MilogAgentServiceImpl.java     |   3 +
 .../manager/service/impl/LogTailServiceImpl.java   |   5 +
 .../nacos/ManagerLevelFilterConfigListener.java    | 243 +++++++++++++++++++++
 .../service/nacos/ManagerLogFilterConfig.java      |  34 +++
 19 files changed, 549 insertions(+), 5 deletions(-)

diff --git 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/AbstractChannelService.java
 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/AbstractChannelService.java
index 2dd95a47..bf011466 100644
--- 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/AbstractChannelService.java
+++ 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/AbstractChannelService.java
@@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 import static org.apache.ozhera.log.common.Constant.GSON;
+import static org.apache.ozhera.log.utils.ConfigUtils.getConfigValue;
 
 /**
  * @author wtt
@@ -50,6 +51,8 @@ public abstract class AbstractChannelService implements 
ChannelService {
 
     public String instanceId = UUID.randomUUID().toString();
 
+    private final int FILTER_LOG_PREFIX_LENGTH = 
Integer.parseInt(getConfigValue("filter_log_level_prefix_length"));
+
     @Override
     public String instanceId() {
         return instanceId;
@@ -202,4 +205,21 @@ public abstract class AbstractChannelService implements 
ChannelService {
         fileProgress.setPodType(channelDefine.getPodType());
         fileProgress.setCtTime(ct);
     }
+
+    public Boolean shouldFilterLogs(List<String> logLevelList, String line){
+        if (logLevelList == null || logLevelList.isEmpty()) {
+            return false;
+        }
+        if (line.length() > FILTER_LOG_PREFIX_LENGTH){
+            line = line.substring(0, FILTER_LOG_PREFIX_LENGTH);
+        }
+        String lineLowerCase = line.toLowerCase();
+        for (String level : logLevelList) {
+            if (lineLowerCase.contains(level.toLowerCase())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
 }
diff --git 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelDefine.java
 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelDefine.java
index 7299267e..636c4c4a 100644
--- 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelDefine.java
+++ 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelDefine.java
@@ -71,4 +71,6 @@ public class ChannelDefine implements Serializable {
      */
     private String delDirectory;
 
+    private List<String> filterLogLevelList;
+
 }
diff --git 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelServiceImpl.java
 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelServiceImpl.java
index 65ccd27c..bcf8c3aa 100644
--- 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelServiceImpl.java
+++ 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/ChannelServiceImpl.java
@@ -42,6 +42,7 @@ import org.apache.ozhera.log.api.enums.K8sPodTypeEnum;
 import org.apache.ozhera.log.api.enums.LogTypeEnum;
 import org.apache.ozhera.log.api.model.meta.FilterConf;
 import org.apache.ozhera.log.api.model.msg.LineMessage;
+import org.apache.ozhera.log.common.Config;
 import org.apache.ozhera.log.common.Constant;
 import org.apache.ozhera.log.common.PathUtils;
 import org.apache.ozhera.log.utils.NetUtil;
@@ -311,7 +312,9 @@ public class ChannelServiceImpl extends 
AbstractChannelService {
                 return;
             }
             long ct = System.currentTimeMillis();
-            readResult.get().getLines().stream().forEach(l -> {
+            readResult.get().getLines().stream()
+                    .filter(l -> 
!shouldFilterLogs(channelDefine.getFilterLogLevelList(), l))
+                    .forEach(l -> {
                 String logType = channelDefine.getInput().getType();
                 LogTypeEnum logTypeEnum = LogTypeEnum.name2enum(logType);
                 // Multi-line application log type and opentelemetry type are 
used to determine the exception stack
@@ -612,6 +615,7 @@ public class ChannelServiceImpl extends 
AbstractChannelService {
         return monitorFileList;
     }
 
+    @Override
     public ChannelDefine getChannelDefine() {
         return channelDefine;
     }
diff --git 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/WildcardChannelServiceImpl.java
 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/WildcardChannelServiceImpl.java
index b1efef22..b9ad7963 100644
--- 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/WildcardChannelServiceImpl.java
+++ 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/WildcardChannelServiceImpl.java
@@ -43,6 +43,7 @@ import org.apache.ozhera.log.agent.input.Input;
 import org.apache.ozhera.log.api.enums.LogTypeEnum;
 import org.apache.ozhera.log.api.model.meta.FilterConf;
 import org.apache.ozhera.log.api.model.msg.LineMessage;
+import org.apache.ozhera.log.common.Config;
 import org.apache.ozhera.log.common.PathUtils;
 
 import java.io.File;
@@ -289,7 +290,7 @@ public class WildcardChannelServiceImpl extends 
AbstractChannelService {
         ReadResult result = readResult.get();
 
         LogTypeEnum logTypeEnum = getLogTypeEnum();
-        result.getLines().forEach(line -> {
+        result.getLines().stream().filter(line -> 
!shouldFilterLogs(channelDefine.getFilterLogLevelList(), line)).forEach(line -> 
{
             if (LogTypeEnum.APP_LOG_MULTI == logTypeEnum || 
LogTypeEnum.OPENTELEMETRY == logTypeEnum) {
                 line = mLog.append2(line);
             }
diff --git 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/locator/ChannelDefineRpcLocator.java
 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/locator/ChannelDefineRpcLocator.java
index a0e23432..eccf3435 100644
--- 
a/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/locator/ChannelDefineRpcLocator.java
+++ 
b/ozhera-log/log-agent/src/main/java/org/apache/ozhera/log/agent/channel/locator/ChannelDefineRpcLocator.java
@@ -122,6 +122,7 @@ public class ChannelDefineRpcLocator implements 
ChannelDefineLocator {
                 ChannelDefine cloneChannelDefine = 
ObjectUtil.clone(channelDefine);
                 cloneChannelDefine.setChannelId(logPattern.getLogtailId());
                 cloneChannelDefine.setTailName(logPattern.getTailName());
+                
cloneChannelDefine.setFilterLogLevelList(logPattern.getFilterLogLevelList());
                 //input
                 AppLogInput input = new AppLogInput();
                 input.setType(logPattern.getLogType() != null ? 
LogTypeEnum.getLogTypeName(logPattern.getLogType()) : "");
diff --git a/ozhera-log/log-agent/src/main/resources/config.properties 
b/ozhera-log/log-agent/src/main/resources/config.properties
index de72fe5f..45284224 100644
--- a/ozhera-log/log-agent/src/main/resources/config.properties
+++ b/ozhera-log/log-agent/src/main/resources/config.properties
@@ -33,4 +33,6 @@ app_id=${app_id}
 env_id=${env_id}
 env_name=${env_name}
 
-registration_initiation_flag=true
\ No newline at end of file
+registration_initiation_flag=true
+
+filter_log_level_prefix_length = ${filter_log_level_prefix_length}
\ No newline at end of file
diff --git a/ozhera-log/log-agent/src/main/resources/config/dev.properties 
b/ozhera-log/log-agent/src/main/resources/config/dev.properties
index 79e5407b..8305f380 100644
--- a/ozhera-log/log-agent/src/main/resources/config/dev.properties
+++ b/ozhera-log/log-agent/src/main/resources/config/dev.properties
@@ -22,4 +22,6 @@ agent.channel.locator=json
 
 app_id=10010
 env_id=1
-env_name=default_env
\ No newline at end of file
+env_name=default_env
+
+filter_log_level_prefix_length = 60
\ No newline at end of file
diff --git a/ozhera-log/log-agent/src/main/resources/config/open.properties 
b/ozhera-log/log-agent/src/main/resources/config/open.properties
index 71f50d84..919ca098 100644
--- a/ozhera-log/log-agent/src/main/resources/config/open.properties
+++ b/ozhera-log/log-agent/src/main/resources/config/open.properties
@@ -24,4 +24,6 @@ agent.channel.locator=rpc
 
 app_id=10010
 env_id=1
-env_name=default_env
\ No newline at end of file
+env_name=default_env
+
+filter_log_level_prefix_length = 60
\ No newline at end of file
diff --git 
a/ozhera-log/log-agent/src/test/java/org/apache/ozhera/log/agent/channel/ChannelServiceTest.java
 
b/ozhera-log/log-agent/src/test/java/org/apache/ozhera/log/agent/channel/ChannelServiceTest.java
index 62daa614..19d1529b 100644
--- 
a/ozhera-log/log-agent/src/test/java/org/apache/ozhera/log/agent/channel/ChannelServiceTest.java
+++ 
b/ozhera-log/log-agent/src/test/java/org/apache/ozhera/log/agent/channel/ChannelServiceTest.java
@@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.junit.Test;
 
 import java.nio.file.FileSystems;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
@@ -117,4 +118,142 @@ public class ChannelServiceTest {
         log.warn("logPattern -> regex:{}", logPattern);
         return Pattern.compile(logPattern);
     }
+
+
+    @Test
+    public void testShouldCollectLogs() {
+        String line = "2025-02-12 19:24:27,076|WARN 
||ExecutorUtil-STP-Virtual-Thread1|o.a.ozhera.log.agent.common.ExecutorUtil|65|Executor
 statistic 
STP_EXECUTOR:java.util.concurrent.ScheduledThreadPoolExecutor@792b749c[Running, 
pool size = 6, active threads = 1, queued tasks = 0, completed tasks = 5]";
+        List list = new ArrayList();
+        list.add("INFO");
+        list.add("WARN");
+        list.add("ERROR");
+        System.out.println(shouldCollectLogs(list, line, 40));
+    }
+
+    @Test
+    public void test() {
+        String logContent =
+                "19:52:35,792 |-INFO in 
ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not 
set\n" +
+                        "19:52:35,794 |-INFO in 
ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender 
of type [ch.qos.logback.core.ConsoleAppender]\n" +
+                        "19:52:35,796 |-INFO in 
ch.qos.logback.core.joran.action.AppenderAction - Naming appender as 
[stdout]\n" +
+                        "19:52:35,849 |-WARN in 
ch.qos.logback.core.ConsoleAppender[stdout] - This appender no longer admits a 
layout as a sub-component, set an encoder instead.\n" +
+                        "19:52:35,849 |-WARN in 
ch.qos.logback.core.ConsoleAppender[stdout] - To ensure compatibility, wrapping 
your layout in LayoutWrappingEncoder.\n" +
+                        "19:52:35,849 |-WARN in 
ch.qos.logback.core.ConsoleAppender[stdout] - See also 
http://logback.qos.ch/codes.html#layoutInsteadOfEncoder for details\n" +
+                        "19:52:35,849 |-INFO in 
ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender 
of type [ch.qos.logback.core.rolling.RollingFileAppender]\n" +
+                        "19:52:35,851 |-INFO in 
ch.qos.logback.core.joran.action.AppenderAction - Naming appender as 
[logfile]\n" +
+                        "19:52:35,851 |-INFO in 
ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default 
type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] 
property\n" +
+                        "19:52:35,859 |-INFO in 
c.q.l.core.rolling.TimeBasedRollingPolicy@1794717576 - No compression will be 
used\n" +
+                        "19:52:35,859 |-INFO in 
c.q.l.core.rolling.TimeBasedRollingPolicy@1794717576 - Will use the pattern 
/home/work/log/log-agent/server.log.%d{yyyy-MM-dd-HH} for the active file\n" +
+                        "19:52:35,861 |-INFO in 
c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - The date 
pattern is 'yyyy-MM-dd-HH' from file name pattern 
'/home/work/log/log-agent/server.log.%d{yyyy-MM-dd-HH}'.\n" +
+                        "19:52:35,861 |-INFO in 
c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Roll-over at 
the top of every hour.\n" +
+                        "19:52:35,904 |-INFO in 
c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy - Setting 
initial period to Wed Feb 12 19:52:35 CST 2025\n" +
+                        "19:52:35,905 |-INFO in 
c.q.l.core.rolling.TimeBasedRollingPolicy@1794717576 - Cleaning on start up\n" +
+                        "19:52:35,907 |-INFO in 
c.q.l.core.rolling.helper.TimeBasedArchiveRemover - first clean up after 
appender initialization\n" +
+                        "19:52:35,908 |-INFO in 
ch.qos.logback.core.rolling.RollingFileAppender[logfile] - Active log file 
name: /home/work/log/log-agent/server.log\n" +
+                        "19:52:35,908 |-INFO in 
ch.qos.logback.core.rolling.RollingFileAppender[logfile] - File property is set 
to [/home/work/log/log-agent/server.log]\n" +
+                        "19:52:36,177 |-ERROR in 
ch.qos.logback.core.rolling.RollingFileAppender[logfile] - Failed to create 
parent directories for [/home/work/log/log-agent/server.log]\n" +
+                        "19:52:36,188 |-ERROR in 
ch.qos.logback.core.rolling.RollingFileAppender[logfile] - 
openFile(/home/work/log/log-agent/server.log,true) call failed. 
java.io.FileNotFoundException: /home/work/log/log-agent/server.log (No such 
file or directory)\n" +
+                        "\tat java.io.FileNotFoundException: 
/home/work/log/log-agent/server.log (No such file or directory)\n" +
+                        "\tat 
\tjava.base/java.io.FileOutputStream.open0(Native Method)\n" +
+                        "\tat 
\tjava.base/java.io.FileOutputStream.open(FileOutputStream.java:289)\n" +
+                        "\tat 
\tjava.base/java.io.FileOutputStream.<init>(FileOutputStream.java:230)\n" +
+                        "\tat 
\tch.qos.logback.core.recovery.ResilientFileOutputStream.<init>(ResilientFileOutputStream.java:26)\n"
 +
+                        "\tat 
\tch.qos.logback.core.FileAppender.openFile(FileAppender.java:204)\n" +
+                        "\tat 
\tch.qos.logback.core.FileAppender.start(FileAppender.java:127)\n" +
+                        "\tat 
\tch.qos.logback.core.rolling.RollingFileAppender.start(RollingFileAppender.java:100)\n"
 +
+                        "\tat 
\tch.qos.logback.core.joran.action.AppenderAction.end(AppenderAction.java:90)\n"
 +
+                        "\tat 
\tch.qos.logback.core.joran.spi.Interpreter.callEndAction(Interpreter.java:309)\n"
 +
+                        "\tat 
\tch.qos.logback.core.joran.spi.Interpreter.endElement(Interpreter.java:193)\n" 
+
+                        "\tat 
\tch.qos.logback.core.joran.spi.Interpreter.endElement(Interpreter.java:179)\n" 
+
+                        "\tat 
\tch.qos.logback.core.joran.spi.EventPlayer.play(EventPlayer.java:62)\n" +
+                        "\tat 
\tch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:165)\n"
 +
+                        "\tat 
\tch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:152)\n"
 +
+                        "\tat 
\tch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:110)\n"
 +
+                        "\tat 
\tch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:53)\n"
 +
+                        "\tat 
\tch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:64)\n"
 +
+                        "\tat 
\tch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:134)\n"
 +
+                        "\tat 
\torg.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)\n" +
+                        "\tat 
\torg.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)\n" +
+                        "\tat 
\torg.slf4j.LoggerFactory.bind(LoggerFactory.java:150)\n" +
+                        "\tat 
\torg.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)\n" +
+                        "\tat 
\torg.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:417)\n" +
+                        "\tat 
\torg.slf4j.LoggerFactory.getLogger(LoggerFactory.java:362)\n" +
+                        "\tat 
\torg.slf4j.LoggerFactory.getLogger(LoggerFactory.java:388)\n" +
+                        "\tat 
\torg.apache.ozhera.log.agent.channel.ChannelServiceTest.<clinit>(ChannelServiceTest.java:44)\n"
 +
+                        "\tat 
\tjava.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)\n" +
+                        "\tat 
\tjava.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1160)\n"
 +
+                        "\tat 
\tjava.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(MethodHandleAccessorFactory.java:340)\n"
 +
+                        "\tat 
\tjava.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(MethodHandleAccessorFactory.java:103)\n"
 +
+                        "\tat 
\tjava.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(ReflectionFactory.java:173)\n"
 +
+                        "\tat 
\tjava.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Constructor.java:549)\n"
 +
+                        "\tat 
\tjava.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)\n"
 +
+                        "\tat 
\tjava.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)\n" +
+                        "\tat 
\torg.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:250)\n"
 +
+                        "\tat 
\torg.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:260)\n"
 +
+                        "\tat 
\torg.junit.runners.BlockJUnit4ClassRunner$2.runReflectiveCall(BlockJUnit4ClassRunner.java:309)\n"
 +
+                        "\tat 
\torg.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n"
 +
+                        "\tat 
\torg.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:306)\n"
 +
+                        "\tat 
\torg.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)\n"
 +
+                        "\tat 
\torg.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)\n" +
+                        "\tat 
\torg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)\n"
 +
+                        "\tat 
\torg.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)\n"
 +
+                        "\tat 
\torg.junit.runners.ParentRunner$4.run(ParentRunner.java:331)\n" +
+                        "\tat 
\torg.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)\n" +
+                        "\tat 
\torg.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)\n" +
+                        "\tat 
\torg.junit.runners.ParentRunner.access$100(ParentRunner.java:66)\n" +
+                        "\tat 
\torg.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)\n" +
+                        "\tat 
\torg.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)\n" +
+                        "\tat 
\torg.junit.runners.ParentRunner.run(ParentRunner.java:413)\n" +
+                        "\tat 
\torg.junit.runner.JUnitCore.run(JUnitCore.java:137)\n" +
+                        "\tat 
\tcom.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)\n"
 +
+                        "\tat 
\tcom.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)\n"
 +
+                        "\tat 
\tcom.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)\n"
 +
+                        "\tat 
\tcom.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)\n"
 +
+                        "\tat 
\tcom.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)\n"
 +
+                        "\tat 
\tcom.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)\n" +
+                        "19:52:36,188 |-INFO in 
ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger 
[org.springframework] to ERROR\n" +
+                        "19:52:36,188 |-INFO in 
ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger 
[ch.qos.logback] to ERROR\n" +
+                        "19:52:36,188 |-INFO in 
ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger 
[com.xiaomi.data.push.service.state] to ERROR\n" +
+                        "19:52:36,188 |-INFO in 
ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger 
[org.reflections.Reflections] to ERROR\n" +
+                        "19:52:36,188 |-INFO in 
ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger 
[com.xiaomi.infra.galaxy] to ERROR\n" +
+                        "19:52:36,188 |-INFO in 
ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT 
logger to INFO\n" +
+                        "19:52:36,188 |-INFO in 
ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named 
[stdout] to Logger[ROOT]\n" +
+                        "19:52:36,189 |-INFO in 
ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named 
[logfile] to Logger[ROOT]\n" +
+                        "19:52:36,189 |-INFO in 
ch.qos.logback.classic.joran.action.ConfigurationAction - End of 
configuration.\n" +
+                        "19:52:36,189 |-INFO in 
ch.qos.logback.classic.joran.JoranConfigurator@6ef888f6 - Registering current 
configuration as safe fallback point";
+
+        List<String> lines = new 
ArrayList<>(Arrays.asList(logContent.split("\n")));
+        long s = System.currentTimeMillis();
+        List list = new ArrayList();
+        list.add("WARN");
+        list.add("ERROR");
+        System.out.println("++++++++++++");
+        for (String line : lines) {
+            if (shouldCollectLogs(list, line, 40)) {
+                System.out.println(line);
+            }
+        }
+        long e = System.currentTimeMillis();
+        System.out.println(e - s);
+
+    }
+
+
+    public Boolean shouldCollectLogs(List<String> logLevelList, String line, 
Integer prefixLength) {
+        if (logLevelList == null || logLevelList.isEmpty()) {
+            return true;
+        }
+        if (line == null || line.isEmpty()) {
+            return false;
+        }
+        if (line.length() > prefixLength) {
+            line = line.substring(0, prefixLength);
+        }
+        for (String level : logLevelList) {
+            if (line.contains(level)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git 
a/ozhera-log/log-api/src/main/java/org/apache/ozhera/log/api/model/meta/LogPattern.java
 
b/ozhera-log/log-api/src/main/java/org/apache/ozhera/log/api/model/meta/LogPattern.java
index c3f1c6e0..872ed0a3 100644
--- 
a/ozhera-log/log-api/src/main/java/org/apache/ozhera/log/api/model/meta/LogPattern.java
+++ 
b/ozhera-log/log-api/src/main/java/org/apache/ozhera/log/api/model/meta/LogPattern.java
@@ -44,6 +44,11 @@ public class LogPattern implements Serializable {
 
     private List<String> ips;
 
+    /**
+     * Level of logs to be collected
+     */
+    private List<String> filterLogLevelList;
+
     /**
      * IP and directory correspondence
      */
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/dao/MilogLogTailDao.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/dao/MilogLogTailDao.java
index 5594aa4d..d74b3c32 100644
--- 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/dao/MilogLogTailDao.java
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/dao/MilogLogTailDao.java
@@ -274,6 +274,14 @@ public class MilogLogTailDao {
         return sql.getList(MilogLogTailDo.class);
     }
 
+    public List<MilogLogTailDo> getLogTailByLastId(Long lastId, int pageSize) {
+        Sql sql = Sqls.queryEntity("SELECT * FROM milog_logstail WHERE id > 
@lastId ORDER BY id LIMIT @pageSize");
+        sql.params().set("lastId", lastId);
+        sql.params().set("pageSize", pageSize);
+        dao.execute(sql);
+        return sql.getList(MilogLogTailDo.class);
+    }
+
     public List<MilogLogTailDo> queryStoreIdByRegionNameEN(String nameEn) {
         Sql sql = Sqls.queryEntity("SELECT * FROM `milog_logstail` where 
JSON_CONTAINS(motor_rooms, JSON_OBJECT(\"nameEn\", @nameEn))");
         sql.params().set("nameEn", nameEn);
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/job/LogLevelFilterConfig.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/job/LogLevelFilterConfig.java
new file mode 100644
index 00000000..fea89348
--- /dev/null
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/job/LogLevelFilterConfig.java
@@ -0,0 +1,25 @@
+/*
+ * 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 org.apache.ozhera.log.manager.job;
+
+import org.apache.ozhera.log.manager.service.nacos.ManagerLogFilterConfig;
+
+public interface LogLevelFilterConfig {
+    ManagerLogFilterConfig getGlobalLogLevelFilterConfig();
+}
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/job/extension/DefaultLogLevelFilterConfig.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/job/extension/DefaultLogLevelFilterConfig.java
new file mode 100644
index 00000000..90b5fcf4
--- /dev/null
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/job/extension/DefaultLogLevelFilterConfig.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.apache.ozhera.log.manager.job.extension;
+
+import com.xiaomi.youpin.docean.anno.Component;
+import org.apache.ozhera.log.manager.job.LogLevelFilterConfig;
+import 
org.apache.ozhera.log.manager.service.nacos.ManagerLevelFilterConfigListener;
+import org.apache.ozhera.log.manager.service.nacos.ManagerLogFilterConfig;
+
+import javax.annotation.Resource;
+
+@Component
+public class DefaultLogLevelFilterConfig implements LogLevelFilterConfig {
+
+    @Resource
+    private ManagerLevelFilterConfigListener listener;
+
+    @Override
+    public ManagerLogFilterConfig getGlobalLogLevelFilterConfig() {
+        return listener.queryFilterConfig();
+    }
+}
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/bo/LogTailParam.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/bo/LogTailParam.java
index 1de93cf6..a4ba0b27 100644
--- 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/bo/LogTailParam.java
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/bo/LogTailParam.java
@@ -82,4 +82,7 @@ public class LogTailParam {
     private Boolean collectionReady = true;
 
     private String originSystem;
+
+    private List<String> logLevelList;
+
 }
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/pojo/MilogLogTailDo.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/pojo/MilogLogTailDo.java
index ccc4ea08..c3824a54 100644
--- 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/pojo/MilogLogTailDo.java
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/pojo/MilogLogTailDo.java
@@ -162,6 +162,13 @@ public class MilogLogTailDo extends BaseCommon {
     @Comment("Indicates the system that originated the record; 'hera' for 
internal, and others for external sources.")
     private String originSystem;
 
+    @Column(value = "filter_log_levels")
+    @ColDefine(type = ColType.MYSQL_JSON)
+    @Comment("Level list of logs to be collected.")
+    @JSONField
+    private List<String> filterLogLevelList;
+
+
     public MilogLogTailDo() {
     }
 
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/extension/agent/MilogAgentServiceImpl.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/extension/agent/MilogAgentServiceImpl.java
index 79d5e16f..a278c817 100644
--- 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/extension/agent/MilogAgentServiceImpl.java
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/extension/agent/MilogAgentServiceImpl.java
@@ -391,6 +391,9 @@ public class MilogAgentServiceImpl implements 
MilogAgentService {
                 logPattern.setLogPattern(milogLogtailDo.getLogPath());
             }
         }
+        if (null != milogLogtailDo.getFilterLogLevelList() && 
!milogLogtailDo.getFilterLogLevelList().isEmpty()) {
+            
logPattern.setFilterLogLevelList(milogLogtailDo.getFilterLogLevelList());
+        }
         String tag = Utils.createTag(milogLogtailDo.getSpaceId(), 
milogLogtailDo.getStoreId(), milogLogtailDo.getId());
         logPattern.setPatternCode(tag);
         return logPattern;
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/impl/LogTailServiceImpl.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/impl/LogTailServiceImpl.java
index 1236d7ee..6dfdecde 100644
--- 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/impl/LogTailServiceImpl.java
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/impl/LogTailServiceImpl.java
@@ -673,6 +673,11 @@ public class LogTailServiceImpl extends BaseService 
implements LogTailService {
         
milogLogtailDo.setFirstLineReg((StringUtils.isNotEmpty(logTailParam.getFirstLineReg())
 ? logTailParam.getFirstLineReg() : ""));
         milogLogtailDo.setCollectionReady(logTailParam.getCollectionReady());
         milogLogtailDo.setOriginSystem(logTailParam.getOriginSystem());
+
+        if (logTailParam.getLogLevelList() != null && 
!logTailParam.getLogLevelList().isEmpty()) {
+            
milogLogtailDo.setFilterLogLevelList(logTailParam.getLogLevelList());
+        }
+
         return milogLogtailDo;
     }
 
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/nacos/ManagerLevelFilterConfigListener.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/nacos/ManagerLevelFilterConfigListener.java
new file mode 100644
index 00000000..535b14b5
--- /dev/null
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/nacos/ManagerLevelFilterConfigListener.java
@@ -0,0 +1,243 @@
+/*
+ * 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 org.apache.ozhera.log.manager.service.nacos;
+
+import cn.hutool.core.thread.ThreadUtil;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.xiaomi.data.push.common.SafeRun;
+import com.xiaomi.youpin.docean.anno.Component;
+import com.xiaomi.youpin.docean.plugin.nacos.NacosConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ozhera.log.manager.dao.MilogLogTailDao;
+import org.apache.ozhera.log.manager.dao.MilogLogstoreDao;
+import org.apache.ozhera.log.manager.mapper.MilogLogTemplateMapper;
+import org.apache.ozhera.log.manager.model.pojo.MilogLogStoreDO;
+import org.apache.ozhera.log.manager.model.pojo.MilogLogTailDo;
+import org.apache.ozhera.log.manager.service.bind.LogTypeProcessor;
+import org.apache.ozhera.log.manager.service.bind.LogTypeProcessorFactory;
+import 
org.apache.ozhera.log.manager.service.extension.tail.TailExtensionService;
+import 
org.apache.ozhera.log.manager.service.extension.tail.TailExtensionServiceFactory;
+
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Queue;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+
+import static org.apache.ozhera.log.common.Constant.*;
+
+@Slf4j
+@Component
+public class ManagerLevelFilterConfigListener {
+
+    @Resource
+    private NacosConfig nacosConfig;
+
+    @Resource
+    private MilogLogTemplateMapper milogLogTemplateMapper;
+
+    @Resource
+    private LogTypeProcessorFactory logTypeProcessorFactory;
+
+    private LogTypeProcessor logTypeProcessor;
+
+    @Resource
+    private MilogLogTailDao logtailDao;
+
+    @Resource
+    private MilogLogstoreDao logStoreDao;
+
+    private TailExtensionService tailExtensionService;
+
+    private final String logLevelFilterKey = "log.level.filter.config.manager";
+
+    private volatile ManagerLogFilterConfig config;
+
+    private static final int BATCH_SIZE = 1000;
+
+
+    private final ExecutorService logUpdateExecutor = new ThreadPoolExecutor(
+            Runtime.getRuntime().availableProcessors(),
+            Runtime.getRuntime().availableProcessors() * 2,
+            60L, TimeUnit.SECONDS,
+            new LinkedBlockingQueue<>(1000),
+            new 
ThreadFactoryBuilder().setNameFormat("global-log-config-update-thread-%d").build(),
+            new ThreadPoolExecutor.CallerRunsPolicy()
+    );
+
+    public void init() {
+        
logTypeProcessorFactory.setMilogLogTemplateMapper(milogLogTemplateMapper);
+        logTypeProcessor = logTypeProcessorFactory.getLogTypeProcessor();
+        tailExtensionService = 
TailExtensionServiceFactory.getTailExtensionService();
+        ScheduledExecutorService scheduledExecutor = Executors
+                
.newSingleThreadScheduledExecutor(ThreadUtil.newNamedThreadFactory("log-level-filter-manager",
 false));
+        scheduledExecutor.scheduleAtFixedRate(() ->
+                SafeRun.run(() -> configChangeOperator()), 1, 1, 
TimeUnit.MINUTES);
+
+    }
+
+    public void configChangeOperator() {
+        String filterConfig = nacosConfig.getConfigStr(logLevelFilterKey, 
DEFAULT_GROUP_ID, DEFAULT_TIME_OUT_MS);
+        ManagerLogFilterConfig newConfig = GSON.fromJson(filterConfig, 
ManagerLogFilterConfig.class);
+
+        if (Objects.equals(config, newConfig)) return;
+
+
+        if ((config == null || !config.getEnableGlobalFilter()) && (newConfig 
== null || !newConfig.getEnableGlobalFilter())) {
+            List<MilogLogTailDo> updateMilogLogtailList = new ArrayList<>();
+            List<MilogLogTailDo> oldLogtailList = new ArrayList<>();
+            if (config != null) {
+                oldLogtailList = 
logtailDao.getMilogLogtail(config.getTailIdList());
+            }
+            if (newConfig != null) {
+                List<MilogLogTailDo> newLogtailList = 
logtailDao.getMilogLogtail(newConfig.getTailIdList());
+                newLogtailList.forEach(tail -> 
tail.setFilterLogLevelList(newConfig.getLogLevelList()));
+                oldLogtailList = oldLogtailList.stream().filter(tail -> 
!newLogtailList.contains(tail)).toList();
+                updateMilogLogtailList.addAll(newLogtailList);
+            }
+            oldLogtailList.forEach(tail -> tail.setFilterLogLevelList(new 
ArrayList<>()));
+            updateMilogLogtailList.addAll(oldLogtailList);
+
+            for (MilogLogTailDo tailDo : updateMilogLogtailList) {
+                boolean isSuccess = logtailDao.update(tailDo);
+                if (isSuccess){
+                    updateSingleTail(tailDo);
+                }
+            }
+        }
+
+        if (newConfig.getEnableGlobalFilter() || 
config.getEnableGlobalFilter()) {
+
+            if (newConfig.getEnableGlobalFilter() && 
config.getEnableGlobalFilter() && 
areElementsSameIgnoreCase(newConfig.getLogLevelList(), 
config.getLogLevelList())) {
+                return;
+            }
+            globalUpdateSendMsg();
+        }
+        config = newConfig;
+    }
+
+    public void globalUpdateSendMsg() {
+        AtomicLong lastId = new AtomicLong(0L);
+        ConcurrentLinkedQueue<MilogLogTailDo> failedTailList = new 
ConcurrentLinkedQueue<>();
+        List<CompletableFuture<Void>> futureList = new ArrayList<>();
+        try {
+            while (true) {
+                List<MilogLogTailDo> logTailByLastIdList = 
logtailDao.getLogTailByLastId(lastId.get(), BATCH_SIZE);
+                if (logTailByLastIdList.isEmpty()) break;
+                CompletableFuture<Void> future = CompletableFuture.runAsync(() 
-> {
+                    logTailByLastIdList.forEach(tail -> {
+                        try {
+                            updateSingleTail(tail);
+                        } catch (Exception e) {
+                            failedTailList.offer(tail);
+                            log.error("Failed to update tail: {}", 
tail.getId(), e);
+                        }
+                    });
+                }, logUpdateExecutor);
+                futureList.add(future);
+                lastId.set(logTailByLastIdList.get(logTailByLastIdList.size() 
- 1).getId());
+            }
+
+            CompletableFuture.allOf(futureList.toArray(new 
CompletableFuture[0])).join();
+
+            if (!failedTailList.isEmpty()) {
+                handleFailedTails(failedTailList);
+            }
+        } catch (Exception e) {
+            log.error("Global log config update failed", e);
+        }
+    }
+
+    private void handleFailedTails(Queue<MilogLogTailDo> failedTailList) {
+
+        failedTailList.forEach(tail -> {
+            for (int retryCount = 1; retryCount <= 3; retryCount++) {
+                try {
+                    updateSingleTail(tail);
+                    break;
+                } catch (Exception e) {
+                    if (retryCount == 3) {
+                        log.error("Max retry attempts reached for tail: {}", 
tail.getId(), e);
+                    } else {
+                        log.warn("Retry {} failed for tail: {}", retryCount, 
tail.getId(), e);
+                    }
+                }
+            }
+        });
+
+
+    }
+
+    private void updateSingleTail(MilogLogTailDo tail) {
+        MilogLogStoreDO logStoreDO = logStoreDao.queryById(tail.getStoreId());
+        Integer appType = tail.getAppType();
+        boolean processSwitch = 
tailExtensionService.bindPostProcessSwitch(tail.getStoreId());
+        if (tailExtensionService.bindMqResourceSwitch(logStoreDO, appType) || 
processSwitch) {
+            try {
+                List<String> ips = tail.getIps();
+                boolean supportedConsume = 
logTypeProcessor.supportedConsume(logStoreDO.getLogType());
+                tailExtensionService.updateSendMsg(tail, ips, 
supportedConsume);
+            } catch (Exception e) {
+                log.error("Update tail error during global log config update", 
e);
+                throw e;
+            }
+        }
+    }
+
+    boolean areElementsSameIgnoreCase(List<String> listA, List<String> listB) {
+        if (listA == null || listB == null) {
+            return listA == listB;
+        }
+        return listA.stream()
+                .map(String::toLowerCase)
+                .distinct()
+                .sorted()
+                .collect(Collectors.toList())
+                .equals(
+                        listB.stream()
+                                .map(String::toLowerCase)
+                                .distinct()
+                                .sorted()
+                                .collect(Collectors.toList())
+                );
+    }
+
+    @PreDestroy
+    public void destroy() {
+        try {
+            log.info("Shutting down global log config update executor");
+            logUpdateExecutor.shutdown();
+            if (!logUpdateExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
+                logUpdateExecutor.shutdownNow();
+            }
+        } catch (InterruptedException e) {
+            logUpdateExecutor.shutdownNow();
+            throw new RuntimeException(e);
+        }
+    }
+
+    public ManagerLogFilterConfig queryFilterConfig() {
+        return config;
+    }
+
+}
diff --git 
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/nacos/ManagerLogFilterConfig.java
 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/nacos/ManagerLogFilterConfig.java
new file mode 100644
index 00000000..938ca532
--- /dev/null
+++ 
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/nacos/ManagerLogFilterConfig.java
@@ -0,0 +1,34 @@
+/*
+ * 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 org.apache.ozhera.log.manager.service.nacos;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ManagerLogFilterConfig {
+
+    private List<Long> tailIdList;
+
+    private Boolean enableGlobalFilter;
+
+    private List<String> logLevelList;
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to