有没有人尝试直接写入log4j的日志文件 ,以 Hadoop分布式文件系统 ?
如果是的话,请回复如何实现这一目标。 我想我将不得不为它创建一个追加程序。
这是方法? 我的必要性是写日志,以在特定的时间间隔一个文件,并在以后的阶段查询数据。
有没有人尝试直接写入log4j的日志文件 ,以 Hadoop分布式文件系统 ?
如果是的话,请回复如何实现这一目标。 我想我将不得不为它创建一个追加程序。
这是方法? 我的必要性是写日志,以在特定的时间间隔一个文件,并在以后的阶段查询数据。
我建议使用Apache的水槽完成这个任务。 有对Log4j的水槽的appender 。 这样,您将日志发送到水槽,并将其写入到HDFS。 有关此方法的好处是,水槽变得与HDFS通信的单点。 水槽可以方便地添加新的数据源,而一次又一次地与HDFS写一堆代码互动。
标准的log4j(1.x中)不支持写入HDFS。 但幸运的是,log4j很容易延伸。 我已经写了一个HDFS FileAppender写日志到MapRFS(用Hadoop兼容)。 该文件名可以是像“maprfs:///projects/example/root.log”。 它工作在我们的项目好。 我提取的代码添加器部分和下方粘贴。 代码段可能无法运行。 但是这会给你的想法如何,你的appender写。 其实,你只需要扩展org.apache.log4j.AppenderSkeleton,实施追加(),close()方法,requiresLayout()。 了解更多信息,您还可以下载log4j的1.2.17源代码,看看AppenderSkeleton是如何定义的,它有给你所有的信息。 祝好运!
注意:写入到HDFS的另一种方式是将HDFS安装到所有节点,所以你可以写日志,就像写入本地目录。 也许这是在实践中更好的办法。
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.Layout;
import org.apache.hadoop.conf.Configuration;
import java.io.*;
public class HDFSFileAppender {
private String filepath = null;
private Layout layout = null;
public HDFSFileAppender(String filePath, Layout layout){
this.filepath = filePath;
this.layout = layout;
}
@Override
protected void append(LoggingEvent event) {
String log = this.layout.format(event);
try {
InputStream logStream = new ByteArrayInputStream(log.getBytes());
writeToFile(filepath, logStream, false);
logStream.close();
}catch (IOException e){
System.err.println("Exception when append log to log file: " + e.getMessage());
}
}
@Override
public void close() {}
@Override
public boolean requiresLayout() {
return true;
}
//here write to HDFS
//filePathStr: the file path in MapR, like 'maprfs:///projects/aibot/1.log'
private boolean writeToFile(String filePathStr, InputStream inputStream, boolean overwrite) throws IOException {
boolean success = false;
int bytesRead = -1;
byte[] buffer = new byte[64 * 1024 * 1024];
try {
Configuration conf = new Configuration();
org.apache.hadoop.fs.FileSystem fs = org.apache.hadoop.fs.FileSystem.get(conf);
org.apache.hadoop.fs.Path filePath = new org.apache.hadoop.fs.Path(filePathStr);
org.apache.hadoop.fs.FSDataOutputStream fsDataOutputStream = null;
if(overwrite || !fs.exists(filePath)) {
fsDataOutputStream = fs.create(filePath, overwrite, 512, 3, 64*1024*1024);
}else{ //append to existing file.
fsDataOutputStream = fs.append(filePath, 512);
}
while ((bytesRead = inputStream.read(buffer)) != -1) {
fsDataOutputStream.write(buffer, 0, bytesRead);
}
fsDataOutputStream.close();
success = true;
} catch (IOException e) {
throw e;
}
return success;
}
}