序
本文主要研究一下rocketmq的FileAppender
WriterAppender
org/apache/rocketmq/logging/inner/LoggingBuilder.java
public static class WriterAppender extends Appender { protected boolean immediateFlush = true; protected String encoding; protected QuietWriter qw; public WriterAppender() {
} public void setImmediateFlush(boolean value) {
immediateFlush = value;
} public boolean getImmediateFlush() { return immediateFlush;
} public void activateOptions() {
} public void append(LoggingEvent event) { if (!checkEntryConditions()) { return;
}
subAppend(event);
} protected boolean checkEntryConditions() { if (this.closed) {
SysLogger.warn("Not allowed to write to a closed appender."); return false;
} if (this.qw == null) {
handleError("No output stream or file set for the appender named [" +
name + "]."); return false;
} if (this.layout == null) {
handleError("No layout set for the appender named [" + name + "]."); return false;
} return true;
} public synchronized void close() { if (this.closed) { return;
} this.closed = true;
writeFooter();
reset();
} protected void closeWriter() { if (qw != null) { try {
qw.close();
} catch (IOException e) {
handleError("Could not close " + qw, e, CODE_CLOSE_FAILURE);
}
}
} protected OutputStreamWriter createWriter(OutputStream os) {
OutputStreamWriter retval = null;
String enc = getEncoding(); if (enc != null) { try {
retval = new OutputStreamWriter(os, enc);
} catch (IOException e) {
SysLogger.warn("Error initializing output writer.");
SysLogger.warn("Unsupported encoding?");
}
} if (retval == null) {
retval = new OutputStreamWriter(os);
} return retval;
} public String getEncoding() { return encoding;
} public void setEncoding(String value) {
encoding = value;
} public synchronized void setWriter(Writer writer) {
reset(); this.qw = new QuietWriter(writer, this);
writeHeader();
} protected void subAppend(LoggingEvent event) { this.qw.write(this.layout.format(event)); if (layout.ignoresThrowable()) {
String[] s = event.getThrowableStr(); if (s != null) { for (String s1 : s) { this.qw.write(s1); this.qw.write(LINE_SEP);
}
}
} if (shouldFlush(event)) { this.qw.flush();
}
} protected void reset() {
closeWriter(); this.qw = null;
} protected void writeFooter() { if (layout != null) {
String f = layout.getFooter(); if (f != null && this.qw != null) { this.qw.write(f); this.qw.flush();
}
}
} protected void writeHeader() { if (layout != null) {
String h = layout.getHeader(); if (h != null && this.qw != null) { this.qw.write(h);
}
}
} protected boolean shouldFlush(final LoggingEvent event) { return event != null && immediateFlush;
}
}这个接口定义了writeHeader、writeFooter、append等方法
append方法这里参数是LoggingEvent,内部委托给subAppend
subAppend方法调用layout进行格式化event,然后如果需要flush,则会直接对qw进行flush
FileAppender
org/apache/rocketmq/logging/inner/LoggingBuilder.java
public static class FileAppender extends WriterAppender { protected boolean fileAppend = true; protected String fileName = null; protected boolean bufferedIO = false; protected int bufferSize = 8 * 1024; public FileAppender() {
} public FileAppender(Layout layout, String filename, boolean append)
throws IOException { this.layout = layout; this.setFile(filename, append, false, bufferSize);
} public void setFile(String file) {
fileName = file.trim();
} public boolean getAppend() { return fileAppend;
} public String getFile() { return fileName;
} public void activateOptions() { if (fileName != null) { try {
setFile(fileName, fileAppend, bufferedIO, bufferSize);
} catch (IOException e) {
handleError("setFile(" + fileName + "," + fileAppend + ") call failed.",
e, CODE_FILE_OPEN_FAILURE);
}
} else {
SysLogger.warn("File option not set for appender [" + name + "].");
SysLogger.warn("Are you using FileAppender instead of ConsoleAppender?");
}
} protected void closeFile() { if (this.qw != null) { try { this.qw.close();
} catch (IOException e) { if (e instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
SysLogger.error("Could not close " + qw, e);
}
}
} public boolean getBufferedIO() { return this.bufferedIO;
} public int getBufferSize() { return this.bufferSize;
} public void setAppend(boolean flag) {
fileAppend = flag;
} public void setBufferedIO(boolean bufferedIO) { this.bufferedIO = bufferedIO; if (bufferedIO) {
immediateFlush = false;
}
} public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize;
} public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
throws IOException {
SysLogger.debug("setFile called: " + fileName + ", " + append); if (bufferedIO) {
setImmediateFlush(false);
}
reset();
FileOutputStream ostream; try {
ostream = new FileOutputStream(fileName, append);
} catch (FileNotFoundException ex) {
String parentName = new File(fileName).getParent(); if (parentName != null) {
File parentDir = new File(parentName); if (!parentDir.exists() && parentDir.mkdirs()) {
ostream = new FileOutputStream(fileName, append);
} else { throw ex;
}
} else { throw ex;
}
}
Writer fw = createWriter(ostream); if (bufferedIO) {
fw = new BufferedWriter(fw, bufferSize);
} this.setQWForFiles(fw); this.fileName = fileName; this.fileAppend = append; this.bufferedIO = bufferedIO; this.bufferSize = bufferSize;
writeHeader();
SysLogger.debug("setFile ended");
} protected void setQWForFiles(Writer writer) { this.qw = new QuietWriter(writer, this);
} protected void reset() {
closeFile(); this.fileName = null; super.reset();
}
}写文件,这里定义了bufferSize为8 * 1024,如果开启bufferedIO,则创建的是BufferedWriter
setQWForFiles方法根据指定的writer创建了QuietWriter
setFile方法设置了qw之后,就直接writeHeader
QuietWriter
org/apache/rocketmq/logging/inner/LoggingBuilder.java
private static class QuietWriter extends FilterWriter {
protected Appender appender; public QuietWriter(Writer writer, Appender appender) {
super(writer); this.appender = appender;
} public void write(String string) { if (string != null) { try {
out.write(string);
} catch (Exception e) {
appender.handleError("Failed to write [" + string + "].", e,
Appender.CODE_WRITE_FAILURE);
}
}
} public void flush() { try {
out.flush();
} catch (Exception e) {
appender.handleError("Failed to flush writer,", e,
Appender.CODE_FLUSH_FAILURE);
}
}
}QuietWriter继承自jdk的FilterWriter,实现了write(String)方法,重写了flush方法
FilterWriter实现了write(int c),write(char cbuf[], int off, int len),write(String str, int off, int len)方法,用于对字符串进行过滤
作者:go4it
链接:https://www.jianshu.com/p/ab96bec4f8f6
随时随地看视频