You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by rg...@apache.org on 2011/05/30 08:02:08 UTC

svn commit: r1129003 - in /logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers: log4j2-api/src/main/java/org/apache/logging/log4j/message/ log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/ log4j2-core/src/main/java/org/apache/logging/lo...

Author: rgoers
Date: Mon May 30 06:02:07 2011
New Revision: 1129003

URL: http://svn.apache.org/viewvc?rev=1129003&view=rev
Log:
Add RFC 5424 Syslog and BSD Syslog layouts

Added:
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java
      - copied, changed from r1128132, logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Facility.java
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Priority.java
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Severity.java
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/RFC5424LayoutTest.java
      - copied, changed from r1128132, logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/XMLLayoutTest.java
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java
Modified:
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataId.java
    logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java

Modified: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataId.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataId.java?rev=1129003&r1=1129002&r2=1129003&view=diff
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataId.java (original)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataId.java Mon May 30 06:02:07 2011
@@ -74,6 +74,9 @@ public class StructuredDataId implements
         if (name == null) {
             throw new IllegalArgumentException("No structured id name was supplied");
         }
+        if (name.contains("@")) {
+            throw new IllegalArgumentException("Structured id name cannot contain an '@");
+        }
         if (enterpriseNumber <= 0) {
             throw new IllegalArgumentException("No enterprise number was supplied");
         }

Modified: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java?rev=1129003&r1=1129002&r2=1129003&view=diff
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java (original)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java Mon May 30 06:02:07 2011
@@ -21,6 +21,9 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.SortedMap;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
 
 /**
  * Represents a Message that conforms to RFC 5424 (http://tools.ietf.org/html/rfc5424).
@@ -30,7 +33,7 @@ public class StructuredDataMessage imple
 
     public static final String FULL = "full";
 
-    private Map data = new HashMap();
+    private Map<String, String> data = new HashMap<String, String>();
 
     private StructuredDataId id;
 
@@ -99,7 +102,7 @@ public class StructuredDataMessage imple
         this.message = msg;
     }
 
-    public Map getData() {
+    public Map<String, String> getData() {
         return Collections.unmodifiableMap(data);
     }
 
@@ -123,11 +126,11 @@ public class StructuredDataMessage imple
     }
 
     public String get(String key) {
-        return (String) data.get(key);
+        return data.get(key);
     }
 
     public String remove(String key) {
-        return (String) data.remove(key);
+        return data.remove(key);
     }
 
     /**
@@ -195,9 +198,8 @@ public class StructuredDataMessage imple
     }
 
     private void appendMap(Map map, StringBuffer sb) {
-        Iterator iter = map.entrySet().iterator();
-        while (iter.hasNext()) {
-            Map.Entry entry = (Map.Entry) iter.next();
+        SortedMap<String, Object> sorted = new TreeMap<String, Object>(map);
+        for (Map.Entry<String, Object> entry : sorted.entrySet()) {
             sb.append(" ");
             sb.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
         }

Added: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java?rev=1129003&view=auto
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java (added)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java Mon May 30 06:02:07 2011
@@ -0,0 +1,364 @@
+/*
+ * 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.logging.log4j.core.layout;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttr;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.net.Facility;
+import org.apache.logging.log4j.core.net.Priority;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.StructuredDataId;
+import org.apache.logging.log4j.message.StructuredDataMessage;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.charset.Charset;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+
+/**
+ *
+ */
+@Plugin(name="RFC5424Layout",type="Core",elementType="layout",printObject=true)
+public class RFC5424Layout extends LayoutBase {
+
+    private final Facility facility;
+    private final String defaultId;
+    private final Integer enterpriseNumber;
+    private final boolean includeMDC;
+    private final String mdcId;
+    private final Charset charset;
+    private final String localHostName;
+    private final String appName;
+    private final String messageId;
+    private final String configName;
+    private final List<String> mdcExcludes;
+    private final List<String> mdcIncludes;
+    private final ListChecker checker;
+    private final boolean includeNewLine;
+
+    private long lastTimestamp = -1;
+    private String timestamppStr = null;
+
+    private static final DecimalFormat TWO_DIGIT = new DecimalFormat("00");
+    private static final DecimalFormat FOUR_DIGIT = new DecimalFormat("0000");
+
+    // Not a very good default - it is the Apache Software Foundation's.
+    public static final int DEFAULT_ENTERPRISE_NUMBER = 18060;
+    public static final String DEFAULT_ID = "Audit";
+
+    public RFC5424Layout(Facility facility, String id, int ein, boolean includeMDC, boolean includeNL, String mdcId,
+                         String appName, String messageId, String excludes, String includes, Charset charset) {
+        this.facility = facility;
+        this.defaultId = id == null ? DEFAULT_ID : id;
+        this.enterpriseNumber = ein;
+        this.includeMDC = includeMDC;
+        this.includeNewLine = includeNL;
+        this.mdcId = mdcId;
+        this.appName = appName;
+        this.messageId = messageId;
+        this.charset = charset;
+        this.localHostName = getLocalHostname();
+        ListChecker c = null;
+        if (excludes != null) {
+            String[] array = excludes.split(",");
+            if (array.length > 0) {
+                c = new ExcludeChecker();
+                mdcExcludes = new ArrayList<String>(array.length);
+                for (String str : array) {
+                    mdcExcludes.add(str.trim());
+                }
+            } else {
+                mdcExcludes = null;
+            }
+        } else {
+            mdcExcludes = null;
+        }
+        if (includes != null) {
+            String[] array = includes.split(",");
+            if (array.length > 0) {
+                c = new IncludeChecker();
+                mdcIncludes = new ArrayList<String>(array.length);
+                for (String str : array) {
+                    mdcIncludes.add(str.trim());
+                }
+            } else {
+                mdcIncludes = null;
+            }
+        } else {
+            mdcIncludes = null;
+        }
+        this.checker = c != null ? c : new NoopChecker();
+        LoggerContext ctx = (LoggerContext) LogManager.getContext();
+        String name = ctx.getConfiguration().getName();
+        configName = (name != null && name.length() > 0) ? name : null;
+    }
+
+    /**
+     * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the RFC 5424 Syslog specification.
+     */
+    public byte[] format(final LogEvent event) {
+        Message msg = event.getMessage();
+        boolean isStructured = msg instanceof StructuredDataMessage;
+        StringBuilder buf = new StringBuilder();
+
+        buf.append("<");
+        buf.append(Priority.getPriority(facility, event.getLevel()));
+        buf.append(">1 ");
+        buf.append(computeTimeStampString(event.getMillis()));
+        buf.append(' ');
+        buf.append(localHostName);
+        buf.append(' ');
+        if (appName != null) {
+            buf.append(appName);
+        } else if (configName != null) {
+            buf.append(configName);
+        } else {
+            buf.append("-");
+        }
+        buf.append(" ");
+        buf.append(getProcId());
+        buf.append(" ");
+        String type = isStructured ? ((StructuredDataMessage) msg).getType() : null;
+        if (type != null) {
+            buf.append(type);
+        } else if (messageId != null) {
+            buf.append(messageId);
+        } else {
+            buf.append("-");
+        }
+        buf.append(" ");
+        if (isStructured) {
+            StructuredDataMessage data = (StructuredDataMessage) msg;
+            Map map = data.getData();
+            StructuredDataId id = data.getId();
+            formatStructuredElement(id, map, buf);
+            if (includeMDC)
+            {
+                int ein = id.getEnterpriseNumber() < 0 ? enterpriseNumber : id.getEnterpriseNumber();
+                StructuredDataId mdcSDID = new StructuredDataId(mdcId, ein, null, null);
+                formatStructuredElement(mdcSDID, event.getContextMap(), buf);
+            }
+            String text = data.getMessageFormat();
+            if (text != null && text.length() > 0) {
+                buf.append(" ").append(text);
+            }
+        } else {
+            buf.append("- ");
+            buf.append(event.getMessage().getFormattedMessage());
+        }
+        if (includeNewLine) {
+            buf.append("\n");
+        }
+        return buf.toString().getBytes(charset);
+    }
+
+    protected String getProcId() {
+        return "-";
+    }
+
+    /**
+     * This method gets the network name of the machine we are running on.
+     * Returns "UNKNOWN_LOCALHOST" in the unlikely case where the host name
+     * cannot be found.
+     *
+     * @return String the name of the local host
+     */
+    public String getLocalHostname() {
+        try {
+            InetAddress addr = InetAddress.getLocalHost();
+            return addr.getHostName();
+        } catch (UnknownHostException uhe) {
+            logger.error("Could not determine local host name", uhe);
+            return "UNKNOWN_LOCALHOST";
+        }
+    }
+
+    private String computeTimeStampString(long now) {
+        long last;
+        synchronized (this) {
+            last = lastTimestamp;
+            if (now == lastTimestamp) {
+                return timestamppStr;
+            }
+        }
+
+        StringBuilder buf = new StringBuilder();
+        Calendar cal = new GregorianCalendar();
+        cal.setTimeInMillis(now);
+        buf.append(Integer.toString(cal.get(Calendar.YEAR)));
+        buf.append("-");
+        pad(cal.get(Calendar.MONTH) + 1, 10, buf);
+        buf.append("-");
+        pad(cal.get(Calendar.DAY_OF_MONTH), 10, buf);
+        buf.append("T");
+        pad(cal.get(Calendar.HOUR_OF_DAY), 10, buf);
+        buf.append(":");
+        pad(cal.get(Calendar.MINUTE), 10, buf);
+        buf.append(":");
+        pad(cal.get(Calendar.SECOND), 10, buf);
+
+        int millis = cal.get(Calendar.MILLISECOND);
+        if (millis != 0) {
+            buf.append(".");
+            pad((int) ((float) millis / 10F), 100, buf);
+        }
+
+        int tzmin = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / 60000;
+        if (tzmin == 0) {
+            buf.append("Z");
+        } else {
+            if (tzmin < 0) {
+                tzmin = -tzmin;
+                buf.append("-");
+            } else {
+                buf.append("+");
+            }
+            int tzhour = tzmin / 60;
+            tzmin -= tzhour * 60;
+            pad(tzhour, 10, buf);
+            buf.append(":");
+            pad(tzmin, 10, buf);
+        }
+        synchronized (this) {
+            if (last == lastTimestamp) {
+                lastTimestamp = now;
+                timestamppStr = buf.toString();
+            }
+        }
+        return buf.toString();
+    }
+
+    private void pad(int val, int max, StringBuilder buf) {
+        while (max > 1) {
+            if (val < max) {
+                buf.append("0");
+            }
+            max = max / 10;
+        }
+        buf.append(Integer.toString(val));
+    }
+
+    private void formatStructuredElement(StructuredDataId id, Map<String, Object> data, StringBuilder sb)
+    {
+        if (id == null && defaultId == null)
+        {
+            return;
+        }
+        sb.append("[");
+        sb.append(getId(id));
+        appendMap(data, sb);
+        sb.append("]");
+    }
+
+    private String getId(StructuredDataId id) {
+        StringBuilder sb = new StringBuilder();
+        if (id.getName() == null) {
+            sb.append(defaultId);
+        } else {
+            sb.append(id.getName());
+        }
+        int ein = id.getEnterpriseNumber();
+        if (ein < 0) {
+            ein = enterpriseNumber;
+        }
+        if (ein >=0) {
+            sb.append("@").append(ein);
+        }
+        return sb.toString();
+    }
+
+    private void appendMap(Map<String, Object> map, StringBuilder sb)
+    {
+        SortedMap<String, Object> sorted = new TreeMap<String, Object>(map);
+        for (Map.Entry<String, Object> entry : sorted.entrySet())
+        {
+            if (checker.check(entry.getKey())) {
+                sb.append(" ");
+                sb.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
+            }
+        }
+    }
+
+    private interface ListChecker {
+        boolean check(String key);
+    }
+
+    private class IncludeChecker implements ListChecker {
+        public boolean check(String key) {
+            return mdcIncludes.contains(key);
+        }
+    }
+
+    private class ExcludeChecker implements ListChecker {
+        public boolean check(String key) {
+            return !mdcExcludes.contains(key);
+        }
+    }
+
+    public class NoopChecker implements ListChecker {
+        public boolean check(String key) {
+            return true;
+        }
+    }
+
+    @PluginFactory
+    public static RFC5424Layout createLayout(@PluginAttr("facility") String facility,
+                                             @PluginAttr("id") String id,
+                                             @PluginAttr("enterpriseNumber") String ein,
+                                             @PluginAttr("includeMDC") String includeMDC,
+                                             @PluginAttr("mdcId") String mdcId,
+                                             @PluginAttr("newLine") String includeNL,
+                                             @PluginAttr("appName") String appName,
+                                             @PluginAttr("messageId") String msgId,
+                                             @PluginAttr("mdcExcludes") String excludes,
+                                             @PluginAttr("mdcINcludes") String includes,
+                                             @PluginAttr("charset") String charset) {
+        Charset c = Charset.isSupported("UTF-8") ? Charset.forName("UTF-8") : Charset.defaultCharset();
+        if (charset != null) {
+            if (Charset.isSupported(charset)) {
+                c = Charset.forName(charset);
+            } else {
+                logger.error("Charset " + charset + " is not supported for layout, using " + c.displayName());
+            }
+        }
+        if (includes != null && excludes != null) {
+            logger.error("mdcIncludes and mdcExcludes are mutually exclusive. Includes wil be ignored");
+            includes = null;
+        }
+        Facility f = facility != null ? Facility.valueOf(facility.toUpperCase()) : Facility.LOCAL0;
+        int enterpriseNumber = ein == null ? DEFAULT_ENTERPRISE_NUMBER : Integer.parseInt(ein);
+        boolean isMdc = includeMDC == null ? true : Boolean.valueOf(includeMDC);
+        boolean includeNewLine = includeNL == null ? false : Boolean.valueOf(includeNL);
+
+        return new RFC5424Layout(f, id, enterpriseNumber, isMdc, includeNewLine, mdcId, appName, msgId, excludes,
+                                 includes, c);
+    }
+}

Copied: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java (from r1128132, logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java?p2=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java&p1=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java&r1=1128132&r2=1129003&rev=1129003&view=diff
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java (original)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java Mon May 30 06:02:07 2011
@@ -20,48 +20,106 @@ import org.apache.logging.log4j.core.Log
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
-import org.apache.logging.log4j.core.helpers.Transform;
+import org.apache.logging.log4j.core.net.Facility;
+import org.apache.logging.log4j.core.net.Priority;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.io.LineNumberReader;
-import java.io.ObjectOutputStream;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
 
 
 /**
  *
  */
-@Plugin(name="SerializedLayout",type="Core",elementType="layout",printObject=true)
-public class SerializedLayout extends LayoutBase {
+@Plugin(name="SyslogLayout",type="Core",elementType="layout",printObject=true)
+public class SyslogLayout extends LayoutBase {
 
-    public SerializedLayout() {
+    private final Charset charset;
+    private final Facility facility;
+    private final boolean includeNewLine;
+
+    /**
+     * 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 = getLocalHostname();
+
+
+    public SyslogLayout(Facility facility, boolean includeNL, Charset c) {
+        this.facility = facility;
+        this.header = header;
+        this.includeNewLine = includeNL;
+        this.charset = c;
     }
 
     /**
      * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the log4j.dtd.
      */
     public byte[] format(final LogEvent event) {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        StringBuilder buf = new StringBuilder();
+
+        buf.append("<");
+        buf.append(Priority.getPriority(facility, event.getLevel()));
+        buf.append(">");
+        addDate(event.getMillis(), buf);
+        buf.append(" ");
+        buf.append(localHostname);
+        buf.append(" ");
+        buf.append(event.getMessage().getFormattedMessage());
+        if (includeNewLine) {
+            buf.append("\n");
+        }
+        return buf.toString().getBytes(charset);
+    }
+
+    /**
+     * This method gets the network name of the machine we are running on.
+     * Returns "UNKNOWN_LOCALHOST" in the unlikely case where the host name
+     * cannot be found.
+     *
+     * @return String the name of the local host
+     */
+    private String getLocalHostname() {
         try {
-            ObjectOutputStream oos = new ObjectOutputStream(baos);
-            oos.writeObject(event);
-        } catch (IOException ioe) {
-            logger.error("Serialization of Logging Event failed.", ioe);
+            InetAddress addr = InetAddress.getLocalHost();
+            return addr.getHostName();
+        } catch (UnknownHostException uhe) {
+            logger.error("Could not determine local host name", uhe);
+            return "UNKNOWN_LOCALHOST";
+        }
+    }
+
+    private synchronized void addDate(final long timestamp, StringBuilder buf) {
+        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, ' ');
         }
-        return baos.toByteArray();
     }
 
-    @PluginFactory
-    public static SerializedLayout createLayout() {
 
-        return new SerializedLayout();
+    @PluginFactory
+    public static SyslogLayout createLayout(@PluginAttr("facility") String facility,
+                                            @PluginAttr("newLine") String includeNL,
+                                            @PluginAttr("charset") String charset) {
+
+        Charset c = Charset.isSupported("UTF-8") ? Charset.forName("UTF-8") : Charset.defaultCharset();
+        if (charset != null) {
+            if (Charset.isSupported(charset)) {
+                c = Charset.forName(charset);
+            } else {
+                logger.error("Charset " + charset + " is not supported for layout, using " + c.displayName());
+            }
+        }
+        boolean includeNewLine = includeNL == null ? false : Boolean.valueOf(includeNL);
+        Facility f = facility != null ? Facility.valueOf(facility.toUpperCase()) : Facility.LOCAL0;
+        return new SyslogLayout(f, includeNewLine, c);
     }
 }

Added: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Facility.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Facility.java?rev=1129003&view=auto
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Facility.java (added)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Facility.java Mon May 30 06:02:07 2011
@@ -0,0 +1,74 @@
+package org.apache.logging.log4j.core.net;
+
+/**
+ *  The facility codes used by the Syslog system.
+ *
+ *        Numerical          Facility<br>
+ *           Code<br>
+ *
+ *             0             kernel messages<br>
+ *             1             user-level messages<br>
+ *             2             mail system<br>
+ *             3             system daemons<br>
+ *             4             security/authorization messages<br>
+ *             5             messages generated internally by syslogd<br>
+ *             6             line printer subsystem<br>
+ *             7             network news subsystem<br>
+ *             8             UUCP subsystem<br>
+ *             9             clock daemon<br>
+ *            10             security/authorization messages<br>
+ *            11             FTP daemon<br>
+ *            12             NTP subsystem<br>
+ *            13             log audit<br>
+ *            14             log alert<br>
+ *            15             clock daemon (note 2)<br>
+ *            16             local use 0  (local0)<br>
+ *            17             local use 1  (local1)<br>
+ *            18             local use 2  (local2)<br>
+ *            19             local use 3  (local3)<br>
+ *            20             local use 4  (local4)<br>
+ *            21             local use 5  (local5)<br>
+ *            22             local use 6  (local6)<br>
+ *            23             local use 7  (local7)<br>
+ */
+public enum Facility {
+    KERN(0),
+    USER(1),
+    MAIL(2),
+    DAEMON(3),
+    AUTH(4),
+    SYSLOG(5),
+    LPR(6),
+    NEWS(7),
+    UUCP(8),
+    CRON(9),
+    AUTHPRIV(10),
+    FTP(11),
+    NTP(12),
+    LOG_AUDIT(13),
+    LOG_ALERT(14),
+    CLOCK(15),
+    LOCAL0(16),
+    LOCAL1(17),
+    LOCAL2(18),
+    LOCAL3(19),
+    LOCAL4(20),
+    LOCAL5(21),
+    LOCAL6(22),
+    LOCAL7(23);
+
+    private final int code;
+
+    private Facility(int code) {
+        this.code = code;
+    }
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public boolean equals(String name) {
+        return this.name().equalsIgnoreCase(name);
+    }
+
+}

Added: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Priority.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Priority.java?rev=1129003&view=auto
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Priority.java (added)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Priority.java Mon May 30 06:02:07 2011
@@ -0,0 +1,53 @@
+/*
+ * 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.logging.log4j.core.net;
+
+import org.apache.logging.log4j.Level;
+
+/**
+ * The Priority used in the Syslog system. Calculated from the Facility and Severity values.
+ */
+public class Priority {
+
+    private final Facility facility;
+    private final Severity severity;
+
+    public Priority(Facility facility, Severity severity) {
+        this.facility = facility;
+        this.severity = severity;
+    }
+
+    public static int getPriority(Facility facility, Level level) {
+        return facility.getCode() << 3 + Severity.getSeverity(level).getCode();
+    }
+
+    public Facility getFacility() {
+        return facility;
+    }
+
+    public Severity getSeverity() {
+        return severity;
+    }
+
+    public int getValue() {
+        return facility.getCode() << 3 + severity.getCode();
+    }
+
+    public String toString() {
+        return Integer.toString(getValue());
+    }
+}

Added: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Severity.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Severity.java?rev=1129003&view=auto
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Severity.java (added)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/net/Severity.java Mon May 30 06:02:07 2011
@@ -0,0 +1,65 @@
+package org.apache.logging.log4j.core.net;
+
+import org.apache.logging.log4j.Level;
+
+/**
+ *  Severity values used by the Syslog system
+ *
+ *        Numerical   Severity<br>
+ *          Code<br>
+ *
+ *            0       Emergency: system is unusable<br>
+ *            1       Alert: action must be taken immediately<br>
+ *            2       Critical: critical conditions<br>
+ *            3       Error: error conditions<br>
+ *            4       Warning: warning conditions<br>
+ *            5       Notice: normal but significant condition<br>
+ *            6       Informational: informational messages<br>
+ *            7       Debug: debug-level messages
+ */
+public enum Severity {
+    EMERG(0),
+    ALERT(1),
+    CRITICAL(2),
+    ERROR(3),
+    WARNING(4),
+    NOTICE(5),
+    INFO(6),
+    DEBUG(7);
+
+    private final int code;
+
+    private Severity(int code) {
+        this.code = code;
+    }
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public boolean equals(String name) {
+        return this.name().equalsIgnoreCase(name);
+    }
+
+    public static Severity getSeverity(Level level) {
+        switch (level) {
+            case ALL:
+                return DEBUG;
+            case TRACE:
+                return DEBUG;
+            case DEBUG:
+                return DEBUG;
+            case INFO:
+                return INFO;
+            case WARN:
+                return WARNING;
+            case ERROR:
+                return ERROR;
+            case FATAL:
+                return ALERT;
+            case OFF:
+                return EMERG;
+        }
+        return DEBUG;
+    }
+}

Copied: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/RFC5424LayoutTest.java (from r1128132, logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/XMLLayoutTest.java)
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/RFC5424LayoutTest.java?p2=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/RFC5424LayoutTest.java&p1=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/XMLLayoutTest.java&r1=1128132&r2=1129003&rev=1129003&view=diff
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/XMLLayoutTest.java (original)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/RFC5424LayoutTest.java Mon May 30 06:02:07 2011
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.la
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.MarkerManager;
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.BasicConfigurationFactory;
 import org.apache.logging.log4j.core.Logger;
@@ -25,21 +26,32 @@ import org.apache.logging.log4j.core.Log
 import org.apache.logging.log4j.core.appender.ConsoleAppender;
 import org.apache.logging.log4j.core.appender.ListAppender;
 import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.message.StructuredDataMessage;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 import java.util.List;
+import java.util.Locale;
 
 import static org.junit.Assert.assertTrue;
 
 /**
  *
  */
-public class XMLLayoutTest {
+public class RFC5424LayoutTest {
     LoggerContext ctx = (LoggerContext) LogManager.getContext();
     Logger root = ctx.getLogger("");
 
+
+    private static final String line1 = "ATM - - - starting mdc pattern test";
+    private static final String line2 = "ATM - - - empty mdc";
+    private static final String line3 = "ATM - - - filled mdc";
+    private static final String line4 =
+        "ATM - Audit [Transfer@18060 Amount=\"200.00\" FromAccount=\"123457\" ToAccount=\"123456\"]" +
+        "[RequestContext@18060 ipAddress=\"192.168.0.120\" locale=\"English (United States)\" " +
+        "loginId=\"JohnDoe\"] Transfer Complete";
+
     static ConfigurationFactory cf = new BasicConfigurationFactory();
 
     @BeforeClass
@@ -54,8 +66,7 @@ public class XMLLayoutTest {
         ConfigurationFactory.removeConfigurationFactory(cf);
     }
 
-    private static final String body =
-        "<log4j:message><![CDATA[empty mdc]]></log4j:message>\r";
+
 
 
     /**
@@ -65,7 +76,8 @@ public class XMLLayoutTest {
     public void testLayout() throws Exception {
 
         // set up appender
-        XMLLayout layout = XMLLayout.createLayout("true", "true", "true", null);
+        RFC5424Layout layout = RFC5424Layout.createLayout("Local0", "Event", "3692", "true", "RequestContext", "true",
+            "ATM", null, "key1, key2", null, null);
         ListAppender appender = new ListAppender("List", null, layout, true, false);
         appender.start();
 
@@ -83,18 +95,24 @@ public class XMLLayoutTest {
 
         root.debug("filled mdc");
 
-        ThreadContext.remove("key1");
-        ThreadContext.remove("key2");
+        ThreadContext.put("loginId", "JohnDoe");
+        ThreadContext.put("ipAddress", "192.168.0.120");
+        ThreadContext.put("locale", Locale.US.getDisplayName());
+        StructuredDataMessage msg = new StructuredDataMessage("Transfer@18060", "Transfer Complete", "Audit");
+        msg.put("ToAccount", "123456");
+        msg.put("FromAccount", "123457");
+        msg.put("Amount", "200.00");
+        root.info(MarkerManager.getMarker("EVENT"), msg);
 
-        root.error("finished mdc pattern test", new NullPointerException("test"));
+        ThreadContext.clear();
 
         appender.stop();
 
         List<String> list = appender.getMessages();
 
-        assertTrue("Incorrect number of lines. Require at least 50 " + list.size(), list.size() > 50);
-        assertTrue("Incorrect header", list.get(0).equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r"));
-        assertTrue("Incorrect footer", list.get(list.size() - 1).equals("</log4j:eventSet>\r"));
-        assertTrue("Incorrect body. Expected " + body + " Actual: " + list.get(8), list.get(8).equals(body));
+        assertTrue("Expected line 1 to end with: " + line1 + " Actual " + list.get(0), list.get(0).endsWith(line1));
+        assertTrue("Expected line 2 to end with: " + line2 + " Actual " + list.get(1), list.get(1).endsWith(line2));
+        assertTrue("Expected line 3 to end with: " + line3 + " Actual " + list.get(2), list.get(2).endsWith(line3));
+        assertTrue("Expected line 4 to end with: " + line4 + " Actual " + list.get(3), list.get(3).endsWith(line4));
     }
 }

Added: logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java?rev=1129003&view=auto
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java (added)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/test/java/org/apache/logging/log4j/core/layout/SyslogLayoutTest.java Mon May 30 06:02:07 2011
@@ -0,0 +1,116 @@
+/*
+ * 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.logging.log4j.core.layout;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.BasicConfigurationFactory;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.ConsoleAppender;
+import org.apache.logging.log4j.core.appender.ListAppender;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.message.StructuredDataMessage;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Locale;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class SyslogLayoutTest {
+    LoggerContext ctx = (LoggerContext) LogManager.getContext();
+    Logger root = ctx.getLogger("");
+
+
+    private static final String line1 = "starting mdc pattern test";
+    private static final String line2 = "empty mdc";
+    private static final String line3 = "filled mdc";
+    private static final String line4 =
+        "Audit [Transfer@18060 Amount=\"200.00\" FromAccount=\"123457\" ToAccount=\"123456\"] Transfer Complete";
+
+    static ConfigurationFactory cf = new BasicConfigurationFactory();
+
+    @BeforeClass
+    public static void setupClass() {
+        ConfigurationFactory.setConfigurationFactory(cf);
+        LoggerContext ctx = (LoggerContext) LogManager.getContext();
+        ctx.reconfigure();
+    }
+
+    @AfterClass
+    public static void cleanupClass() {
+        ConfigurationFactory.removeConfigurationFactory(cf);
+    }
+
+
+
+
+    /**
+     * Test case for MDC conversion pattern.
+     */
+    @Test
+    public void testLayout() throws Exception {
+
+        // set up appender
+        SyslogLayout layout = SyslogLayout.createLayout("Local0", "true", null);
+        //ConsoleAppender appender = new ConsoleAppender("Console", layout);
+        ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        root.addAppender(appender);
+        root.setLevel(Level.DEBUG);
+
+        // output starting message
+        root.debug("starting mdc pattern test");
+
+        root.debug("empty mdc");
+
+        ThreadContext.put("key1", "value1");
+        ThreadContext.put("key2", "value2");
+
+        root.debug("filled mdc");
+
+        ThreadContext.put("loginId", "JohnDoe");
+        ThreadContext.put("ipAddress", "192.168.0.120");
+        ThreadContext.put("locale", Locale.US.getDisplayName());
+        StructuredDataMessage msg = new StructuredDataMessage("Transfer@18060", "Transfer Complete", "Audit");
+        msg.put("ToAccount", "123456");
+        msg.put("FromAccount", "123457");
+        msg.put("Amount", "200.00");
+        root.info(MarkerManager.getMarker("EVENT"), msg);
+
+        ThreadContext.clear();
+
+        appender.stop();
+
+        List<String> list = appender.getMessages();
+
+        assertTrue("Expected line 1 to end with: " + line1 + " Actual " + list.get(0), list.get(0).endsWith(line1));
+        assertTrue("Expected line 2 to end with: " + line2 + " Actual " + list.get(1), list.get(1).endsWith(line2));
+        assertTrue("Expected line 3 to end with: " + line3 + " Actual " + list.get(2), list.get(2).endsWith(line3));
+        assertTrue("Expected line 4 to end with: " + line4 + " Actual " + list.get(3), list.get(3).endsWith(line4));
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org