SpringBoot Log4j2发消息到Kafka以及动态添加KafkaAppender

本文介绍如何通过Log4j2配置将应用程序日志发送到Kafka,包括XML文件配置方法及Spring Boot项目的动态配置方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一:log4j2.xml文件配置

<Appenders>
<Kafkaname ="KAFKA"topic="log4j-kafka" syncSend="false">  
  <!-- <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />  -->
  <MarkerFiltermarker ="kafkaLog"onMatch ="ACCEPT"onMismatch= "DENY"/>  
  <PatternLayoutpattern ="%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n"/>  
  <Property name ="bootstrap.servers" >0.0.0.0:9092</ Property> 
  <Property name ="retries" >3</ Property> 
  <Property name ="linger.ms" >1000</ Property> 
  <Property name ="buffer.memory" > 10485760</ Property> 
</Kafka>
</Appenders>

<Loggers>
   <!-- additivity属性作用是在使用当前Logger配置的Appender打印日志 -->
   <Logger name ="com.hhaip" level="INFO" additivity ="false" >
       <AppenderRefref ="CONSOLE"/>
       <AppenderRefref ="INTERPHONE"/>
       <AppenderRefref ="KAFKA"/>
   </Logger>

   <!-- Root表示所有Logger用Root中的Appender打印日志  -->
   <Root level ="INFO" >
      <AppenderRefref ="CONSOLE"/>
      <AppenderRefref ="INTERPHONE"/>
      <AppenderRefref ="KAFKA"/>
   </Root>
</Loggers>

注意不要定义key.serializervalue.serializerbatch.size,log4j2里已经帮我们设置好了
解释:MarkerFilter是一种过滤器,marker过滤器的名称,使用时只有加上这种过滤器的日志才会输出到kafka,如下消息发送
     ThresholdFilter也是过滤器,用来指定过滤的级别,如:ERROR级别的才会发送至kafka
     PatternLayout是消息的格式
     syncSend指是否同步等待,设为false表示发送消息后立即返回,true则会等待kafka响应后返回(log4j2 2.8以上版本)

发送消息至kafka

在Java类中可以按如下方式发送消息至kafka:
log.info(Markers.KAFKA,"kafka消息{}", "log4j-" +content);

kafka收到的消息



Markers类的内容

import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

publicclass Markers {
    publicstatic final Marker DB = MarkerFactory.getMarker("dbLog");
    publicstatic final Marker KAFKA = MarkerFactory.getMarker("kafkaLog");
}


方法二:动态添加(SpringBoot项目)

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.DefaultConfiguration;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.filter.MarkerFilter;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.springframework.stereotype.Component;

@Component
publicclass KafkaLogAppender {

    @PostConstruct
    publicvoid init(){
       final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
       final Configuration config = ctx .getConfiguration();
       final Logger interLogger = ctx .getLogger("com.hhaip"); //需要写日志到数据库的包名
         
        List<Property>list = new ArrayList<>();
       list .add(Property.createProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG ,"0.0.0.0:9092" ));
       list .add(Property.createProperty(ProducerConfig.ACKS_CONFIG , "1"));
       list .add(Property.createProperty(ProducerConfig.RETRIES_CONFIG , "3"));
       list .add(Property.createProperty(ProducerConfig.LINGER_MS_CONFIG , "10000"));
       list .add(Property.createProperty(ProducerConfig.BUFFER_MEMORY_CONFIG ,"10485760"));
       list .add(Property.createProperty(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG ,"1000"));
        Property[]props = list .toArray(new Property[list .size()]);
         
       //配置Marker过滤器(标记过滤器和方法一的一样)
        MarkerFilterfilter = MarkerFilter.createFilter("kafkaLog", Filter.Result.ACCEPT , Filter.Result.DENY);
         
        Configurationconfiguration = new DefaultConfiguration();
        Layout<String>layout = PatternLayout.createLayout("%date %message",null , configuration , null , Charset.forName ("UTF-8" ),false , false , null,null);
         
        Appenderappender = KafkaAppender.createAppender(layout,filter, "KAFKA" ,true , "log4j-kafka" , props , configuration );
         
       config .addAppender(appender );
       interLogger .addAppender(appender );
       appender .start();
       ctx .updateLoggers();   
    }
}

方法二和方法一的使用是一样的,也许要定义一个Markers类.

注意:0.0.0.0换成你自己的IP地址

<think>我们正在配置log4j(第一代)来设置Kafka日志级别为INFO,并使用DailyRollingFileAppender(根据引用[1])来记录日志。但是用户要求使用kafkaAppender,而引用[1]中提到的配置实际上是DailyRollingFileAppender,并不是直接发送到Kafka的Appender。注意:引用[2][3][4]提到的是log4j2(第二代)的KafkaAppender,而用户问题中明确提到的是log4j(第一代)。因此,我们需要区分:用户问题:配置log4j(即log4j1.x)使用kafkaAppender,并将Kafka日志级别设置为INFO。然而,log4j1.x本身并没有内置的KafkaAppender。通常,我们需要自定义一个Appender或者使用第三方提供的Appender。但是,引用[4]提到“使用Log4j中的自定义Appender”,这里Log4j可能指的是log4j1.x。因此,我们可以这样回答:1.对于设置Kafka日志级别为INFO:我们可以通过配置log4j.properties文件,设置Kafka相关类的日志级别。2.对于使用kafkaAppender:由于log4j1.x没有内置的KafkaAppender,我们需要引入一个自定义的或者第三方的KafkaAppender。常见的是使用kafka-log4j-appender(由ApacheKafka提供)。步骤:1.添加依赖:在项目中添加kafka-log4j-appender的依赖(例如,如果使用Maven,则添加对应的依赖坐标)。2.配置log4j.properties:设置日志级别和Appender。具体配置示例:首先,确保有kafka-log4j-appender的jar包。然后,在log4j.properties中配置:#设置Kafka相关日志记录器的级别为INFOlog4j.logger.org.apache.kafka=INFO#定义KafkaAppenderlog4j.appender.kafkaAppender=org.apache.kafka.log4jappender.KafkaLog4jAppender#设置Kafkabroker列表log4j.appender.kafkaAppender.brokerList=localhost:9092#设置发送到Kafka的主题log4j.appender.kafkaAppender.topic=logs#设置布局(PatternLayout)log4j.appender.kafkaAppender.layout=org.apache.log4j.PatternLayoutlog4j.appender.kafkaAppender.layout.ConversionPattern=%d[%t]%-5p%c-%m%n#将Kafka相关日志记录器附加到kafkaAppender(可选,也可以将其他日志记录器附加到此Appender)log4j.logger.org.apache.kafka=INFO,kafkaAppender注意:上面的配置中,我们定义了一个名为kafkaAppender的Appender,并设置其类为org.apache.kafka.log4jappender.KafkaLog4jAppender。然后配置了broker列表和主题,并指定了日志格式。但是,请注意,我们可能还需要设置其他属性,比如压缩、超时等。具体可参考Kafka官方文档。另外,引用[1]中提到了一个DailyRollingFileAppender的配置,但用户要求的是kafkaAppender,所以我们不使用那个。如果用户使用的是log4j2,那么配置方式完全不同(如引用[2][3]所述),但用户明确要求log4j(第一代)。因此,我们按照log4j1.x的配置方式给出答案。注意:由于log4j1.x已经停止维护,建议升级到log4j2以获得更好的性能和内置的KafkaAppender支持(如引用[3]所述)。相关问题:1.如何在log4j2中配置KafkaAppender2.如何将log4j升级到log4j2?3.KafkaAppender在发送日志时如何保证可靠性?</think>### 配置log4jKafka日志级别和KafkaAppenderlog4j 1.x中配置Kafka日志级别为INFO并使用KafkaAppender,需完成以下步骤: #### 1. 添加Maven依赖 ```xml <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-log4j-appender</artifactId> <version>2.8.0</version> <!-- 匹配您的Kafka版本 --> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> ``` #### 2. 配置log4j.properties文件 ```properties # 设置Kafka日志级别为INFO log4j.logger.org.apache.kafka=INFO # 定义KafkaAppender log4j.appender.KAFKA=org.apache.kafka.log4jappender.KafkaLog4jAppender log4j.appender.KAFKA.BrokerList=localhost:9092 # Kafka broker地址 log4j.appender.KAFKA.Topic=app_logs # 目标Kafka主题 log4j.appender.KAFKA.CompressionType=gzip # 压缩类型(可选) log4j.appender.KAFKA.SyncSend=true # 同步发送(确保可靠性) # 配置日志格式 log4j.appender.KAFKA.layout=org.apache.log4j.PatternLayout log4j.appender.KAFKA.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n # 将Appender绑定到根日志记录器 log4j.rootLogger=INFO, KAFKA ``` #### 关键参数说明: - **BrokerList**:Kafka集群地址,多节点用逗号分隔(如 `kafka1:9092,kafka2:9092`) - **Topic**:日志写入的Kafka主题(需提前创建) - **CompressionType**:可选 `gzip`/`snappy`/`lz4`,降低网络开销 - **SyncSend**:设为 `true` 确保日志不丢失,但会降低性能 #### 3. 验证配置 在代码中获取Kafka日志记录器并输出测试消息: ```java import org.apache.log4j.Logger; public class LogTest { private static final Logger kafkaLogger = Logger.getLogger("org.apache.kafka"); public static void main(String[] args) { kafkaLogger.info("INFO级别测试消息 - 应发送到Kafka"); kafkaLogger.debug("DEBUG消息 - 不应发送"); } } ``` #### 注意事项: 1. **主题自动创建**:确保Kafka已启用`auto.create.topics.enable=true`,或手动创建目标主题 2. **性能影响**:同步发送(`SyncSend=true`)可能成为瓶颈,生产环境建议: - 使用异步模式(`SyncSend=false`) - 添加`AsyncAppender`缓冲日志 ```properties log4j.appender.ASYNC=org.apache.log4j.AsyncAppender log4j.appender.ASYNC.appenderRef=KAFKA log4j.rootLogger=INFO, ASYNC ``` 3. **日志截断**:超过Kafka `max.message.bytes`(默认1MB)的日志会被丢弃,需调整Kafka服务端配置 > **日志级别作用域**:`log4j.logger.org.apache.kafka=INFO` 表示所有Kafka相关类(producer/consumer/client)均使用INFO级别,DEBUG及更低级别日志将被过滤[^1]。 --- ### 相关问题 1. 如何解决KafkaAppender发送日志时的性能瓶颈问题? 2. Log4jLog4j2KafkaAppender配置有何主要区别? 3. 当日志发送到Kafka失败时,如何配置备用存储策略? 4. 在微服务架构中如何统一管理多个服务的Kafka日志输出? > 引用说明: > [^1]: Kafka日志配置支持包级粒度控制,`org.apache.kafka` 包下的所有类均受此日志级别约束。 > [^2]: 同步发送模式虽降低性能但可防止日志丢失,适用于审计类关键日志。 > [^3]: 超过Kafka消息大小限制的日志会被静默丢弃,需提前评估日志体积。 > [^4]: AsyncAppender通过内存队列实现异步发送,但崩溃时可能丢失缓冲中的日志。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值