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 */ 017 package org.apache.logging.log4j.core.layout; 018 019 import org.apache.logging.log4j.core.LogEvent; 020 import org.apache.logging.log4j.core.config.plugins.Plugin; 021 import org.apache.logging.log4j.core.config.plugins.PluginAttr; 022 import org.apache.logging.log4j.core.config.plugins.PluginFactory; 023 import org.apache.logging.log4j.core.net.Facility; 024 import org.apache.logging.log4j.core.net.Priority; 025 import org.apache.logging.log4j.util.EnglishEnums; 026 027 import java.net.InetAddress; 028 import java.net.UnknownHostException; 029 import java.nio.charset.Charset; 030 import java.text.SimpleDateFormat; 031 import java.util.Date; 032 import java.util.Locale; 033 034 035 /** 036 * Formats a log event as a BSD Log record. 037 */ 038 @Plugin(name = "SyslogLayout", type = "Core", elementType = "layout", printObject = true) 039 public class SyslogLayout extends AbstractStringLayout { 040 041 private final Facility facility; 042 private final boolean includeNewLine; 043 044 /** 045 * Date format used if header = true. 046 */ 047 private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd HH:mm:ss ", Locale.ENGLISH); 048 /** 049 * Host name used to identify messages from this appender. 050 */ 051 private final String localHostname = getLocalHostname(); 052 053 054 protected SyslogLayout(Facility facility, boolean includeNL, Charset c) { 055 super(c); 056 this.facility = facility; 057 this.includeNewLine = includeNL; 058 } 059 060 /** 061 * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the log4j.dtd. 062 * 063 * @param event The LogEvent 064 * @return the event formatted as a String. 065 */ 066 public String toSerializable(final LogEvent event) { 067 StringBuilder buf = new StringBuilder(); 068 069 buf.append("<"); 070 buf.append(Priority.getPriority(facility, event.getLevel())); 071 buf.append(">"); 072 addDate(event.getMillis(), buf); 073 buf.append(" "); 074 buf.append(localHostname); 075 buf.append(" "); 076 buf.append(event.getMessage().getFormattedMessage()); 077 if (includeNewLine) { 078 buf.append("\n"); 079 } 080 return buf.toString(); 081 } 082 083 /** 084 * This method gets the network name of the machine we are running on. 085 * Returns "UNKNOWN_LOCALHOST" in the unlikely case where the host name 086 * cannot be found. 087 * 088 * @return String the name of the local host 089 */ 090 private String getLocalHostname() { 091 try { 092 InetAddress addr = InetAddress.getLocalHost(); 093 return addr.getHostName(); 094 } catch (UnknownHostException uhe) { 095 LOGGER.error("Could not determine local host name", uhe); 096 return "UNKNOWN_LOCALHOST"; 097 } 098 } 099 100 private synchronized void addDate(final long timestamp, StringBuilder buf) { 101 int index = buf.length() + 4; 102 buf.append(dateFormat.format(new Date(timestamp))); 103 // RFC 3164 says leading space, not leading zero on days 1-9 104 if (buf.charAt(index) == '0') { 105 buf.setCharAt(index, ' '); 106 } 107 } 108 109 /** 110 * Create a SyslogLayout. 111 * @param facility The Facility is used to try to classify the message. 112 * @param includeNL If true a newline will be appended to the result. 113 * @param charset The character set. 114 * @return A SyslogLayout. 115 */ 116 @PluginFactory 117 public static SyslogLayout createLayout(@PluginAttr("facility") String facility, 118 @PluginAttr("newLine") String includeNL, 119 @PluginAttr("charset") String charset) { 120 121 Charset c = Charset.isSupported("UTF-8") ? Charset.forName("UTF-8") : Charset.defaultCharset(); 122 if (charset != null) { 123 if (Charset.isSupported(charset)) { 124 c = Charset.forName(charset); 125 } else { 126 LOGGER.error("Charset " + charset + " is not supported for layout, using " + c.displayName()); 127 } 128 } 129 boolean includeNewLine = includeNL == null ? false : Boolean.valueOf(includeNL); 130 Facility f = Facility.toFacility(facility, Facility.LOCAL0); 131 return new SyslogLayout(f, includeNewLine, c); 132 } 133 }