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
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.Layout;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.config.Configuration;
27 import org.apache.logging.log4j.core.config.plugins.Plugin;
28 import org.apache.logging.log4j.core.config.plugins.PluginAliases;
29 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
30 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
31 import org.apache.logging.log4j.core.config.plugins.PluginElement;
32 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
33 import org.apache.logging.log4j.core.layout.SerializedLayout;
34 import org.apache.logging.log4j.core.net.AbstractSocketManager;
35 import org.apache.logging.log4j.core.net.Advertiser;
36 import org.apache.logging.log4j.core.net.DatagramSocketManager;
37 import org.apache.logging.log4j.core.net.Protocol;
38 import org.apache.logging.log4j.core.net.SslSocketManager;
39 import org.apache.logging.log4j.core.net.TcpSocketManager;
40 import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
41 import org.apache.logging.log4j.core.util.Booleans;
42
43
44
45
46 @Plugin(name = "Socket", category = "Core", elementType = "appender", printObject = true)
47 public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketManager> {
48
49 private final Object advertisement;
50 private final Advertiser advertiser;
51
52 protected SocketAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
53 final AbstractSocketManager manager, final boolean ignoreExceptions, final boolean immediateFlush,
54 final Advertiser advertiser) {
55 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
56 if (advertiser != null) {
57 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
58 configuration.putAll(manager.getContentFormat());
59 configuration.put("contentType", layout.getContentType());
60 configuration.put("name", name);
61 this.advertisement = advertiser.advertise(configuration);
62 } else {
63 this.advertisement = null;
64 }
65 this.advertiser = advertiser;
66 }
67
68 @Override
69 public void stop() {
70 super.stop();
71 if (this.advertiser != null) {
72 this.advertiser.unadvertise(this.advertisement);
73 }
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 @PluginFactory
111 public static SocketAppender createAppender(
112
113 @PluginAttribute("host") final String host,
114 @PluginAttribute(value = "port", defaultInt = 0) final int port,
115 @PluginAttribute("protocol") final Protocol protocol,
116 @PluginElement("SSL") final SslConfiguration sslConfig,
117 @PluginAttribute(value = "connectTimeoutMillis", defaultInt = 0) final int connectTimeoutMillis,
118 @PluginAliases("reconnectionDelay")
119 @PluginAttribute(value = "reconnectionDelayMillis", defaultInt = 0) final int reconnectDelayMillis,
120 @PluginAttribute(value = "immediateFail", defaultBoolean = true) final boolean immediateFail,
121 @PluginAttribute("name") final String name,
122 @PluginAttribute(value = "immediateFlush", defaultBoolean = true) boolean immediateFlush,
123 @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions,
124 @PluginElement("Layout") Layout<? extends Serializable> layout,
125 @PluginElement("Filter") final Filter filter,
126 @PluginAttribute(value = "advertise", defaultBoolean = false) final boolean advertise,
127 @PluginConfiguration final Configuration config) {
128
129
130 if (layout == null) {
131 layout = SerializedLayout.createLayout();
132 }
133
134 if (name == null) {
135 LOGGER.error("No name provided for SocketAppender");
136 return null;
137 }
138
139 final Protocol actualProtocol = protocol != null ? protocol : Protocol.TCP;
140 if (actualProtocol == Protocol.UDP) {
141 immediateFlush = true;
142 }
143
144 final AbstractSocketManager manager = createSocketManager(name, actualProtocol, host, port, connectTimeoutMillis,
145 sslConfig, reconnectDelayMillis, immediateFail, layout);
146
147 return new SocketAppender(name, layout, filter, manager, ignoreExceptions, immediateFlush,
148 advertise ? config.getAdvertiser() : null);
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 @Deprecated
189 public static SocketAppender createAppender(
190
191 final String host,
192 final String portNum,
193 final String protocolIn,
194 final SslConfiguration sslConfig,
195 final int connectTimeoutMillis,
196
197 final String delayMillis,
198 final String immediateFail,
199 final String name,
200 final String immediateFlush,
201 final String ignore,
202 final Layout<? extends Serializable> layout,
203 final Filter filter,
204 final String advertise,
205 final Configuration config) {
206
207 final boolean isFlush = Booleans.parseBoolean(immediateFlush, true);
208 final boolean isAdvertise = Boolean.parseBoolean(advertise);
209 final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
210 final boolean fail = Booleans.parseBoolean(immediateFail, true);
211 final int reconnectDelayMillis = AbstractAppender.parseInt(delayMillis, 0);
212 final int port = AbstractAppender.parseInt(portNum, 0);
213 final Protocol p = protocolIn == null ? Protocol.UDP : Protocol.valueOf(protocolIn);
214 return createAppender(host, port, p, sslConfig, connectTimeoutMillis, reconnectDelayMillis, fail, name, isFlush,
215 ignoreExceptions, layout, filter, isAdvertise, config);
216 }
217
218
219
220
221
222
223
224 protected static AbstractSocketManager createSocketManager(final String name, Protocol protocol, final String host,
225 final int port, final int connectTimeoutMillis, final SslConfiguration sslConfig, final int delayMillis,
226 final boolean immediateFail, final Layout<? extends Serializable> layout) {
227 if (protocol == Protocol.TCP && sslConfig != null) {
228
229 protocol = Protocol.SSL;
230 }
231 if (protocol != Protocol.SSL && sslConfig != null) {
232 LOGGER.info("Appender {} ignoring SSL configuration for {} protocol", name, protocol);
233 }
234 switch (protocol) {
235 case TCP:
236 return TcpSocketManager.getSocketManager(host, port, connectTimeoutMillis, delayMillis, immediateFail,
237 layout);
238 case UDP:
239 return DatagramSocketManager.getSocketManager(host, port, layout);
240 case SSL:
241 return SslSocketManager.getSocketManager(sslConfig, host, port, connectTimeoutMillis, delayMillis,
242 immediateFail, layout);
243 default:
244 throw new IllegalArgumentException(protocol.toString());
245 }
246 }
247
248 @Override
249 protected void directEncodeEvent(final LogEvent event) {
250
251
252 writeByteArrayToManager(event);
253 }
254 }