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