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.HashMap;
21 import java.util.Map;
22 import java.util.concurrent.TimeUnit;
23
24 import org.apache.logging.log4j.core.Appender;
25 import org.apache.logging.log4j.core.Filter;
26 import org.apache.logging.log4j.core.Layout;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.config.Configuration;
29 import org.apache.logging.log4j.core.config.plugins.Plugin;
30 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
31 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
32 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
33 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
34 import org.apache.logging.log4j.core.config.plugins.PluginElement;
35 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
36 import org.apache.logging.log4j.core.layout.SerializedLayout;
37 import org.apache.logging.log4j.core.net.AbstractSocketManager;
38 import org.apache.logging.log4j.core.net.Advertiser;
39 import org.apache.logging.log4j.core.net.DatagramSocketManager;
40 import org.apache.logging.log4j.core.net.Protocol;
41 import org.apache.logging.log4j.core.net.SslSocketManager;
42 import org.apache.logging.log4j.core.net.TcpSocketManager;
43 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
44 import org.apache.logging.log4j.core.util.Booleans;
45 import org.apache.logging.log4j.core.util.Constants;
46
47
48
49
50 @Plugin(name = "Socket", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true)
51 public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketManager> {
52
53
54
55
56
57
58
59
60
61
62 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
63 implements org.apache.logging.log4j.core.util.Builder<SocketAppender> {
64
65 @PluginBuilderAttribute
66 private boolean advertise;
67
68 @PluginConfiguration
69 private Configuration configuration;
70
71 @PluginBuilderAttribute
72 private int connectTimeoutMillis;
73
74 @PluginBuilderAttribute
75 private String host = "localhost";
76
77 @PluginBuilderAttribute
78 private boolean immediateFail = true;
79
80 @PluginBuilderAttribute
81 private int port;
82
83 @PluginBuilderAttribute
84 private Protocol protocol = Protocol.TCP;
85
86 @PluginBuilderAttribute
87 @PluginAliases({ "reconnectDelay, delayMillis" })
88 private int reconnectDelayMillis;
89
90 @PluginElement("SslConfiguration")
91 @PluginAliases({ "SslConfig" })
92 private SslConfiguration sslConfiguration;
93
94 @SuppressWarnings("resource")
95 @Override
96 public SocketAppender build() {
97 boolean immediateFlush = isImmediateFlush();
98 final boolean bufferedIo = isBufferedIo();
99 Layout<? extends Serializable> layout = getLayout();
100 if (layout == null) {
101 layout = SerializedLayout.createLayout();
102 }
103
104 final String name = getName();
105 if (name == null) {
106 SocketAppender.LOGGER.error("No name provided for SocketAppender");
107 return null;
108 }
109
110 final Protocol actualProtocol = protocol != null ? protocol : Protocol.TCP;
111 if (actualProtocol == Protocol.UDP) {
112 immediateFlush = true;
113 }
114
115 final AbstractSocketManager manager = SocketAppender.createSocketManager(name, actualProtocol, host, port,
116 connectTimeoutMillis, sslConfiguration, reconnectDelayMillis, immediateFail, layout, getBufferSize());
117
118 return new SocketAppender(name, layout, getFilter(), manager, isIgnoreExceptions(),
119 !bufferedIo || immediateFlush, advertise ? configuration.getAdvertiser() : null);
120 }
121
122 public boolean getAdvertise() {
123 return advertise;
124 }
125
126 public int getConnectTimeoutMillis() {
127 return connectTimeoutMillis;
128 }
129
130 public String getHost() {
131 return host;
132 }
133
134 public int getPort() {
135 return port;
136 }
137
138 public Protocol getProtocol() {
139 return protocol;
140 }
141
142 public SslConfiguration getSslConfiguration() {
143 return sslConfiguration;
144 }
145
146 public boolean getImmediateFail() {
147 return immediateFail;
148 }
149
150 public B withAdvertise(final boolean advertise) {
151 this.advertise = advertise;
152 return asBuilder();
153 }
154
155 public B withConfiguration(final Configuration configuration) {
156 this.configuration = configuration;
157 return asBuilder();
158 }
159
160 public B withConnectTimeoutMillis(final int connectTimeoutMillis) {
161 this.connectTimeoutMillis = connectTimeoutMillis;
162 return asBuilder();
163 }
164
165 public B withHost(final String host) {
166 this.host = host;
167 return asBuilder();
168 }
169
170 public B withImmediateFail(final boolean immediateFail) {
171 this.immediateFail = immediateFail;
172 return asBuilder();
173 }
174
175 public B withPort(final int port) {
176 this.port = port;
177 return asBuilder();
178 }
179
180 public B withProtocol(final Protocol protocol) {
181 this.protocol = protocol;
182 return asBuilder();
183 }
184
185 public B withReconnectDelayMillis(final int reconnectDelayMillis) {
186 this.reconnectDelayMillis = reconnectDelayMillis;
187 return asBuilder();
188 }
189
190 public B withSslConfiguration(final SslConfiguration sslConfiguration) {
191 this.sslConfiguration = sslConfiguration;
192 return asBuilder();
193 }
194 }
195
196 @PluginBuilderFactory
197 public static <B extends Builder<B>> B newBuilder() {
198 return new Builder<B>().asBuilder();
199 }
200
201 private final Object advertisement;
202 private final Advertiser advertiser;
203
204 protected SocketAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
205 final AbstractSocketManager manager, final boolean ignoreExceptions, final boolean immediateFlush,
206 final Advertiser advertiser) {
207 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
208 if (advertiser != null) {
209 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
210 configuration.putAll(manager.getContentFormat());
211 configuration.put("contentType", layout.getContentType());
212 configuration.put("name", name);
213 this.advertisement = advertiser.advertise(configuration);
214 } else {
215 this.advertisement = null;
216 }
217 this.advertiser = advertiser;
218 }
219
220 @Override
221 public boolean stop(final long timeout, final TimeUnit timeUnit) {
222 setStopping();
223 super.stop(timeout, timeUnit, false);
224 if (this.advertiser != null) {
225 this.advertiser.unadvertise(this.advertisement);
226 }
227 setStopped();
228 return true;
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 @Deprecated
267 @PluginFactory
268 public static SocketAppender createAppender(
269
270 final String host,
271 final int port,
272 final Protocol protocol,
273 final SslConfiguration sslConfig,
274 final int connectTimeoutMillis,
275 final int reconnectDelayMillis,
276 final boolean immediateFail,
277 final String name,
278 boolean immediateFlush,
279 final boolean ignoreExceptions,
280 Layout<? extends Serializable> layout,
281 final Filter filter,
282 final boolean advertise,
283 final Configuration configuration) {
284
285
286 if (true) {
287
288 return newBuilder()
289 .withAdvertise(advertise)
290 .withConfiguration(configuration)
291 .withConnectTimeoutMillis(connectTimeoutMillis)
292 .withFilter(filter)
293 .withHost(host)
294 .withIgnoreExceptions(ignoreExceptions)
295 .withImmediateFail(immediateFail)
296 .withLayout(layout)
297 .withName(name)
298 .withPort(port)
299 .withProtocol(protocol)
300 .withReconnectDelayMillis(reconnectDelayMillis)
301 .withSslConfiguration(sslConfig)
302 .build();
303
304 }
305 if (layout == null) {
306 layout = SerializedLayout.createLayout();
307 }
308
309 if (name == null) {
310 LOGGER.error("No name provided for SocketAppender");
311 return null;
312 }
313
314 final Protocol actualProtocol = protocol != null ? protocol : Protocol.TCP;
315 if (actualProtocol == Protocol.UDP) {
316 immediateFlush = true;
317 }
318
319 final AbstractSocketManager manager = createSocketManager(name, actualProtocol, host, port,
320 connectTimeoutMillis, sslConfig, reconnectDelayMillis, immediateFail, layout, Constants.ENCODER_BYTE_BUFFER_SIZE);
321
322 return new SocketAppender(name, layout, filter, manager, ignoreExceptions, immediateFlush,
323 advertise ? configuration.getAdvertiser() : null);
324 }
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360 @Deprecated
361 public static SocketAppender createAppender(
362
363 final String host,
364 final String portNum,
365 final String protocolIn,
366 final SslConfiguration sslConfig,
367 final int connectTimeoutMillis,
368
369 final String delayMillis,
370 final String immediateFail,
371 final String name,
372 final String immediateFlush,
373 final String ignore,
374 final Layout<? extends Serializable> layout,
375 final Filter filter,
376 final String advertise,
377 final Configuration config) {
378
379 final boolean isFlush = Booleans.parseBoolean(immediateFlush, true);
380 final boolean isAdvertise = Boolean.parseBoolean(advertise);
381 final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
382 final boolean fail = Booleans.parseBoolean(immediateFail, true);
383 final int reconnectDelayMillis = AbstractAppender.parseInt(delayMillis, 0);
384 final int port = AbstractAppender.parseInt(portNum, 0);
385 final Protocol p = protocolIn == null ? Protocol.UDP : Protocol.valueOf(protocolIn);
386 return createAppender(host, port, p, sslConfig, connectTimeoutMillis, reconnectDelayMillis, fail, name, isFlush,
387 ignoreExceptions, layout, filter, isAdvertise, config);
388 }
389
390
391
392
393
394
395
396 protected static AbstractSocketManager createSocketManager(final String name, Protocol protocol, final String host,
397 final int port, final int connectTimeoutMillis, final SslConfiguration sslConfig, final int reconnectDelayMillis,
398 final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) {
399 if (protocol == Protocol.TCP && sslConfig != null) {
400
401 protocol = Protocol.SSL;
402 }
403 if (protocol != Protocol.SSL && sslConfig != null) {
404 LOGGER.info("Appender {} ignoring SSL configuration for {} protocol", name, protocol);
405 }
406 switch (protocol) {
407 case TCP:
408 return TcpSocketManager.getSocketManager(host, port, connectTimeoutMillis, reconnectDelayMillis, immediateFail,
409 layout, bufferSize);
410 case UDP:
411 return DatagramSocketManager.getSocketManager(host, port, layout, bufferSize);
412 case SSL:
413 return SslSocketManager.getSocketManager(sslConfig, host, port, connectTimeoutMillis, reconnectDelayMillis,
414 immediateFail, layout, bufferSize);
415 default:
416 throw new IllegalArgumentException(protocol.toString());
417 }
418 }
419
420 @Override
421 protected void directEncodeEvent(final LogEvent event) {
422
423
424 writeByteArrayToManager(event);
425 }
426 }