All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.log4j.layout.Log4j1SyslogLayout Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */
package org.apache.log4j.layout;

import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.StringLayout;
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.PluginBuilderAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.layout.AbstractStringLayout;
import org.apache.logging.log4j.core.net.Facility;
import org.apache.logging.log4j.core.net.Priority;
import org.apache.logging.log4j.core.pattern.DatePatternConverter;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.util.NetUtils;
import org.apache.logging.log4j.util.Chars;

/**
 * Port of the layout used by SyslogAppender in Log4j 1.x. Provided for
 * compatibility with existing Log4j 1 configurations.
 *
 * Originally developed by Ceki Gülcü and Anders Kristensen.
 */
@Plugin(name = "Log4j1SyslogLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class Log4j1SyslogLayout  extends AbstractStringLayout {

    /**
     * Builds a SyslogLayout.
     * 

The main arguments are

*
    *
  • facility: The Facility is used to try to classify the message.
  • *
  • includeNewLine: If true a newline will be appended to the result.
  • *
  • escapeNL: Pattern to use for replacing newlines.
  • *
  • charset: The character set.
  • *
* @param the builder type */ public static class Builder> extends AbstractStringLayout.Builder implements org.apache.logging.log4j.core.util.Builder { public Builder() { setCharset(StandardCharsets.UTF_8); } @PluginBuilderAttribute private Facility facility = Facility.USER; @PluginBuilderAttribute private boolean facilityPrinting; @PluginBuilderAttribute private boolean header; @PluginElement("Layout") private Layout messageLayout; @Override public Log4j1SyslogLayout build() { if (!isValid()) { return null; } if (messageLayout != null && !(messageLayout instanceof StringLayout)) { LOGGER.error("Log4j1SyslogLayout: the message layout must be a StringLayout."); return null; } return new Log4j1SyslogLayout(facility, facilityPrinting, header, (StringLayout) messageLayout, getCharset()); } public Facility getFacility() { return facility; } public boolean isFacilityPrinting() { return facilityPrinting; } public boolean isHeader() { return header; } public Layout getMessageLayout() { return messageLayout; } public B setFacility(final Facility facility) { this.facility = facility; return asBuilder(); } public B setFacilityPrinting(final boolean facilityPrinting) { this.facilityPrinting = facilityPrinting; return asBuilder(); } public B setHeader(final boolean header) { this.header = header; return asBuilder(); } public B setMessageLayout(final Layout messageLayout) { this.messageLayout = messageLayout; return asBuilder(); } } @PluginBuilderFactory public static > B newBuilder() { return new Builder().asBuilder(); } /** * Host name used to identify messages from this appender. */ private static final String localHostname = NetUtils.getLocalHostname(); private final Facility facility; private final boolean facilityPrinting; private final boolean header; private final StringLayout messageLayout; /** * Date format used if header = true. */ private static final String[] dateFormatOptions = {"MMM dd HH:mm:ss", null, "en"}; private final LogEventPatternConverter dateConverter = DatePatternConverter.newInstance(dateFormatOptions); private Log4j1SyslogLayout(final Facility facility, final boolean facilityPrinting, final boolean header, final StringLayout messageLayout, final Charset charset) { super(charset); this.facility = facility; this.facilityPrinting = facilityPrinting; this.header = header; this.messageLayout = messageLayout; } /** * 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) { // The messageLayout also uses the thread-bound StringBuilder, // so we generate the message first final String message = messageLayout != null ? messageLayout.toSerializable(event) : event.getMessage().getFormattedMessage(); final StringBuilder buf = getStringBuilder(); buf.append('<'); buf.append(Priority.getPriority(facility, event.getLevel())); buf.append('>'); if (header) { final int index = buf.length() + 4; dateConverter.format(event, buf); // RFC 3164 says leading space, not leading zero on days 1-9 if (buf.charAt(index) == '0') { buf.setCharAt(index, Chars.SPACE); } buf.append(Chars.SPACE); buf.append(localHostname); buf.append(Chars.SPACE); } if (facilityPrinting) { buf.append(facility != null ? facility.name().toLowerCase() : "user").append(':'); } buf.append(message); // TODO: splitting message into 1024 byte chunks? return buf.toString(); } /** * Gets this SyslogLayout's content format. Specified by: *
    *
  • Key: "structured" Value: "false"
  • *
  • Key: "dateFormat" Value: "MMM dd HH:mm:ss"
  • *
  • Key: "format" Value: "<LEVEL>TIMESTAMP PROP(HOSTNAME) MESSAGE"
  • *
  • Key: "formatType" Value: "logfilepatternreceiver" (format uses the keywords supported by * LogFilePatternReceiver)
  • *
* * @return Map of content format keys supporting SyslogLayout */ @Override public Map getContentFormat() { final Map result = new HashMap<>(); result.put("structured", "false"); result.put("formatType", "logfilepatternreceiver"); result.put("dateFormat", dateFormatOptions[0]); if (header) { result.put("format", "TIMESTAMP PROP(HOSTNAME) MESSAGE"); } else { result.put("format", "MESSAGE"); } return result; } }