在使用flume采集日志写入hdfs的时候,可以通过
a1.sinks.k1.hdfs.path = /flume/events/%y-%m-%d/%H%M/%S
配置目录名称为日期,默认情况下会使用系统时间,但是在日志采集过程中经常会发生延迟情况,比如23:59的日志00:01才采集完,那这个时候本来是前一天的日志就会被写入第二天的目录里,后续ETL的过程中就会发生误差,这个时候我们会想,能不能使用日志里的时间字段来作为hdfs的文件目录呢?配置拦截器,在 headers 里添加 timestamp 可以实现这个功能。
首先创建一个maven项目,pom.xml添加依赖:
<dependency>
<groupId>org.apache.flume</groupId>
<artifactId>flume-ng-core</artifactId>
<version>1.7.0</version>
</dependency>
这里flume实际使用的是什么版本就写什么版本,我用的是1.7
然后创建 TimestampInterceptor.java
package com.flume;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class TimestampInterceptor implements Interceptor {
@Override
public void initialize() {
}
@Override
public Event intercept(Event event) {
String log=new String(event.getBody(), Charset.forName("UTF-8"));
Map<String, String> headers = event.getHeaders();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timestamp;
String[] split = log.split("\\|");
try {
// 这里假设日志格式为 2020-01-01 00:00:00|a|b|c|d
timestamp=String.valueOf(sdf.parse(split[0]).getTime());
headers.put("timestamp",timestamp);
return event;
} catch (ParseException e) {
return null;
}
}
@Override
public List<Event> intercept(List<Event> list) {
List<Event> list1=new ArrayList<>();
for (Event event : list) {
Event event1=intercept(event);
if(event1!=null) list1.add(event1);
}
return list1;
}
@Override
public void close() {
}
public static class Builder implements Interceptor.Builder{
@Override
public Interceptor build() {
return new TimestampInterceptor();
}
@Override
public void configure(Context context) {
}
}
}
将项目打成jar包,上传到flume的lib目录下
在flume的配置文件里添加拦截器
#interceptor
a1.sources.r2.interceptors = i1
a1.sources.r2.interceptors.i1.type = com.flume.TimestampInterceptor$Builder
这样就大功告成了!