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