001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.appender; 018 019import java.io.Serializable; 020import java.nio.charset.Charset; 021import java.nio.charset.StandardCharsets; 022 023import org.apache.logging.log4j.core.Appender; 024import org.apache.logging.log4j.core.Core; 025import org.apache.logging.log4j.core.Filter; 026import org.apache.logging.log4j.core.Layout; 027import org.apache.logging.log4j.core.config.Configuration; 028import org.apache.logging.log4j.core.config.Property; 029import org.apache.logging.log4j.core.config.plugins.Plugin; 030import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; 031import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; 032import org.apache.logging.log4j.core.config.plugins.PluginElement; 033import org.apache.logging.log4j.core.layout.LoggerFields; 034import org.apache.logging.log4j.core.layout.Rfc5424Layout; 035import org.apache.logging.log4j.core.layout.SyslogLayout; 036import org.apache.logging.log4j.core.net.AbstractSocketManager; 037import org.apache.logging.log4j.core.net.Advertiser; 038import org.apache.logging.log4j.core.net.Facility; 039import org.apache.logging.log4j.core.net.Protocol; 040import org.apache.logging.log4j.core.net.ssl.SslConfiguration; 041import org.apache.logging.log4j.core.util.Constants; 042import org.apache.logging.log4j.util.EnglishEnums; 043 044/** 045 * The Syslog Appender. 046 */ 047@Plugin(name = "Syslog", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) 048public class SyslogAppender extends SocketAppender { 049 050 public static class Builder<B extends Builder<B>> extends AbstractBuilder<B> 051 implements org.apache.logging.log4j.core.util.Builder<SocketAppender> { 052 053 @PluginBuilderAttribute(value = "facility") 054 private Facility facility = Facility.LOCAL0; 055 056 @PluginBuilderAttribute("id") 057 private String id; 058 059 @PluginBuilderAttribute(value = "enterpriseNumber") 060 private int enterpriseNumber = Rfc5424Layout.DEFAULT_ENTERPRISE_NUMBER; 061 062 @PluginBuilderAttribute(value = "includeMdc") 063 private boolean includeMdc = true; 064 065 @PluginBuilderAttribute("mdcId") 066 private String mdcId; 067 068 @PluginBuilderAttribute("mdcPrefix") 069 private String mdcPrefix; 070 071 @PluginBuilderAttribute("eventPrefix") 072 private String eventPrefix; 073 074 @PluginBuilderAttribute(value = "newLine") 075 private boolean newLine; 076 077 @PluginBuilderAttribute("newLineEscape") 078 private String escapeNL; 079 080 @PluginBuilderAttribute("appName") 081 private String appName; 082 083 @PluginBuilderAttribute("messageId") 084 private String msgId; 085 086 @PluginBuilderAttribute("mdcExcludes") 087 private String excludes; 088 089 @PluginBuilderAttribute("mdcIncludes") 090 private String includes; 091 092 @PluginBuilderAttribute("mdcRequired") 093 private String required; 094 095 @PluginBuilderAttribute("format") 096 private String format; 097 098 @PluginBuilderAttribute("charset") 099 private Charset charsetName = StandardCharsets.UTF_8; 100 101 @PluginBuilderAttribute("exceptionPattern") 102 private String exceptionPattern; 103 104 @PluginElement("LoggerFields") 105 private LoggerFields[] loggerFields; 106 107 @SuppressWarnings({"resource", "unchecked"}) 108 @Override 109 public SyslogAppender build() { 110 final Protocol protocol = getProtocol(); 111 final SslConfiguration sslConfiguration = getSslConfiguration(); 112 final boolean useTlsMessageFormat = sslConfiguration != null || protocol == Protocol.SSL; 113 final Configuration configuration = getConfiguration(); 114 Layout<? extends Serializable> layout = getLayout(); 115 if (layout == null) { 116 layout = RFC5424.equalsIgnoreCase(format) 117 ? Rfc5424Layout.createLayout(facility, id, enterpriseNumber, includeMdc, mdcId, mdcPrefix, 118 eventPrefix, newLine, escapeNL, appName, msgId, excludes, includes, required, 119 exceptionPattern, useTlsMessageFormat, loggerFields, configuration) 120 : 121 // @formatter:off 122 SyslogLayout.newBuilder() 123 .setFacility(facility) 124 .setIncludeNewLine(newLine) 125 .setEscapeNL(escapeNL) 126 .setCharset(charsetName) 127 .build(); 128 // @formatter:on 129 } 130 final String name = getName(); 131 if (name == null) { 132 LOGGER.error("No name provided for SyslogAppender"); 133 return null; 134 } 135 final AbstractSocketManager manager = createSocketManager(name, protocol, getHost(), getPort(), getConnectTimeoutMillis(), 136 sslConfiguration, getReconnectDelayMillis(), getImmediateFail(), layout, Constants.ENCODER_BYTE_BUFFER_SIZE, null); 137 138 return new SyslogAppender(name, layout, getFilter(), isIgnoreExceptions(), isImmediateFlush(), manager, 139 getAdvertise() ? configuration.getAdvertiser() : null, null); 140 } 141 142 public Facility getFacility() { 143 return facility; 144 } 145 146 public String getId() { 147 return id; 148 } 149 150 public int getEnterpriseNumber() { 151 return enterpriseNumber; 152 } 153 154 public boolean isIncludeMdc() { 155 return includeMdc; 156 } 157 158 public String getMdcId() { 159 return mdcId; 160 } 161 162 public String getMdcPrefix() { 163 return mdcPrefix; 164 } 165 166 public String getEventPrefix() { 167 return eventPrefix; 168 } 169 170 public boolean isNewLine() { 171 return newLine; 172 } 173 174 public String getEscapeNL() { 175 return escapeNL; 176 } 177 178 public String getAppName() { 179 return appName; 180 } 181 182 public String getMsgId() { 183 return msgId; 184 } 185 186 public String getExcludes() { 187 return excludes; 188 } 189 190 public String getIncludes() { 191 return includes; 192 } 193 194 public String getRequired() { 195 return required; 196 } 197 198 public String getFormat() { 199 return format; 200 } 201 202 public Charset getCharsetName() { 203 return charsetName; 204 } 205 206 public String getExceptionPattern() { 207 return exceptionPattern; 208 } 209 210 public LoggerFields[] getLoggerFields() { 211 return loggerFields; 212 } 213 214 public B setFacility(final Facility facility) { 215 this.facility = facility; 216 return asBuilder(); 217 } 218 219 public B setId(final String id) { 220 this.id = id; 221 return asBuilder(); 222 } 223 224 public B setEnterpriseNumber(final int enterpriseNumber) { 225 this.enterpriseNumber = enterpriseNumber; 226 return asBuilder(); 227 } 228 229 public B setIncludeMdc(final boolean includeMdc) { 230 this.includeMdc = includeMdc; 231 return asBuilder(); 232 } 233 234 public B setMdcId(final String mdcId) { 235 this.mdcId = mdcId; 236 return asBuilder(); 237 } 238 239 public B setMdcPrefix(final String mdcPrefix) { 240 this.mdcPrefix = mdcPrefix; 241 return asBuilder(); 242 } 243 244 public B setEventPrefix(final String eventPrefix) { 245 this.eventPrefix = eventPrefix; 246 return asBuilder(); 247 } 248 249 public B setNewLine(final boolean newLine) { 250 this.newLine = newLine; 251 return asBuilder(); 252 } 253 254 public B setEscapeNL(final String escapeNL) { 255 this.escapeNL = escapeNL; 256 return asBuilder(); 257 } 258 259 public B setAppName(final String appName) { 260 this.appName = appName; 261 return asBuilder(); 262 } 263 264 public B setMsgId(final String msgId) { 265 this.msgId = msgId; 266 return asBuilder(); 267 } 268 269 public B setExcludes(final String excludes) { 270 this.excludes = excludes; 271 return asBuilder(); 272 } 273 274 public B setIncludes(final String includes) { 275 this.includes = includes; 276 return asBuilder(); 277 } 278 279 public B setRequired(final String required) { 280 this.required = required; 281 return asBuilder(); 282 } 283 284 public B setFormat(final String format) { 285 this.format = format; 286 return asBuilder(); 287 } 288 289 public B setCharsetName(final Charset charset) { 290 this.charsetName = charset; 291 return asBuilder(); 292 } 293 294 public B setExceptionPattern(final String exceptionPattern) { 295 this.exceptionPattern = exceptionPattern; 296 return asBuilder(); 297 } 298 299 public B setLoggerFields(final LoggerFields[] loggerFields) { 300 this.loggerFields = loggerFields; 301 return asBuilder(); 302 } 303 } 304 305 protected static final String RFC5424 = "RFC5424"; 306 307 protected SyslogAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter, 308 final boolean ignoreExceptions, final boolean immediateFlush, 309 final AbstractSocketManager manager, final Advertiser advertiser, final Property[] properties) { 310 super(name, layout, filter, manager, ignoreExceptions, immediateFlush, advertiser, properties); 311 } 312 313 /** 314 * @deprecated Use 315 * {@link #SyslogAppender(String, Layout, Filter, boolean, boolean, AbstractSocketManager, Advertiser, Property[])}. 316 */ 317 @Deprecated 318 protected SyslogAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter, 319 final boolean ignoreExceptions, final boolean immediateFlush, final AbstractSocketManager manager, 320 final Advertiser advertiser) { 321 super(name, layout, filter, manager, ignoreExceptions, immediateFlush, advertiser, Property.EMPTY_ARRAY); 322 } 323 324 /** 325 * Creates a SyslogAppender. 326 * @param host The name of the host to connect to. 327 * @param port The port to connect to on the target host. 328 * @param protocolStr The Protocol to use. 329 * @param sslConfiguration TODO 330 * @param connectTimeoutMillis the connect timeout in milliseconds. 331 * @param reconnectDelayMillis The interval in which failed writes should be retried. 332 * @param immediateFail True if the write should fail if no socket is immediately available. 333 * @param name The name of the Appender. 334 * @param immediateFlush "true" if data should be flushed on each write. 335 * @param ignoreExceptions If {@code "true"} (default) exceptions encountered when appending events are logged; 336 * otherwise they are propagated to the caller. 337 * @param facility The Facility is used to try to classify the message. 338 * @param id The default structured data id to use when formatting according to RFC 5424. 339 * @param enterpriseNumber The IANA enterprise number. 340 * @param includeMdc Indicates whether data from the ThreadContextMap will be included in the RFC 5424 Syslog 341 * record. Defaults to "true:. 342 * @param mdcId The id to use for the MDC Structured Data Element. 343 * @param mdcPrefix The prefix to add to MDC key names. 344 * @param eventPrefix The prefix to add to event key names. 345 * @param newLine If true, a newline will be appended to the end of the syslog record. The default is false. 346 * @param escapeNL String that should be used to replace newlines within the message text. 347 * @param appName The value to use as the APP-NAME in the RFC 5424 syslog record. 348 * @param msgId The default value to be used in the MSGID field of RFC 5424 syslog records. 349 * @param excludes A comma separated list of mdc keys that should be excluded from the LogEvent. 350 * @param includes A comma separated list of mdc keys that should be included in the FlumeEvent. 351 * @param required A comma separated list of mdc keys that must be present in the MDC. 352 * @param format If set to "RFC5424" the data will be formatted in accordance with RFC 5424. Otherwise, 353 * it will be formatted as a BSD Syslog record. 354 * @param filter A Filter to determine if the event should be handled by this Appender. 355 * @param configuration The Configuration. 356 * @param charset The character set to use when converting the syslog String to a byte array. 357 * @param exceptionPattern The converter pattern to use for formatting exceptions. 358 * @param loggerFields The logger fields 359 * @param advertise Whether to advertise 360 * @return A SyslogAppender. 361 * @deprecated Use {@link #newSyslogAppenderBuilder()}. 362 */ 363 @Deprecated 364 public static <B extends Builder<B>> SyslogAppender createAppender( 365 // @formatter:off 366 final String host, 367 final int port, 368 final String protocolStr, 369 final SslConfiguration sslConfiguration, 370 final int connectTimeoutMillis, 371 final int reconnectDelayMillis, 372 final boolean immediateFail, 373 final String name, 374 final boolean immediateFlush, 375 final boolean ignoreExceptions, 376 final Facility facility, 377 final String id, 378 final int enterpriseNumber, 379 final boolean includeMdc, 380 final String mdcId, 381 final String mdcPrefix, 382 final String eventPrefix, 383 final boolean newLine, 384 final String escapeNL, 385 final String appName, 386 final String msgId, 387 final String excludes, 388 final String includes, 389 final String required, 390 final String format, 391 final Filter filter, 392 final Configuration configuration, 393 final Charset charset, 394 final String exceptionPattern, 395 final LoggerFields[] loggerFields, 396 final boolean advertise) { 397 // @formatter:on 398 399 // @formatter:off 400 return SyslogAppender.<B>newSyslogAppenderBuilder() 401 .withHost(host) 402 .withPort(port) 403 .withProtocol(EnglishEnums.valueOf(Protocol.class, protocolStr)) 404 .withSslConfiguration(sslConfiguration) 405 .withConnectTimeoutMillis(connectTimeoutMillis) 406 .withReconnectDelayMillis(reconnectDelayMillis) 407 .withImmediateFail(immediateFail).setName(appName) 408 .withImmediateFlush(immediateFlush).setIgnoreExceptions(ignoreExceptions).setFilter(filter) 409 .setConfiguration(configuration) 410 .withAdvertise(advertise) 411 .setFacility(facility) 412 .setId(id) 413 .setEnterpriseNumber(enterpriseNumber) 414 .setIncludeMdc(includeMdc) 415 .setMdcId(mdcId) 416 .setMdcPrefix(mdcPrefix) 417 .setEventPrefix(eventPrefix) 418 .setNewLine(newLine) 419 .setAppName(appName) 420 .setMsgId(msgId) 421 .setExcludes(excludes) 422 .setIncludeMdc(includeMdc) 423 .setRequired(required) 424 .setFormat(format) 425 .setCharsetName(charset) 426 .setExceptionPattern(exceptionPattern) 427 .setLoggerFields(loggerFields) 428 .build(); 429 // @formatter:on 430 } 431 432 // Calling this method newBuilder() does not compile 433 @PluginBuilderFactory 434 public static <B extends Builder<B>> B newSyslogAppenderBuilder() { 435 return new Builder<B>().asBuilder(); 436 } 437 438}