Pārlūkot izejas kodu

解决在 springboot 中以编程方式配置 logback

reghao 5 gadi atpakaļ
vecāks
revīzija
3932602362

+ 6 - 1
dagent/src/main/java/cn/reghao/autodop/dagent/DagentApplication.java

@@ -1,8 +1,10 @@
 package cn.reghao.autodop.dagent;
 
 import cn.reghao.autodop.dagent.utils.lifecycle.BeforeAppShutdown;
+import cn.reghao.autodop.dagent.utils.spring.LoggingInitializer;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 
@@ -15,6 +17,9 @@ public class DagentApplication {
 	}
 
 	public static void main(String[] args) {
-		SpringApplication.run(DagentApplication.class, args);
+		SpringApplication app = new SpringApplication(DagentApplication.class);
+		app.addInitializers(new LoggingInitializer());
+		app.run(args);
+		//SpringApplication.run(DagentApplication.class, args);
 	}
 }

+ 16 - 0
dagent/src/main/java/cn/reghao/autodop/dagent/machine/timer/HeartbeatJob.java

@@ -1,5 +1,9 @@
 package cn.reghao.autodop.dagent.machine.timer;
 
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
 import cn.reghao.autodop.common.amqp.MqMessage;
 import cn.reghao.autodop.common.amqp.MessageType;
 import cn.reghao.autodop.common.amqp.RabbitProducer;
@@ -9,6 +13,8 @@ import cn.reghao.autodop.common.utils.serializer.JsonConverter;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.*;
 
+import java.util.Iterator;
+
 /**
  * 机器心跳任务
  *
@@ -28,6 +34,16 @@ public class HeartbeatJob implements Job {
         MqMessage mqMessage = MqMessage.mqMessage(MessageType.machineType.name(),
                 MachineOps.machineHeartbeatOps.name(), false, payload);
         rabbitProducer.send("amq.direct", "dmaster", mqMessage);
+
+        LoggerContext loggerContext = ((Logger) log).getLoggerContext();
+        Logger logger = loggerContext.getLogger("Main");
+        Iterator<Appender<ILoggingEvent>> iterator = logger.iteratorForAppenders();
+        while (iterator.hasNext()) {
+            Appender<ILoggingEvent> appender = iterator.next();
+            String appenderName = appender.getName();
+            System.out.println();
+        }
+
         log.info("发送机器心跳...");
     }
 }

+ 88 - 0
dagent/src/main/java/cn/reghao/autodop/dagent/utils/spring/LoggingInitializer.java

@@ -0,0 +1,88 @@
+package cn.reghao.autodop.dagent.utils.spring;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.ConsoleAppender;
+import ch.qos.logback.core.FileAppender;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.rabbit.logback.AmqpAppender;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.annotation.Order;
+
+/**
+ * 编程方式配置 logback,相当于 logback-spring.xml 配置
+ *
+ * @author reghao
+ * @date 2021-02-23 23:53:35
+ */
+@Order
+public class LoggingInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
+    @Override
+    public void initialize(ConfigurableApplicationContext applicationContext) {
+        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+        Logger rootLogger = loggerContext.getLogger("ROOT");
+        rootLogger.setAdditive(false);
+        rootLogger.setLevel(Level.INFO);
+        rootLogger.addAppender(amqpAppender(loggerContext));
+    }
+
+    private Appender<ILoggingEvent> amqpAppender(LoggerContext loggerContext) {
+        PatternLayoutEncoder layoutEncoder = new PatternLayoutEncoder();
+        layoutEncoder.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n");
+        layoutEncoder.setContext(loggerContext);
+        layoutEncoder.start();
+
+        AmqpAppender amqpAppender = new AmqpAppender();
+        amqpAppender.setName("mqAppender");
+        amqpAppender.setAddresses("localhost:5672");
+        amqpAppender.setUsername("dev");
+        amqpAppender.setPassword("Dev@12345678");
+        amqpAppender.setDeclareExchange(true);
+        amqpAppender.setExchangeType("direct");
+        amqpAppender.setExchangeName("rabbit.log");
+        amqpAppender.setRoutingKeyPattern("info");
+        amqpAppender.setDurable(true);
+        amqpAppender.setAutoDelete(false);
+        amqpAppender.setDeliveryMode("NON_PERSISTENT");
+        amqpAppender.setGenerateId(true);
+        amqpAppender.setCharset("UTF-8");
+        amqpAppender.setContext(loggerContext);
+        amqpAppender.setEncoder(layoutEncoder);
+        amqpAppender.start();
+
+        return amqpAppender;
+    }
+
+    private Appender<ILoggingEvent> fileAppender(LoggerContext loggerContext) {
+        PatternLayoutEncoder layoutEncoder = new PatternLayoutEncoder();
+        layoutEncoder.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n");
+        layoutEncoder.setContext(loggerContext);
+        layoutEncoder.start();
+
+        FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>();
+        fileAppender.setFile("file");
+        fileAppender.setEncoder(layoutEncoder);
+        fileAppender.setContext(loggerContext);
+        fileAppender.start();
+
+        return fileAppender;
+    }
+
+    private Appender<ILoggingEvent> consoleAppender(LoggerContext loggerContext) {
+        PatternLayoutEncoder layoutEncoder = new PatternLayoutEncoder();
+        layoutEncoder.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %c %M %L - %msg%n");
+        layoutEncoder.setContext(loggerContext);
+        layoutEncoder.start();
+
+        ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
+        consoleAppender.start();
+
+        return consoleAppender;
+    }
+}

+ 42 - 0
dagent/src/main/resources/logback-spring.ba.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志文件的绝对路径 -->
+    <property name="LOG_HOME" value="/home/reghao/dev/logs" />
+
+    <!-- 日志输出到控制台 -->
+    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <!-- 日志输出格式 -->
+            <pattern>
+                %d{HH:mm:ss.SSS} [%thread] %-5level %c %M %L - %msg%n
+            </pattern>
+        </layout>
+    </appender>
+
+    <!-- 日志输出到 MQ -->
+    <appender name="mqLog" class="org.springframework.amqp.rabbit.logback.AmqpAppender">
+        <layout>
+            <pattern><![CDATA[ %d %p %t [%c] - <%m>%n ]]></pattern>
+        </layout>
+
+        <!-- RabbitMQ 配置 -->
+        <addresses>localhost:5672</addresses>
+        <username>dev</username>
+        <password>Dev@12345678</password>
+        <declareExchange>true</declareExchange>
+        <exchangeType>direct</exchangeType>
+        <exchangeName>rabbit.log</exchangeName>
+        <routingKeyPattern>info</routingKeyPattern>
+        <generateId>true</generateId>
+        <charset>UTF-8</charset>
+        <durable>true</durable>
+        <deliveryMode>NON_PERSISTENT</deliveryMode>
+        <autoDelete>false</autoDelete>
+    </appender>
+
+    <!-- 日志输出级别,level 默认值 DEBUG,root 其实是 logger,它是 logger 的根 -->
+    <root level="INFO">
+        <appender-ref ref="consoleLog"/>
+        <appender-ref ref="mqLog"/>
+    </root>
+</configuration>

+ 0 - 81
dagent/src/main/resources/logback-spring.xml.bak

@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<configuration>
-    <!-- 这个配置项需要用到这个ConsoleAppender处理 -->
-    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
-        <!-- layout就是一个展示的形式 -->
-        <layout class="ch.qos.logback.classic.PatternLayout">
-            <!-- 具体格式 -->
-            <pattern>
-                %d{HH:mm:ss.SSS} [%thread] %-5level %c %M %L - %msg%n
-            </pattern>
-        </layout>
-    </appender>
-
-    <!-- 滚动的info文件输出 -->
-    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <filter class="ch.qos.logback.classic.filter.LevelFilter">
-            <level>ERROR</level>
-            <!-- 如果匹配则禁止 -->
-            <onMatch>DENY</onMatch>
-            <!-- 如果没有命中, 则使用 -->
-            <onMismatch>ACCEPT</onMismatch>
-        </filter>
-        <encoder>
-            <pattern>
-                %d{HH:mm:ss.SSS} %-5level %c %M %L - %msg%n
-            </pattern>
-            <charset>UTF-8</charset>
-        </encoder>
-        <!-- 滚动策略 -->
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 路径 , 在日志的文件名里面加入时间-->
-            <fileNamePattern>
-                logs/info.%d.log
-            </fileNamePattern>
-        </rollingPolicy>
-    </appender>
-
-    <!-- 滚动的error文件输出 -->
-    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <level>ERROR</level>
-        </filter>
-        <encoder>
-            <pattern>
-                %d{HH:mm:ss.SSS} %-5level %c %M %L - %msg%n
-            </pattern>
-            <charset>UTF-8</charset>
-        </encoder>
-        <!-- 滚动策略 -->
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 路径 , 在日志的文件名里面加入时间-->
-            <fileNamePattern>
-                logs/error.%d.log
-            </fileNamePattern>
-        </rollingPolicy>
-    </appender>
-
-    <springProfile name="prod">
-        <!-- 日志开启级别 -->
-        <root level="info">
-            <appender-ref ref="fileInfoLog"></appender-ref>
-            <appender-ref ref="fileErrorLog"></appender-ref>
-        </root>
-    </springProfile>
-
-    <springProfile name="test">
-        <!-- 日志开启级别 -->
-        <root level="info">
-            <appender-ref ref="fileInfoLog"></appender-ref>
-            <appender-ref ref="fileErrorLog"></appender-ref>
-        </root>
-    </springProfile>
-
-    <springProfile name="dev">
-        <!-- 日志开启级别 -->
-        <root level="info">
-            <appender-ref ref="consoleLog"></appender-ref>
-        </root>
-    </springProfile>
-</configuration>

+ 0 - 44
dagent/src/main/resources/logback.xml

@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<configuration debug="false">
-    <!--定义日志文件的绝对路径-->
-    <property name="LOG_HOME" value="/home/reghao/dev/logs" />
-
-    <!-- 控制台输出 -->
-    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-            <!--格式化输出,%d:日期;%thread:线程名;%-5level:级别,从左显示5个字符宽度;%msg:日志消息;%n:换行符-->
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
-        </encoder>
-    </appender>
-
-    <!-- 输出到 MQ -->
-    <appender name="RABBITMQ" class="org.springframework.amqp.rabbit.logback.AmqpAppender">
-        <layout>
-            <pattern><![CDATA[ %d %p %t [%c] - <%m>%n ]]></pattern>
-        </layout>
-        <!--rabbitmq地址 -->
-        <addresses>localhost:5672</addresses>
-        <username>dev</username>
-        <password>Dev@12345678</password>
-        <declareExchange>true</declareExchange>
-        <exchangeType>direct</exchangeType>
-        <exchangeName>rabbit.log</exchangeName>
-        <routingKeyPattern>info</routingKeyPattern>
-        <generateId>true</generateId>
-        <charset>UTF-8</charset>
-        <durable>true</durable>
-        <deliveryMode>NON_PERSISTENT</deliveryMode>
-        <autoDelete>false</autoDelete>
-    </appender>
-
-    <logger name="cn.reghao.rabbitmq" level="info" additivity="false">
-        <appender-ref ref="STDOUT"/>
-        <appender-ref ref="RABBITMQ"/>
-    </logger>
-
-    <!-- 日志输出级别,level 默认值 DEBUG,root 其实是 logger,它是 logger 的根 -->
-    <root level="INFO">
-        <appender-ref ref="STDOUT" />
-        <appender-ref ref="RABBITMQ" />
-    </root>
-</configuration>

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/amqp/DmasterConsumer.java

@@ -15,7 +15,7 @@ import org.springframework.stereotype.Component;
  * @date 2020-09-04 11:00:22
  */
 @Slf4j
-@Component
+//@Component
 public class DmasterConsumer implements MessageListener {
     private MessageDispatcher machineMessageDispatcher;
 

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/amqp/DmasterConsumerConfig.java

@@ -16,7 +16,7 @@ import org.springframework.context.annotation.Configuration;
  * @author reghao
  * @date 2020-09-04 10:57:56
  */
-@Configuration
+//@Configuration
 public class DmasterConsumerConfig {
     private DmasterConsumer dmasterConsumer;
 
@@ -37,9 +37,9 @@ public class DmasterConsumerConfig {
     }
 
     @Bean
-    Binding bindingQueueToExchange(Queue queue, DirectExchange directExchange) {
+    Binding bindingQueueToExchange(DirectExchange directExchange) {
         String routeKey = Machine.machineId();
-        return BindingBuilder.bind(queue).to(directExchange).with("dmaster");
+        return BindingBuilder.bind(dmasterQueue()).to(directExchange).with("dmaster");
     }
 
     @Bean

+ 22 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/amqp/LogConsumer.java

@@ -0,0 +1,22 @@
+package cn.reghao.autodop.dmaster.utils.amqp;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessageListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * dmaster 消息分发
+ *
+ * @author reghao
+ * @date 2020-09-04 11:00:22
+ */
+@Slf4j
+@Component
+public class LogConsumer implements MessageListener {
+    @Override
+    public void onMessage(Message msg) {
+        String body = new String(msg.getBody());
+        log.info("dagent 日志...");
+    }
+}

+ 51 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/utils/amqp/LogConsumerConfig.java

@@ -0,0 +1,51 @@
+package cn.reghao.autodop.dmaster.utils.amqp;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * log 队列消费者
+ *
+ * @author reghao
+ * @date 2020-09-04 10:57:56
+ */
+@Configuration
+public class LogConsumerConfig {
+    private LogConsumer logConsumer;
+
+    public LogConsumerConfig(LogConsumer logConsumer) {
+        this.logConsumer = logConsumer;
+    }
+
+    @Bean
+    DirectExchange logDirectExchange(){
+        return new DirectExchange("rabbit.log", true, false);
+    }
+
+    @Bean
+    public Queue logQueue() {
+        String queueName = "log";
+        return new Queue(queueName, true);
+    }
+
+    @Bean
+    Binding bindingLogQueueToLogExchange(DirectExchange directExchange) {
+        String routeKey = "info";
+        return BindingBuilder.bind(logQueue()).to(directExchange).with(routeKey);
+    }
+
+    @Bean
+    public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory) {
+        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
+        container.setConnectionFactory(connectionFactory);
+        container.setMessageListener(logConsumer);
+        container.addQueues(logQueue());
+        return container;
+    }
+}

+ 7 - 18
dmaster/src/main/resources/logback-spring.xml

@@ -1,24 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <configuration>
-    <!-- 这个配置项需要用到这个ConsoleAppender处理 -->
     <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
-        <!-- layout就是一个展示的形式 -->
         <layout class="ch.qos.logback.classic.PatternLayout">
-            <!-- 具体格式 -->
             <pattern>
                 %d{HH:mm:ss.SSS} [%thread] %-5level %c %M %L - %msg%n
             </pattern>
         </layout>
     </appender>
 
-    <!-- 滚动的info文件输出 -->
+    <!-- info 日志文件 -->
     <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <filter class="ch.qos.logback.classic.filter.LevelFilter">
             <level>ERROR</level>
-            <!-- 如果匹配则禁止 -->
             <onMatch>DENY</onMatch>
-            <!-- 如果没有命中, 则使用 -->
             <onMismatch>ACCEPT</onMismatch>
         </filter>
         <encoder>
@@ -29,14 +24,13 @@
         </encoder>
         <!-- 滚动策略 -->
         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 路径 , 在日志的文件名里面加入时间-->
             <fileNamePattern>
                 logs/info.%d.log
             </fileNamePattern>
         </rollingPolicy>
     </appender>
 
-    <!-- 滚动的error文件输出 -->
+    <!-- error 日志文件 -->
     <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
             <level>ERROR</level>
@@ -47,35 +41,30 @@
             </pattern>
             <charset>UTF-8</charset>
         </encoder>
-        <!-- 滚动策略 -->
         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 路径 , 在日志的文件名里面加入时间-->
             <fileNamePattern>
                 logs/error.%d.log
             </fileNamePattern>
         </rollingPolicy>
     </appender>
 
-    <springProfile name="prod">
-        <!-- 日志开启级别 -->
+    <springProfile name="dev">
         <root level="info">
-            <appender-ref ref="fileInfoLog"></appender-ref>
-            <appender-ref ref="fileErrorLog"></appender-ref>
+            <appender-ref ref="consoleLog"></appender-ref>
         </root>
     </springProfile>
 
     <springProfile name="test">
-        <!-- 日志开启级别 -->
         <root level="info">
             <appender-ref ref="fileInfoLog"></appender-ref>
             <appender-ref ref="fileErrorLog"></appender-ref>
         </root>
     </springProfile>
 
-    <springProfile name="dev">
-        <!-- 日志开启级别 -->
+    <springProfile name="prod">
         <root level="info">
-            <appender-ref ref="consoleLog"></appender-ref>
+            <appender-ref ref="fileInfoLog"></appender-ref>
+            <appender-ref ref="fileErrorLog"></appender-ref>
         </root>
     </springProfile>
 </configuration>