[ 
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: "&lt;LEVEL&gt;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]

Reply via email to