[
https://issues.apache.org/jira/browse/LOG4J2-969?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14791833#comment-14791833
]
Paul D Johe commented on LOG4J2-969:
------------------------------------
[~micpalmia] : Here is the code we have used (also changes the INFO level to
syslog NOTICE level):
log4j2.xml config:
{code}
<appenders>
<Socket name="SYSLOG" host="localhost" port="514"
protocol="UDP">
<Rfc3164SyslogLayout charset="ISO-8859-1"
pattern="test[syslog]: [%X{logref}] %m"/>
</Socket>
</appenders>
{code}
Rfc3164SyslogLayout Plugin java code (a lot copied from the log4j2 SyslogLayout
because that class is 'final'):
{code}
package no.fiskeridir.logging.layouts;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.AbstractStringLayout;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.net.Facility;
import org.apache.logging.log4j.core.net.Priority;
import org.apache.logging.log4j.core.net.Severity;
import org.apache.logging.log4j.core.util.NetUtils;
/**
* Log4j2 plugin for RFC3164 otherwise known as the BSD syslog format.
*
* Note the log level to syslog severity mapping:
*
* <ul>
* <li>level FATAL - severity ALERT (red)</li>
* <li>level ERROR - severity ERROR (red)</li>
* <li>level WARN - severity WARN (yellow)</li>
* <li>level INFO - severity NOTICE (green)</li>
* <li>level DEBUG - severity INFO (white)</li>
* <li>level TRACE - severity DEBUG</li>
* </ul>
*
* @author pajoh
* @since 1.0.0
*
*/
@Plugin(name = "Rfc3164SyslogLayout", category = Node.CATEGORY, elementType =
Layout.ELEMENT_TYPE, printObject = true)
public class Rfc3164SyslogLayout extends AbstractStringLayout {
private static final long serialVersionUID = 1L;
/**
* Match newlines in a platform-independent manner.
*/
public static final Pattern NEWLINE_PATTERN = Pattern.compile("\\r?\\n");
private final Facility facility;
private final boolean includeNewLine;
private final String escapeNewLine;
private final PatternLayout patternLayout;
/**
* Date format used if header = true.
*/
private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd
HH:mm:ss", Locale.ENGLISH);
/**
* Host name used to identify messages from this appender.
*/
private final String localHostname = NetUtils.getLocalHostname();
protected Rfc3164SyslogLayout(final Facility facility, final boolean
includeNL, final String escapeNL, final Charset charset,
final String pattern ) {
super(charset);
this.facility = facility;
this.includeNewLine = includeNL;
this.escapeNewLine = escapeNL == null ? null :
Matcher.quoteReplacement(escapeNL);
this.patternLayout = (pattern == null) ? null :
PatternLayout.newBuilder().withPattern(pattern).withCharset(charset).build();
}
/**
* Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance
with the BSD Log record format.
*
* @param event The LogEvent
* @return the event formatted as a String.
*/
@Override
public String toSerializable(final LogEvent event) {
final StringBuilder buf = new StringBuilder();
buf.append('<');
buf.append(new Priority(facility,
getSeverity(event.getLevel())).getValue());
buf.append('>');
addDate(event.getTimeMillis(), buf);
buf.append(' ');
buf.append(localHostname);
buf.append(' ');
String message = (patternLayout == null) ?
event.getMessage().getFormattedMessage() :
patternLayout.toSerializable(event).toString();
if (null != escapeNewLine) {
message =
NEWLINE_PATTERN.matcher(message).replaceAll(escapeNewLine);
}
buf.append(message);
if (includeNewLine) {
buf.append('\n');
}
return buf.toString();
}
/**
* Override this to change the 'loglevel'-to-'syslog serverity' mapping
*
* @param level the level of the log event
* @return {@link Severity}
*/
protected Severity getSeverity(Level level) {
switch (level.getStandardLevel()) {
case ALL:
return Severity.DEBUG;
case TRACE:
return Severity.DEBUG;
case DEBUG:
return Severity.INFO;
case INFO:
return Severity.NOTICE;
case WARN:
return Severity.WARNING;
case ERROR:
return Severity.ERROR;
case FATAL:
return Severity.ALERT;
case OFF:
return Severity.EMERG;
}
return Severity.DEBUG;
}
private synchronized void addDate(final long timestamp, final
StringBuilder buf) {
final int index = buf.length() + 4;
buf.append(dateFormat.format(new Date(timestamp)));
// RFC 3164 says leading space, not leading zero on days 1-9
if (buf.charAt(index) == '0') {
buf.setCharAt(index, ' ');
}
}
/**
* Gets this SyslogLayout's content format. Specified by:
* <ul>
* <li>Key: "structured" Value: "false"</li>
* <li>Key: "dateFormat" Value: "MMM dd HH:mm:ss "</li>
* <li>Key: "format" Value: "<LEVEL>TIMESTAMP PROP(HOSTNAME)
MESSAGE"</li>
* <li>Key: "formatType" Value: "logfilepatternreceiver" (format uses the
keywords supported by
* LogFilePatternReceiver)</li>
* </ul>
*
* @return Map of content format keys supporting SyslogLayout
*/
@Override
public Map<String, String> getContentFormat() {
final Map<String, String> result = new HashMap<String, String>();
result.put("structured", "false");
result.put("formatType", "logfilepatternreceiver");
result.put("dateFormat", dateFormat.toPattern());
result.put("format", "<LEVEL>TIMESTAMP PROP(HOSTNAME) MESSAGE");
return result;
}
/**
* Create a SyslogLayout.
* @param facility The Facility is used to try to classify the message.
* @param includeNewLine If true a newline will be appended to the result.
* @param escapeNL Pattern to use for replacing newlines.
* @param charset The character set.
* @param pattern The pattern to use for the message part of the syslog
* @return A SyslogLayout.
*/
@PluginFactory
public static Rfc3164SyslogLayout createLayout(
@PluginAttribute(value = "facility", defaultString = "LOCAL0")
final Facility facility,
@PluginAttribute(value = "newLine", defaultBoolean = false) final
boolean includeNewLine,
@PluginAttribute("newLineEscape") final String escapeNL,
@PluginAttribute(value = "charset", defaultString = "ISO-8859-1")
final Charset charset,
@PluginAttribute(value = "pattern") String pattern ) {
return new Rfc3164SyslogLayout(facility, includeNewLine, escapeNL,
charset, pattern);
}
public static Rfc3164SyslogLayout createDefaultLayout() {
return new Rfc3164SyslogLayout(Facility.LOCAL0, false, null,
Charset.forName("ISO-8859-1"), null );
}
}
{code}
> Refactor SyslogAppender so that Layout is a Plugin element
> -----------------------------------------------------------
>
> Key: LOG4J2-969
> URL: https://issues.apache.org/jira/browse/LOG4J2-969
> Project: Log4j 2
> Issue Type: Improvement
> Components: Appenders, Layouts
> Affects Versions: 2.2
> Reporter: Paul D Johe
> Labels: syslog, syslogappender
>
> There are quite a lot of attributes to the syslogappender that could have
> been simply included as:
> {code}
> @PluginElement("layout") Layout<? extends Serializable> layout,
> {code}
> This is much more flexible (for example, extension of existing syslog
> layouts) and the field 'format' becomes superfluous, as it is implied by the
> layout chosen (normally SyslogLayout or Rfc5424Layout will be chosen).
> Furthermore, it becomes much clearer which attributes are for the RFC5424
> format and which are for the BSD format.
> Or at least add the possibility for a Layout element, which if does not exist
> will use the existing code.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]