log4j2中的自定义Appender详解

时间:2025-03-22 22:23:26

log4j官网提供了很多Appender组件,但是当那些组键不满足日志收集的时候,我们需要自己定义Appender

定点Appender需要处理好两个地方的问题
1.需要在代码中写一个自定义Appender
2.修改文件中的Appenders下面引用的Appender为自定义appender

首先是代码实现主要是继承AbstractAppender这个抽象类,重写append()方法
append方法是我们进行接收日志的方法

  @Override
    public void append(LogEvent logEvent) {
        final byte[] bytes = getLayout().toByteArray(logEvent);
        String  log= new String(bytes);
        doLog(log,genericService);
    }

createAppender
这个方法可以用来接收的传参数,可以自行添加接收,和 中传参数对应上就行

 @PluginFactory
    public static LogAreaAppender createAppender(
            @PluginAttribute("name") String name, @PluginElement("Filter") final Filter filter,
            @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginAttribute("ignoreExceptions") boolean ignoreExceptions,
            @PluginAttribute("registryAddress") String registryAddress,
            @PluginAttribute("registryProtocol") String registryProtocol,
            @PluginAttribute("namespace") String namespace,
            @PluginAttribute("protocolName") String protocolName,
            @PluginAttribute("consumerGroup") String consumerGroup
    ) {
        if (name == null) {
            ("No name provided for MyCustomAppenderImpl");
            return null;
        }
        if (layout == null) {
            layout = ();
        }
        return new LogAreaAppender(name, filter, layout, ignoreExceptions,registryAddress,registryProtocol,namespace,protocolName,consumerGroup);
    }

LogAreaAppender 构造方法可以用来初始化我们要进行用的保存日志的方式

 public LogAreaAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions,
                           String registryAddress, String registryProtocol, String namespace, String protocolName, String consumerGroup) {
        super(name, filter, layout, ignoreExceptions);
        createDubbo(registryAddress,registryProtocol,namespace,protocolName,consumerGroup);
    }

上代码实现dubbo的日志接口

import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import .;
import .;
import .;
import .;

import .;
import .;
import .;
import .;
import .;

import ;
import ;

@Slf4j
@Plugin(name = "LogAreaAppender", category = "Core", elementType = "appender", printObject = true)
public class LogAreaAppender extends AbstractAppender {


    GenericService genericService =null;
    //dubbo日志方法
    private String logMethodName = "saveLog";

    public LogAreaAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions,
                           String registryAddress, String registryProtocol, String namespace, String protocolName, String consumerGroup) {
        super(name, filter, layout, ignoreExceptions);
        createDubbo(registryAddress,registryProtocol,namespace,protocolName,consumerGroup);
    }

    @Override
    public void append(LogEvent logEvent) {
        final byte[] bytes = getLayout().toByteArray(logEvent);
        String  log= new String(bytes);
        doLog(log,genericService);
    }

    // 下面这个方法可以接收配置文件中的参数信息
    @PluginFactory
    public static LogAreaAppender createAppender(
            @PluginAttribute("name") String name, @PluginElement("Filter") final Filter filter,
            @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginAttribute("ignoreExceptions") boolean ignoreExceptions,
            @PluginAttribute("registryAddress") String registryAddress,
            @PluginAttribute("registryProtocol") String registryProtocol,
            @PluginAttribute("namespace") String namespace,
            @PluginAttribute("protocolName") String protocolName,
            @PluginAttribute("consumerGroup") String consumerGroup
    ) {
        if (name == null) {
            ("No name provided for MyCustomAppenderImpl");
            return null;
        }
        if (layout == null) {
            layout = ();
        }
        return new LogAreaAppender(name, filter, layout, ignoreExceptions,registryAddress,registryProtocol,namespace,protocolName,consumerGroup);
    }

    private void createDubbo(String registryAddress ,String registryProtocolame,String namespace,String protocolName,String consumerGroup) {
        try {

            //设置应用名称
            ApplicationConfig applicationConfig = new ApplicationConfig();
            ("douc-rpc-dubbo");

            //连接注册中心
            RegistryConfig registryConfig = new RegistryConfig();
            (registryAddress);  //本地nacos
            (registryProtocolame);  //本地nacos

            HashMap<String, String> registryNacosMap = new HashMap<>();
            ("namespace",namespace);
            (registryNacosMap);

            // reference remote service
            ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
            (applicationConfig);
            (registryConfig);
            (protocolName);
            (consumerGroup);
            ("1.0.0");
            (3000);
            ("");
            (true);
            genericService = ();
            ("create client success");
        } catch (Exception e) {
            ("create file exception", e);
        }
    }

    /**
     * 执行dubbo接口
     * @param logInfo
     */
    public void doLog(String logInfo, GenericService genericService){
        ("dubbo----====-日志log---=====--入参:"+logInfo);
        genericService.$invoke(logMethodName, new String[]
                {""}, new Object[]{logInfo});
    }
}

配置介绍

registryAddress nacos地址和 namespace 命名空间ID

<Configuration status="info" packages=".log4j2plugin">  
修改一 Appenders里面的
<Appenders>
 
<!-- 这个就是自定义的Appender -->
<LogAreaAppender name="LogAreaAppender" registryProtocol="nacos" registryAddress="10.0.2.102:8848"
 namespace = "douc-102" protocolName = "" consumerGroup = "DOUC_RPC_DUBBO" >
 <JsonLayout properties="true"/>
</LogAreaAppender>
  
  
修改2 将这个地方的 http的删掉 添加  LogAreaAppender 引用
<AsyncLogger name="operatorLogger"  level="INFO">
<!--            <appender-ref ref="httpAppender" level="INFO" />-->
            <appender-ref ref="LogAreaAppender"  level="INFO"/>
        </AsyncLogger>

注: log4j2配置里面的的<LogAreaAppender name=“LogAreaAppender” 与java中的类对应上

需要的mavn依赖

<dependency>
<groupId>.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>