将Log4j输出写入HDFS

有没有人试图log4j日志文件直接写入 Hadoop分布式文件系统

如果是,请回复如何实现这一目标。 我想我必须为它创建一个Appender。

这是这样的吗? 我的必要性是以特定的间隔将日志写入文件,并在稍后阶段查询该数据。

标准log4j(1.x)不支持写入HDFS。 但幸运的是,log4j很容易扩展。 我写了一个HDFS FileAppender来将日志写入MapRFS(与Hadoop兼容)。 文件名可以是“maprfs:///projects/example/root.log”。 它在我们的项目中运作良好。 我提取代码的appender部分并将其粘贴到下面。 代码段可能无法运行。 但这会让你知道如何写你的appender。 实际上,您只需要扩展org.apache.log4j.AppenderSkeleton,并实现append(),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; } }