flume源码分析--Log4j日志直接发送到Flume过程分析(三)

一、分析Log4j向flume发送日志的过程
按照前述调试过程,理清Log4j向flume发送日志所经过的过程,如下所示:
首先在初始化日志类时,就需要读取配置文件信息,并对其进行解读定位,关键是用到了org.apache.flume.clients.log4jappender.Log4jAppender类。在类初始化过程中,重点对该类进行调用,使得log4j在输出时可以通过netty,输出到相应的目标当中。

private static final Logger logger = LoggerFactory.getLogger(MyTest.class);

初始化过程中其调用关系为log4j->log4jAppender->RpcClientFactory ->NettyAvroRpcClient,如下图所示
flume源码分析--Log4j日志直接发送到Flume过程分析(三)_第1张图片
可以看出,log4j将日志直接输送到flume当中,同发送到文件、console等appender中一样,flume在其源码过程中,特意增加Log4jAppender类来解决相关的传送问题。

logger.info("Now the time is:{}",String.valueOf(new Date().getTime()));

log4j在输出的时候调用了log4jAppender通过netty将相关数据传递到flume中,有关log4j的如何调用Appender网上相关分析很多,大家可以自行搜索。
二、log4jAppender分析
有关log4j的Appender自定义开发可以参考这里,该文详细介绍了log4j的调用机理、结构关系及自定义Appender需要注意的事项,log4j能够直接输出日志到flume,核心就在于flume源码中提供了自定义的log4jAppender来解决这一问题。
1、继承log4j公共的基类:AppenderSkeleton

public class Log4jAppender extends AppenderSkeleton {
  private String hostname;
  private int port;
  ……

2、重写打印日志核心方法:abstract protected void append(LoggingEvent event);

  @Override
  public synchronized void append(LoggingEvent event) throws FlumeException{
    //If rpcClient is null, it means either this appender object was never
    //setup by setting hostname and port and then calling activateOptions
    //or this appender object was closed by calling close(), so we throw an
    //exception to show the appender is no longer accessible.
    if (rpcClient == null) {
      String errorMsg = "Cannot Append to Appender! Appender either closed or" +
        " not setup correctly!";
      LogLog.error(errorMsg);
      if (unsafeMode) {
        return;
      }
      throw new FlumeException(errorMsg);
    }
   ……

3、初始化加载资源:public void activateOptions(),

 @Override
  public void activateOptions() throws FlumeException {
    Properties props = new Properties();
    props.setProperty(RpcClientConfigurationConstants.CONFIG_HOSTS, "h1");
    props.setProperty(RpcClientConfigurationConstants.CONFIG_HOSTS_PREFIX + "h1",
      hostname + ":" + port);
    props.setProperty(RpcClientConfigurationConstants.CONFIG_CONNECT_TIMEOUT,
    ……

这里最关键的是在参数初始化过程中初始化了netty连接,这也是flume-NG一个比较大的改动,使用了JBOSS的netty来完成传输任务。

其他如释放资源:public void close();是否需要按格式输出文本:public boolean requiresLayout() 等等在类中都有体现,可以进一步进行仔细的分析。

你可能感兴趣的:(flume,OpenSOC)