[LOG4J2-1709] Add a Builder to SyslogAppender and deprecate SyslogAppender.createAppender().
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/ed828be6 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/ed828be6 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/ed828be6 Branch: refs/heads/master Commit: ed828be67a23ee3513cafc9d2fd0ff16a26c7013 Parents: 2b595b6 Author: Gary Gregory <[email protected]> Authored: Mon Nov 14 15:11:47 2016 -0800 Committer: Gary Gregory <[email protected]> Committed: Mon Nov 14 15:11:47 2016 -0800 ---------------------------------------------------------------------- .../log4j/core/appender/SocketAppender.java | 101 +++-- .../log4j/core/appender/SyslogAppender.java | 408 +++++++++++++++---- src/changes/changes.xml | 3 + 3 files changed, 386 insertions(+), 126 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ed828be6/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java index 079ceee..8037475 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SocketAppender.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; +import org.apache.logging.log4j.core.AbstractLifeCycle; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Core; import org.apache.logging.log4j.core.Filter; @@ -54,14 +55,15 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM /** * Subclasses can extend this abstract Builder. * - * Removed deprecated "delayMillis", use "reconnectionDelayMillis". - * Removed deprecated "reconnectionDelay", use "reconnectionDelayMillis". + * <ul> + * <li>Removed deprecated "delayMillis", use "reconnectionDelayMillis".</li> + * <li>Removed deprecated "reconnectionDelay", use "reconnectionDelayMillis".</li> + * </ul> * * @param <B> - * This builder class. + * The type to build. */ - public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B> - implements org.apache.logging.log4j.core.util.Builder<SocketAppender> { + public static abstract class AbstractBuilder<B extends AbstractBuilder<B>> extends AbstractOutputStreamAppender.Builder<B> { @PluginBuilderAttribute private boolean advertise; @@ -85,7 +87,7 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM private Protocol protocol = Protocol.TCP; @PluginBuilderAttribute - @PluginAliases({ "reconnectDelay, delayMillis" }) + @PluginAliases({ "reconnectDelay, reconnectionDelay, delayMillis" }) private int reconnectDelayMillis; @PluginElement("SocketOptions") @@ -95,34 +97,6 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM @PluginAliases({ "SslConfig" }) private SslConfiguration sslConfiguration; - @SuppressWarnings("resource") - @Override - public SocketAppender build() { - boolean immediateFlush = isImmediateFlush(); - final boolean bufferedIo = isBufferedIo(); - Layout<? extends Serializable> layout = getLayout(); - if (layout == null) { - layout = SerializedLayout.createLayout(); - } - - final String name = getName(); - if (name == null) { - SocketAppender.LOGGER.error("No name provided for SocketAppender"); - return null; - } - - final Protocol actualProtocol = protocol != null ? protocol : Protocol.TCP; - if (actualProtocol == Protocol.UDP) { - immediateFlush = true; - } - - final AbstractSocketManager manager = SocketAppender.createSocketManager(name, actualProtocol, host, port, - connectTimeoutMillis, sslConfiguration, reconnectDelayMillis, immediateFail, layout, getBufferSize(), socketOptions); - - return new SocketAppender(name, layout, getFilter(), manager, isIgnoreExceptions(), - !bufferedIo || immediateFlush, advertise ? configuration.getAdvertiser() : null); - } - public boolean getAdvertise() { return advertise; } @@ -200,11 +174,64 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM this.sslConfiguration = sslConfiguration; return asBuilder(); } + + public int getReconnectDelayMillis() { + return reconnectDelayMillis; + } + + public SocketOptions getSocketOptions() { + return socketOptions; + } + + public Configuration getConfiguration() { + return configuration; + } + + } + + /** + * Builds a SocketAppender. + * <ul> + * <li>Removed deprecated "delayMillis", use "reconnectionDelayMillis".</li> + * <li>Removed deprecated "reconnectionDelay", use "reconnectionDelayMillis".</li> + * </ul> + */ + public static class Builder extends AbstractBuilder<Builder> + implements org.apache.logging.log4j.core.util.Builder<SocketAppender> { + + @SuppressWarnings("resource") + @Override + public SocketAppender build() { + boolean immediateFlush = isImmediateFlush(); + final boolean bufferedIo = isBufferedIo(); + Layout<? extends Serializable> layout = getLayout(); + if (layout == null) { + layout = SerializedLayout.createLayout(); + } + + final String name = getName(); + if (name == null) { + AbstractLifeCycle.LOGGER.error("No name provided for SocketAppender"); + return null; + } + + final Protocol protocol = getProtocol(); + final Protocol actualProtocol = protocol != null ? protocol : Protocol.TCP; + if (actualProtocol == Protocol.UDP) { + immediateFlush = true; + } + + final AbstractSocketManager manager = SocketAppender.createSocketManager(name, actualProtocol, getHost(), getPort(), + getConnectTimeoutMillis(), getSslConfiguration(), getReconnectDelayMillis(), getImmediateFail(), layout, getBufferSize(), getSocketOptions()); + + return new SocketAppender(name, layout, getFilter(), manager, isIgnoreExceptions(), + !bufferedIo || immediateFlush, getAdvertise() ? getConfiguration().getAdvertiser() : null); + } } @PluginBuilderFactory - public static <B extends Builder<B>> B newBuilder() { - return new Builder<B>().asBuilder(); + public static Builder newBuilder() { + return new Builder(); } private final Object advertisement; @@ -384,7 +411,7 @@ public class SocketAppender extends AbstractOutputStreamAppender<AbstractSocketM * @deprecated Use {@link #createSocketManager(String, Protocol, String, int, int, SslConfiguration, int, boolean, Layout, int, SocketOptions)}. */ @Deprecated - protected static AbstractSocketManager createSocketManager(final String name, Protocol protocol, final String host, + protected static AbstractSocketManager createSocketManager(final String name, final Protocol protocol, final String host, final int port, final int connectTimeoutMillis, final SslConfiguration sslConfig, final int reconnectDelayMillis, final boolean immediateFail, final Layout<? extends Serializable> layout, final int bufferSize) { return createSocketManager(name, protocol, host, port, connectTimeoutMillis, sslConfig, reconnectDelayMillis, immediateFail, layout, bufferSize, null); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ed828be6/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java index 6df591d..2fc73d8 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java @@ -18,20 +18,17 @@ package org.apache.logging.log4j.core.appender; import java.io.Serializable; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Core; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.Layout; -import org.apache.logging.log4j.core.appender.SocketAppender.Builder; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginAliases; -import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; -import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; +import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; import org.apache.logging.log4j.core.config.plugins.PluginElement; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.core.layout.LoggerFields; import org.apache.logging.log4j.core.layout.Rfc5424Layout; import org.apache.logging.log4j.core.layout.SyslogLayout; @@ -39,7 +36,6 @@ import org.apache.logging.log4j.core.net.AbstractSocketManager; import org.apache.logging.log4j.core.net.Advertiser; import org.apache.logging.log4j.core.net.Facility; import org.apache.logging.log4j.core.net.Protocol; -import org.apache.logging.log4j.core.net.SocketOptions; import org.apache.logging.log4j.core.net.ssl.SslConfiguration; import org.apache.logging.log4j.core.util.Constants; import org.apache.logging.log4j.util.EnglishEnums; @@ -50,37 +46,247 @@ import org.apache.logging.log4j.util.EnglishEnums; @Plugin(name = "Syslog", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) public class SyslogAppender extends SocketAppender { - public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B> - implements org.apache.logging.log4j.core.util.Builder<SyslogAppender> { - -// @PluginAliases("reconnectionDelay") // deprecated -// @PluginAttribute("name") final String name, -// @PluginAttribute(value = "immediateFlush", defaultBoolean = true) final boolean immediateFlush, -// @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions, -// @PluginAttribute(value = "facility", defaultString = "LOCAL0") final Facility facility, -// @PluginAttribute("id") final String id, -// @PluginAttribute(value = "enterpriseNumber", defaultInt = Rfc5424Layout.DEFAULT_ENTERPRISE_NUMBER) final int enterpriseNumber, -// @PluginAttribute(value = "includeMdc", defaultBoolean = true) final boolean includeMdc, -// @PluginAttribute("mdcId") final String mdcId, -// @PluginAttribute("mdcPrefix") final String mdcPrefix, -// @PluginAttribute("eventPrefix") final String eventPrefix, -// @PluginAttribute(value = "newLine") final boolean newLine, -// @PluginAttribute("newLineEscape") final String escapeNL, -// @PluginAttribute("appName") final String appName, -// @PluginAttribute("messageId") final String msgId, -// @PluginAttribute("mdcExcludes") final String excludes, -// @PluginAttribute("mdcIncludes") final String includes, -// @PluginAttribute("mdcRequired") final String required, -// @PluginAttribute("format") final String format, -// @PluginElement("Filter") final Filter filter, -// @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charsetName, -// @PluginAttribute("exceptionPattern") final String exceptionPattern, -// @PluginElement("LoggerFields") final LoggerFields[] loggerFields, + public static class Builder extends AbstractBuilder<Builder> + implements org.apache.logging.log4j.core.util.Builder<SocketAppender> { + + @PluginBuilderAttribute(value = "facility") + private Facility facility = Facility.LOCAL0; + + @PluginBuilderAttribute("id") + private String id; + + @PluginBuilderAttribute(value = "enterpriseNumber") + private int enterpriseNumber = Rfc5424Layout.DEFAULT_ENTERPRISE_NUMBER; + + @PluginBuilderAttribute(value = "includeMdc") + private boolean includeMdc = true; + + @PluginBuilderAttribute("mdcId") + private String mdcId; + + @PluginBuilderAttribute("mdcPrefix") + private String mdcPrefix; + + @PluginBuilderAttribute("eventPrefix") + private String eventPrefix; + + @PluginBuilderAttribute(value = "newLine") + private boolean newLine; + + @PluginBuilderAttribute("newLineEscape") + private String escapeNL; + + @PluginBuilderAttribute("appName") + private String appName; + + @PluginBuilderAttribute("messageId") + private String msgId; + + @PluginBuilderAttribute("mdcExcludes") + private String excludes; + + @PluginBuilderAttribute("mdcIncludes") + private String includes; + + @PluginBuilderAttribute("mdcRequired") + private String required; + + @PluginBuilderAttribute("format") + private String format; + + @PluginBuilderAttribute("charset") + private Charset charsetName = StandardCharsets.UTF_8; + + @PluginBuilderAttribute("exceptionPattern") + private String exceptionPattern; + + @PluginElement("LoggerFields") + private LoggerFields[] loggerFields; @Override - public SyslogAppender build() { - // TODO Auto-generated method stub - return null; + public SyslogAppender build() { + final Protocol protocol = getProtocol(); + final SslConfiguration sslConfiguration = getSslConfiguration(); + final boolean useTlsMessageFormat = sslConfiguration != null || protocol == Protocol.SSL; + final Configuration configuration = getConfiguration(); + final Layout<? extends Serializable> layout = RFC5424.equalsIgnoreCase(format) ? + Rfc5424Layout.createLayout(facility, id, enterpriseNumber, includeMdc, mdcId, mdcPrefix, eventPrefix, newLine, + escapeNL, appName, msgId, excludes, includes, required, exceptionPattern, useTlsMessageFormat, loggerFields, + configuration) : + SyslogLayout.createLayout(facility, newLine, escapeNL, charsetName); + + final String name = getName(); + if (name == null) { + LOGGER.error("No name provided for SyslogAppender"); + return null; + } + final AbstractSocketManager manager = createSocketManager(name, protocol, getHost(), getPort(), getConnectTimeoutMillis(), + sslConfiguration, getReconnectDelayMillis(), getImmediateFail(), layout, Constants.ENCODER_BYTE_BUFFER_SIZE, null); + + return new SyslogAppender(name, layout, getFilter(), isIgnoreExceptions(), isImmediateFlush(), manager, + getAdvertise() ? configuration.getAdvertiser() : null); + } + + public Facility getFacility() { + return facility; + } + + public String getId() { + return id; + } + + public int getEnterpriseNumber() { + return enterpriseNumber; + } + + public boolean isIncludeMdc() { + return includeMdc; + } + + public String getMdcId() { + return mdcId; + } + + public String getMdcPrefix() { + return mdcPrefix; + } + + public String getEventPrefix() { + return eventPrefix; + } + + public boolean isNewLine() { + return newLine; + } + + public String getEscapeNL() { + return escapeNL; + } + + public String getAppName() { + return appName; + } + + public String getMsgId() { + return msgId; + } + + public String getExcludes() { + return excludes; + } + + public String getIncludes() { + return includes; + } + + public String getRequired() { + return required; + } + + public String getFormat() { + return format; + } + + public Charset getCharsetName() { + return charsetName; + } + + public String getExceptionPattern() { + return exceptionPattern; + } + + public LoggerFields[] getLoggerFields() { + return loggerFields; + } + + public Builder setFacility(Facility facility) { + this.facility = facility; + return this; + } + + public Builder setId(String id) { + this.id = id; + return this; + } + + public Builder setEnterpriseNumber(int enterpriseNumber) { + this.enterpriseNumber = enterpriseNumber; + return this; + } + + public Builder setIncludeMdc(boolean includeMdc) { + this.includeMdc = includeMdc; + return this; + } + + public Builder setMdcId(String mdcId) { + this.mdcId = mdcId; + return this; + } + + public Builder setMdcPrefix(String mdcPrefix) { + this.mdcPrefix = mdcPrefix; + return this; + } + + public Builder setEventPrefix(String eventPrefix) { + this.eventPrefix = eventPrefix; + return this; + } + + public Builder setNewLine(boolean newLine) { + this.newLine = newLine; + return this; + } + + public Builder setEscapeNL(String escapeNL) { + this.escapeNL = escapeNL; + return this; + } + + public Builder setAppName(String appName) { + this.appName = appName; + return this; + } + + public Builder setMsgId(String msgId) { + this.msgId = msgId; + return this; + } + + public Builder setExcludes(String excludes) { + this.excludes = excludes; + return this; + } + + public Builder setIncludes(String includes) { + this.includes = includes; + return this; + } + + public Builder setRequired(String required) { + this.required = required; + return this; + } + + public Builder setFormat(String format) { + this.format = format; + return this; + } + + public Builder setCharsetName(Charset charset) { + this.charsetName = charset; + return this; + } + + public Builder setExceptionPattern(String exceptionPattern) { + this.exceptionPattern = exceptionPattern; + return this; + } + + public Builder setLoggerFields(LoggerFields[] loggerFields) { + this.loggerFields = loggerFields; + return this; } } @@ -98,9 +304,9 @@ public class SyslogAppender extends SocketAppender { * @param host The name of the host to connect to. * @param port The port to connect to on the target host. * @param protocolStr The Protocol to use. - * @param sslConfig TODO + * @param sslConfiguration TODO * @param connectTimeoutMillis the connect timeout in milliseconds. - * @param reconnectionDelayMillis The interval in which failed writes should be retried. + * @param reconnectDelayMillis The interval in which failed writes should be retried. * @param immediateFail True if the write should fail if no socket is immediately available. * @param name The name of the Appender. * @param immediateFlush "true" if data should be flushed on each write. @@ -124,66 +330,90 @@ public class SyslogAppender extends SocketAppender { * @param format If set to "RFC5424" the data will be formatted in accordance with RFC 5424. Otherwise, * it will be formatted as a BSD Syslog record. * @param filter A Filter to determine if the event should be handled by this Appender. - * @param config The Configuration. - * @param charsetName The character set to use when converting the syslog String to a byte array. + * @param configuration The Configuration. + * @param charset The character set to use when converting the syslog String to a byte array. * @param exceptionPattern The converter pattern to use for formatting exceptions. * @param loggerFields The logger fields * @param advertise Whether to advertise * @return A SyslogAppender. + * @deprecated Use {@link #newSyslogAppenderBuilder()}. */ - @PluginFactory + @Deprecated public static SyslogAppender createAppender( // @formatter:off - @PluginAttribute("host") final String host, - @PluginAttribute(value = "port", defaultInt = 0) final int port, - @PluginAttribute("protocol") final String protocolStr, - @PluginElement("SSL") final SslConfiguration sslConfig, - @PluginAttribute(value = "connectTimeoutMillis", defaultInt = 0) final int connectTimeoutMillis, - @PluginAliases("reconnectionDelay") // deprecated - @PluginAttribute(value = "reconnectionDelayMillis", defaultInt = 0) final int reconnectionDelayMillis, - @PluginAttribute(value = "immediateFail", defaultBoolean = true) final boolean immediateFail, - @PluginAttribute("name") final String name, - @PluginAttribute(value = "immediateFlush", defaultBoolean = true) final boolean immediateFlush, - @PluginAttribute(value = "ignoreExceptions", defaultBoolean = true) final boolean ignoreExceptions, - @PluginAttribute(value = "facility", defaultString = "LOCAL0") final Facility facility, - @PluginAttribute("id") final String id, - @PluginAttribute(value = "enterpriseNumber", defaultInt = Rfc5424Layout.DEFAULT_ENTERPRISE_NUMBER) final int enterpriseNumber, - @PluginAttribute(value = "includeMdc", defaultBoolean = true) final boolean includeMdc, - @PluginAttribute("mdcId") final String mdcId, - @PluginAttribute("mdcPrefix") final String mdcPrefix, - @PluginAttribute("eventPrefix") final String eventPrefix, - @PluginAttribute(value = "newLine") final boolean newLine, - @PluginAttribute("newLineEscape") final String escapeNL, - @PluginAttribute("appName") final String appName, - @PluginAttribute("messageId") final String msgId, - @PluginAttribute("mdcExcludes") final String excludes, - @PluginAttribute("mdcIncludes") final String includes, - @PluginAttribute("mdcRequired") final String required, - @PluginAttribute("format") final String format, - @PluginElement("Filter") final Filter filter, - @PluginConfiguration final Configuration config, - @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charsetName, - @PluginAttribute("exceptionPattern") final String exceptionPattern, - @PluginElement("LoggerFields") final LoggerFields[] loggerFields, - @PluginAttribute(value = "advertise") final boolean advertise) { + final String host, + final int port, + final String protocolStr, + final SslConfiguration sslConfiguration, + final int connectTimeoutMillis, + final int reconnectDelayMillis, + final boolean immediateFail, + final String name, + final boolean immediateFlush, + final boolean ignoreExceptions, + final Facility facility, + final String id, + final int enterpriseNumber, + final boolean includeMdc, + final String mdcId, + final String mdcPrefix, + final String eventPrefix, + final boolean newLine, + final String escapeNL, + final String appName, + final String msgId, + final String excludes, + final String includes, + final String required, + final String format, + final Filter filter, + final Configuration configuration, + final Charset charset, + final String exceptionPattern, + final LoggerFields[] loggerFields, + final boolean advertise) { // @formatter:on - final Protocol protocol = EnglishEnums.valueOf(Protocol.class, protocolStr); - final boolean useTlsMessageFormat = sslConfig != null || protocol == Protocol.SSL; - final Layout<? extends Serializable> layout = RFC5424.equalsIgnoreCase(format) ? - Rfc5424Layout.createLayout(facility, id, enterpriseNumber, includeMdc, mdcId, mdcPrefix, eventPrefix, newLine, - escapeNL, appName, msgId, excludes, includes, required, exceptionPattern, useTlsMessageFormat, loggerFields, - config) : - SyslogLayout.createLayout(facility, newLine, escapeNL, charsetName); - - if (name == null) { - LOGGER.error("No name provided for SyslogAppender"); - return null; - } - final AbstractSocketManager manager = createSocketManager(name, protocol, host, port, connectTimeoutMillis, - sslConfig, reconnectionDelayMillis, immediateFail, layout, Constants.ENCODER_BYTE_BUFFER_SIZE); - - return new SyslogAppender(name, layout, filter, ignoreExceptions, immediateFlush, manager, - advertise ? config.getAdvertiser() : null); + // @formatter:off + return newSyslogAppenderBuilder() + .withHost(host) + .withPort(port) + .withProtocol(EnglishEnums.valueOf(Protocol.class, protocolStr)) + .withSslConfiguration(sslConfiguration) + .withConnectTimeoutMillis(connectTimeoutMillis) + .withReconnectDelayMillis(reconnectDelayMillis) + .withImmediateFail(immediateFail) + .withName(appName) + .withImmediateFlush(immediateFlush) + .withIgnoreExceptions(ignoreExceptions) + .withFilter(filter) + .withConfiguration(configuration) + .withAdvertise(advertise) + .setFacility(facility) + .setId(id) + .setEnterpriseNumber(enterpriseNumber) + .setIncludeMdc(includeMdc) + .setMdcId(mdcId) + .setMdcPrefix(mdcPrefix) + .setEventPrefix(eventPrefix) + .setNewLine(newLine) + .setAppName(appName) + .setMsgId(msgId) + .setExcludes(excludes) + .setIncludeMdc(includeMdc) + .setRequired(required) + .setFormat(format) + .setCharsetName(charset) + .setExceptionPattern(exceptionPattern) + .setLoggerFields(loggerFields) + .build(); + // @formatter:on } + + // Calling this method newBuilder() does not compile + @PluginBuilderFactory + public static Builder newSyslogAppenderBuilder() { + return new Builder(); + } + } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ed828be6/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6002d02..10ee145 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -150,6 +150,9 @@ <action issue="LOG4J2-1704" dev="ggregory" type="add"> Add a Builder to RollingRandomAccessFileAppender and deprecate RollingRandomAccessFileAppender.createAppender(). </action> + <action issue="LOG4J2-1709" dev="ggregory" type="add"> + Add a Builder to SyslogAppender and deprecate SyslogAppender.createAppender(). + </action> <action issue="LOG4J2-1707" dev="ggregory" type="add"> Allow TCP Socket Appender to set socket options. </action>
