1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender;
18
19 import java.io.Serializable;
20 import java.util.concurrent.TimeUnit;
21
22 import org.apache.logging.log4j.core.Filter;
23 import org.apache.logging.log4j.core.Layout;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
26 import org.apache.logging.log4j.core.util.Constants;
27
28
29
30
31
32
33 public abstract class AbstractOutputStreamAppender<M extends OutputStreamManager> extends AbstractAppender {
34
35
36
37
38
39
40 public abstract static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B> {
41
42 @PluginBuilderAttribute
43 private boolean bufferedIo = true;
44
45 @PluginBuilderAttribute
46 private int bufferSize = Constants.ENCODER_BYTE_BUFFER_SIZE;
47
48 @PluginBuilderAttribute
49 private boolean immediateFlush = true;
50
51 public int getBufferSize() {
52 return bufferSize;
53 }
54
55 public boolean isBufferedIo() {
56 return bufferedIo;
57 }
58
59 public boolean isImmediateFlush() {
60 return immediateFlush;
61 }
62
63 public B withImmediateFlush(final boolean immediateFlush) {
64 this.immediateFlush = immediateFlush;
65 return asBuilder();
66 }
67
68 public B withBufferedIo(final boolean bufferedIo) {
69 this.bufferedIo = bufferedIo;
70 return asBuilder();
71 }
72
73 public B withBufferSize(final int bufferSize) {
74 this.bufferSize = bufferSize;
75 return asBuilder();
76 }
77
78 }
79
80
81
82
83
84
85
86 private final boolean immediateFlush;
87
88 private final M manager;
89
90
91
92
93
94
95
96
97
98 protected AbstractOutputStreamAppender(final String name, final Layout<? extends Serializable> layout,
99 final Filter filter, final boolean ignoreExceptions, final boolean immediateFlush, final M manager) {
100 super(name, filter, layout, ignoreExceptions);
101 this.manager = manager;
102 this.immediateFlush = immediateFlush;
103 }
104
105
106
107
108
109
110 public boolean getImmediateFlush() {
111 return immediateFlush;
112 }
113
114
115
116
117
118
119 public M getManager() {
120 return manager;
121 }
122
123 @Override
124 public void start() {
125 if (getLayout() == null) {
126 LOGGER.error("No layout set for the appender named [" + getName() + "].");
127 }
128 if (manager == null) {
129 LOGGER.error("No OutputStreamManager set for the appender named [" + getName() + "].");
130 }
131 super.start();
132 }
133
134 @Override
135 public boolean stop(final long timeout, final TimeUnit timeUnit) {
136 return stop(timeout, timeUnit, true);
137 }
138
139 @Override
140 protected boolean stop(final long timeout, final TimeUnit timeUnit, final boolean changeLifeCycleState) {
141 boolean stopped = super.stop(timeout, timeUnit, changeLifeCycleState);
142 stopped &= manager.stop(timeout, timeUnit);
143 if (changeLifeCycleState) {
144 setStopped();
145 }
146 LOGGER.debug("Appender {} stopped with status {}", getName(), stopped);
147 return stopped;
148 }
149
150
151
152
153
154
155
156
157
158 @Override
159 public void append(final LogEvent event) {
160 try {
161 tryAppend(event);
162 } catch (final AppenderLoggingException ex) {
163 error("Unable to write to stream " + manager.getName() + " for appender " + getName() + ": " + ex);
164 throw ex;
165 }
166 }
167
168 private void tryAppend(final LogEvent event) {
169 if (Constants.ENABLE_DIRECT_ENCODERS) {
170 directEncodeEvent(event);
171 } else {
172 writeByteArrayToManager(event);
173 }
174 }
175
176 protected void directEncodeEvent(final LogEvent event) {
177 getLayout().encode(event, manager);
178 if (this.immediateFlush || event.isEndOfBatch()) {
179 manager.flush();
180 }
181 }
182
183 protected void writeByteArrayToManager(final LogEvent event) {
184 final byte[] bytes = getLayout().toByteArray(event);
185 if (bytes != null && bytes.length > 0) {
186 manager.write(bytes, this.immediateFlush || event.isEndOfBatch());
187 }
188 }
189 }