Binary files log4j-gelf/.DS_Store and empty/.DS_Store differ diff -r --unidirectional-new-file -N log4j-gelf/pom.xml empty/pom.xml 1,255d0 < < < 4.0.0 < < < org.apache.logging.log4j < log4j < 2.0RC1-SNAPSHOT < ../ < < < log4j-gelf < < log4j GELF Appender < 2013 < < < UTF-8 < .. < < < 1.1 < 4.11 < < < < < < src/main/resources < true < < < < < < org.apache.maven.plugins < maven-site-plugin < < 3.3 < < < < org.apache.maven.plugins < maven-jar-plugin < < < < test-jar < < < < < < < < org.apache.maven.plugins < maven-remote-resources-plugin < < < < process < < < false < < < < < < < org.apache.maven.plugins < maven-dependency-plugin < 2.8 < < < < org.apache.maven.plugins < maven-release-plugin < 2.4.1 < < sonatype-oss-release < deploy < < < < < org.codehaus.mojo < exec-maven-plugin < 1.2.1 < < < process-classes < < java < < < < < org.apache.logging.log4j.core.config.plugins.PluginManager < < ${project.build.outputDirectory} < org.apache.logging.log4j.gelf < < < < < < < < < com.googlecode.json-simple < json-simple < ${com.googlecode.json-simple.version} < < < org.apache.logging.log4j < log4j-api < < < org.apache.logging.log4j < log4j-core < < < junit < junit < ${junit.version} < test < < < < < < < org.apache.maven.plugins < maven-changes-plugin < ${changes.plugin.version} < < < < changes-report < < < < < %URL%/show_bug.cgi?id=%ISSUE% < true < < < < org.apache.maven.plugins < maven-checkstyle-plugin < 2.7 < < < ${log4jParentDir}/checkstyle.xml < ${log4jParentDir}/checkstyle-suppressions.xml < false < basedir=${basedir} < licensedir=${log4jParentDir}/checkstyle-header.txt < < < < org.apache.maven.plugins < maven-javadoc-plugin < ${javadoc.plugin.version} < < Copyright © {inceptionYear}-{currentYear} {organizationName}. All Rights Reserved.
< Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, the Apache Logging project logo, < and the Apache Log4j logo are trademarks of The Apache Software Foundation.

]]>
< < false < true < < < issue < a < JIRA issue: < < < doubt < a < Troublesome: < < < compare < a < Compare with: < < <
< < < non-aggregate < < javadoc < < < <
< < org.codehaus.mojo < findbugs-maven-plugin < 2.5.2 < < true < -Duser.language=en < Normal < Default < ${log4jParentDir}/findbugs-exclude-filter.xml < < < < org.apache.maven.plugins < maven-jxr-plugin < 2.3 < < < non-aggregate < < jxr < < < < aggregate < < aggregate < < < < < < org.apache.maven.plugins < maven-pmd-plugin < ${pmd.plugin.version} < < ${maven.compile.target} < < < < org.codehaus.mojo < cobertura-maven-plugin < ${cobertura.plugin.version} < < < < < < < <
<
<
\ No newline at end of file Binary files log4j-gelf/src/.DS_Store and empty/src/.DS_Store differ Binary files log4j-gelf/src/main/.DS_Store and empty/src/main/.DS_Store differ Binary files log4j-gelf/src/main/java/.DS_Store and empty/src/main/java/.DS_Store differ diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/MdcMessageField.java empty/src/main/java/org/apache/logging/log4j/gelf/MdcMessageField.java 1,50d0 < /* < * 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.gelf; < < /** < * Log-Field pulling a Value from MDC. < */ < public class MdcMessageField implements MessageField { < < private String name; < private String mdcName; < < public MdcMessageField(String name, String mdcName) { < this.mdcName = mdcName; < this.name = name; < } < < public String getMdcName() { < return mdcName; < } < < public String getName() { < return name; < } < < @Override < public String toString() { < final StringBuffer sb = new StringBuffer(); < sb.append(getClass().getSimpleName()); < sb.append(" [name='").append(name).append('\''); < sb.append(", mdcName='").append(mdcName).append('\''); < sb.append(']'); < return sb.toString(); < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/MessageField.java empty/src/main/java/org/apache/logging/log4j/gelf/MessageField.java 1,29d0 < /* < * 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.gelf; < < /** < * Generic message field. < */ < public interface MessageField { < /** < * < * @return the field name. < */ < String getName(); < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/PatternLogMessageField.java empty/src/main/java/org/apache/logging/log4j/gelf/PatternLogMessageField.java 1,52d0 < /* < * 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.gelf; < < import org.apache.logging.log4j.core.layout.PatternLayout; < < /** < * Log-Field using a PatternLayout. < */ < public class PatternLogMessageField implements MessageField { < < private String name; < private PatternLayout patternLayout; < < public PatternLogMessageField(String name, PatternLayout patternLayout) { < this.name = name; < this.patternLayout = patternLayout; < } < < public PatternLayout getPatternLayout() { < return patternLayout; < } < < public String getName() { < return name; < } < < @Override < public String toString() { < final StringBuffer sb = new StringBuffer(); < sb.append(getClass().getSimpleName()); < sb.append(" [name='").append(name).append('\''); < sb.append(", patternLayout=").append(patternLayout); < sb.append(']'); < return sb.toString(); < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/RuntimeContainer.java empty/src/main/java/org/apache/logging/log4j/gelf/RuntimeContainer.java 1,125d0 < /* < * 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.gelf; < < import java.io.IOException; < import java.net.InetAddress; < import java.net.NetworkInterface; < import java.net.SocketException; < import java.util.Enumeration; < < import org.apache.logging.log4j.LogManager; < import org.apache.logging.log4j.Logger; < < /** < * Static Details about the runtime container: Hostname (simple/fqdn), Address and timestamp of the first access (time when the < * application was loaded). < */ < public class RuntimeContainer { < < /** < * Current Hostname. < */ < public static final String HOSTNAME; < < /** < * Current FQDN Hostname. < */ < public static final String FQDN_HOSTNAME; < < /** < * Current Address. < */ < public static final String ADDRESS; < < /** < * Load-Time of this class. < */ < public static final long FIRST_ACCESS; < < private static final Logger LOGGER = LogManager.getLogger(RuntimeContainer.class); < < /** < * Utility Constructor. < */ < private RuntimeContainer() { < < } < < static { < < FIRST_ACCESS = System.currentTimeMillis(); < < String myHostName = "unknown"; < String myFQDNHostName = "unknown"; < String myAddress = ""; < try { < < InetAddress inetAddress = getInetAddressWithHostname(); < < if (inetAddress == null) { < inetAddress = InetAddress.getLocalHost(); < } < < myHostName = getHostname(inetAddress, false); < myFQDNHostName = getHostname(inetAddress, true); < myAddress = inetAddress.getHostAddress(); < } catch (IOException e) { < LOGGER.info(e.getMessage(), e); < } < < FQDN_HOSTNAME = myFQDNHostName; < HOSTNAME = myHostName; < ADDRESS = myAddress; < } < < private static String getHostname(InetAddress inetAddress, boolean fqdn) throws IOException { < < String hostname = inetAddress.getHostName(); < if (hostname.indexOf('.') != -1 && !fqdn) { < hostname = hostname.substring(0, hostname.indexOf('.')); < } < < return hostname; < } < < private static InetAddress getInetAddressWithHostname() throws SocketException { < Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces(); < < while (netInterfaces.hasMoreElements()) { < NetworkInterface ni = netInterfaces.nextElement(); < < Enumeration ias = ni.getInetAddresses(); < while (ias.hasMoreElements()) { < InetAddress inetAddress = ias.nextElement(); < < if (inetAddress.isLoopbackAddress()) { < continue; < } < < if (inetAddress.getHostAddress().equals(inetAddress.getCanonicalHostName())) { < continue; < } < < return inetAddress; < } < } < < return null; < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/StackTraceFilter.java empty/src/main/java/org/apache/logging/log4j/gelf/StackTraceFilter.java 1,231d0 < /* < * 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.gelf; < < import org.apache.logging.log4j.status.StatusLogger; < < import java.io.IOException; < import java.io.InputStream; < import java.io.PrintWriter; < import java.io.StringWriter; < import java.util.Arrays; < import java.util.HashSet; < import java.util.List; < import java.util.Properties; < import java.util.Set; < < /** < * Filtering Facility for Stack-Traces. This is to shorten very long Traces. It leads to a very short Trace containing only the < * interesting parts. Please provide an own Resource /StackTraceFilter.packages with the packages you want to have filtered out < * (one package per line) < * < * < # Packages to filter < org.h2 < org.apache.catalina < org.apache.coyote < org.apache.tomcat < com.arjuna < org.apache.cxf < * < * < */ < @SuppressWarnings("ALL") < public class StackTraceFilter { < < private static final StatusLogger LOG = StatusLogger.getLogger(); < private static final String INDENT = "\t"; < private static final String FILTER_SETTINGS = "/" + StackTraceFilter.class.getSimpleName() + ".packages"; < < /** < * List of Surpressed Packages. < */ < private static Set suppressedPackages; < < static { < < InputStream is = null; < try { < is = getStream(); < if (is == null) { < LOG.debug("No " + FILTER_SETTINGS + " resource present, using defaults"); < suppressedPackages = new HashSet(getDefaults()); < } else { < Properties p = new Properties(); < p.load(is); < //noinspection unchecked,unchecked < suppressedPackages = (Set) p.keySet(); < } < < } catch (IOException e) { < LOG.warn("Could not parse " + FILTER_SETTINGS + " resource, using defaults", e); < suppressedPackages = new HashSet(getDefaults()); < } finally { < try { < if (is != null) { < is.close(); < } < } catch (IOException e) { < // ignore < } < } < < } < < private static InputStream getStream() { < < Thread thread = Thread.currentThread(); < InputStream is = StackTraceFilter.class.getResourceAsStream(FILTER_SETTINGS); < if (is == null && thread.getContextClassLoader() != null) { < is = thread.getContextClassLoader().getResourceAsStream(FILTER_SETTINGS); < } < return is; < } < < public static List getDefaults() { < < return Arrays.asList("org.h2", "org.apache.catalina", "org.apache.coyote", "org.apache.tomcat", "com.arjuna", < "org.apache.cxf", "org.hibernate", "org.junit", "org.jboss", "java.lang.reflect.Method", "sun.", "com.sun", < "org.eclipse", "junit.framework", "com.sun.faces", "javax.faces", "org.richfaces", "org.apache.el", < "javax.servlet"); < } < < /** < * Utility-Constructor. < */ < private StackTraceFilter() { < < } < < /** < * Filter Stack-Trace < * < * @param t the throwable < * @return String containing the filtered Stack-Trace. < */ < public static String getFilteredStackTrace(Throwable t) { < < return getFilteredStackTrace(t, true); < } < < /** < * Filter Stack-Trace < * < * @param t the throwable < * @param shouldFilter true in case filtering should be performed. Else stack-trace as string will be returned. < * @return String containing the Stack-Trace. < */ < public static String getFilteredStackTrace(Throwable t, boolean shouldFilter) { < < try { < StringWriter sw = new StringWriter(); < PrintWriter pw = new PrintWriter(sw); < writeCleanStackTrace(t, pw, shouldFilter); < return sw.getBuffer().toString(); < } catch (Exception e) { < LOG.warn("Error filtering StackTrace: " + e.getMessage()); < return e.toString(); < } < } < < private static void writeCleanStackTrace(Throwable t, PrintWriter s, boolean wantsFilter) { < < s.print("Exception: "); < < printExceptionChain(t, s); < < Set skippedPackages = new HashSet(); < int skippedLines = 0; < boolean shouldFilter = wantsFilter; < boolean first = true; < < for (StackTraceElement traceElement : getBottomThrowable(t).getStackTrace()) { < String forbiddenPackageName = null; < < if (shouldFilter && !first) { < forbiddenPackageName = tryGetForbiddenPackageName(traceElement); < } < < first = false; < < if (forbiddenPackageName == null) { < < if (!skippedPackages.isEmpty()) { < // 37 lines skipped for [org.h2, org.hibernate, sun., < // java.lang.reflect.Method, $Proxy] < s.println(getSkippedPackagesMessage(skippedPackages, skippedLines)); < } < < // at hib.HibExample.test(HibExample.java:18) < s.println(INDENT + "at " + traceElement); < skippedPackages.clear(); < skippedLines = 0; < } else { < skippedLines++; < skippedPackages.add(forbiddenPackageName); < } < } < < if (skippedLines > 0) { < s.println(getSkippedPackagesMessage(skippedPackages, skippedLines)); < } < } < < // 37 lines skipped for [org.h2, org.hibernate, sun., < // java.lang.reflect.Method, $Proxy] < private static String getSkippedPackagesMessage(Set skippedPackages, int skippedLines) { < < return INDENT + INDENT + skippedLines + " line" + (skippedLines == 1 ? "" : "s") + " skipped for " + skippedPackages; < } < < private static Throwable getBottomThrowable(Throwable t) { < < Throwable result = t; < while (result.getCause() != null) { < result = result.getCause(); < } < return result; < } < < private static void printExceptionChain(Throwable t, PrintWriter s) { < < s.println(t); < if (t.getCause() != null) { < s.print("Caused by: "); < printExceptionChain(t.getCause(), s); < } < } < < /** < * Checks to see if the class is part of a forbidden package. If so, it returns the package name from the list of suppressed < * packages that matches, otherwise it returns null. < * < * @param traceElement StackTraceElement < * @return forbidden package name or null. < */ < private static String tryGetForbiddenPackageName(StackTraceElement traceElement) { < < String classAndMethod = traceElement.getClassName() + "." + traceElement.getMethodName(); < for (String pkg : suppressedPackages) { < if (classAndMethod.startsWith(pkg)) { < return pkg; < } < } < return null; < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/StaticMessageField.java empty/src/main/java/org/apache/logging/log4j/gelf/StaticMessageField.java 1,49d0 < /* < * 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.gelf; < < /** < */ < public class StaticMessageField implements MessageField { < < private String name; < private String value; < < public StaticMessageField(String name, String value) { < this.name = name; < this.value = value; < } < < public String getName() { < return name; < } < < public String getValue() { < return value; < } < < @Override < public String toString() { < final StringBuffer sb = new StringBuffer(); < sb.append(getClass().getSimpleName()); < sb.append(" [name='").append(name).append('\''); < sb.append(", value='").append(value).append('\''); < sb.append(']'); < return sb.toString(); < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfConnectionSpec.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfConnectionSpec.java 1,45d0 < /* < * 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.gelf.appender; < < /** < * Connection details (host, port). < */ < class GelfConnectionSpec { < < public static final int DEFAULT_PORT = 12201; < < private String host; < private int port = DEFAULT_PORT; < < public void setHost(String host) { < this.host = host; < } < < public void setPort(int port) { < this.port = port; < } < < public String getHost() { < return host; < } < < public int getPort() { < return port; < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfLogAppender.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfLogAppender.java 1,307d0 < /* < * 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.gelf.appender; < < import org.apache.logging.log4j.Logger; < import org.apache.logging.log4j.core.Filter; < import org.apache.logging.log4j.core.LogEvent; < import org.apache.logging.log4j.core.appender.AbstractAppender; < 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.PluginElement; < import org.apache.logging.log4j.core.config.plugins.PluginFactory; < import org.apache.logging.log4j.core.helpers.Strings; < import org.apache.logging.log4j.gelf.MdcMessageField; < import org.apache.logging.log4j.gelf.PatternLogMessageField; < import org.apache.logging.log4j.gelf.StaticMessageField; < import org.apache.logging.log4j.status.StatusLogger; < < /** < * Logging-Handler for GELF (Graylog Extended Logging Format). This Java-Util-Logging Handler creates GELF Messages and posts < * them using UDP (default) or TCP. Following parameters are supported/needed: < *

< *

    < *
  • host (Mandatory): Hostname/IP-Address of the Logstash Host < *
      < *
    • tcp:(the host) for TCP, e.g. tcp:127.0.0.1 or tcp:some.host.com
    • < *
    • udp:(the host) for UDP, e.g. udp:127.0.0.1 or udp:some.host.com
    • < *
    • (the host) for UDP, e.g. 127.0.0.1 or some.host.com
    • < *
    < *
  • < *
  • port (Optional): Port, default 12201
  • < *
  • extractStackTrace (Optional): Post Stack-Trace to StackTrace field, default false
  • < *
  • filterStackTrace (Optional): Perform Stack-Trace filtering (true/false), default false
  • < *
  • mdcProfiling (Optional): Perform Profiling (Call-Duration) based on MDC Data. See MDC < * Profiling, default false
  • < *
  • facility (Optional): Name of the Facility, default log4j-gelf
  • < *
< * < *

Fields

< * < *

< * Log4j v2 supports an extensive and flexible configuration in contrast to other log frameworks (JUL, log4j v1). This allows < * you to specify your needed fields you want to use in the GELF message. An empty field configuration results in a message < * containing only < *

< * < *
    < *
  • timestamp
  • < *
  • level (syslog level)
  • < *
  • host
  • < *
  • facility
  • < *
  • message
  • < *
  • short_message
  • < *
< *
< * < *

< * You can add different fields: < *

< * < * < *
< * < * In order to do so, use nested Field elements below the Appender element. < * < *

Static Literals

< <Field name="fieldName1" literal="your literal value" /> < * < * < *

MDC Fields

< <Field name="fieldName1" mdc="name of the MDC entry" /> < * < * < * < *

Log-Event fields

< *

< * See also: Pattern Layout < *

< * < *

< * You can use all built-in Pattern Fields: < *

< * < <Field name="simpleClassName" pattern="%C{1}" />
< <Field name="timestamp" pattern="%d{dd MMM yyyy HH:mm:ss,SSS}" />
< <Field name="level" pattern="%level" /> <
< * < *

< * Additionally, you can add the host-Field, which can supply you either the FQDN hostname, the simple hostname < * or the local address. < *

< * < * < * < * < * < * < * < * < * < * < * < *
OptionDescription
< * host
< *   {["fqdn"
< *   |"simple"
< *   |"address"]}
< *

< * Outputs either the FQDN hostname, the simple hostname or the local address. < *

< *

< * You can follow the throwable conversion word with an option in the form %host{option}. < *

< *

< * %host{fqdn} default setting, outputs the FQDN hostname, e.g. www.you.host.name.com. < *

< *

< * %host{simple} outputs simple hostname, e.g. www. < *

< *

< * %host{address} outputs the local IP address of the found hostname, e.g. 1.2.3.4 or affe:affe:affe::1. < *

< *
< * < */ < @Plugin(name = "Gelf", category = "Core", elementType = "appender", printObject = true) < public class GelfLogAppender extends AbstractAppender { < private static final Logger LOGGER = StatusLogger.getLogger(); < < private GelfMessageAssembler gelfMessageAssembler; < private GelfManager gelfManager; < < public GelfLogAppender(String name, Filter filter, GelfMessageAssembler gelfMessageAssembler, GelfManager gelfManager) { < super(name, filter, null); < this.gelfMessageAssembler = gelfMessageAssembler; < this.gelfManager = gelfManager; < } < < /** < * < * @param name < * @param filter < * @param fields < * @param graylogHost < * @param host < * @param graylogPort < * @param port < * @param extractStackTrace < * @param facility < * @param filterStackTrace < * @param maximumMessageSize < * @param testSenderClass < * @return GelfLogAppender < */ < @PluginFactory < public static GelfLogAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filter") Filter filter, < @PluginElement("Field") final GelfLogField[] fields, @PluginAttribute("graylogHost") String graylogHost, < @PluginAttribute("host") String host, @PluginAttribute("graylogPort") String graylogPort, < @PluginAttribute("port") String port, @PluginAttribute("extractStackTrace") String extractStackTrace, < @PluginAttribute("facility") String facility, @PluginAttribute("filterStackTrace") String filterStackTrace, < @PluginAttribute("maximumMessageSize") String maximumMessageSize, < @PluginAttribute("testSenderClass") String testSenderClass) { < < GelfMessageAssembler mdcGelfMessageAssembler = new GelfMessageAssembler(); < < if (name == null) { < LOGGER.error("No name provided for " + GelfLogAppender.class.getSimpleName()); < return null; < } < < if (Strings.isEmpty(host) && Strings.isEmpty(graylogHost)) { < LOGGER.error("No host provided for " + GelfLogAppender.class.getSimpleName()); < return null; < } < < GelfManager gelfManager = getGelfManager(graylogHost, host, graylogPort, port); < < if (facility != null) { < mdcGelfMessageAssembler.setFacility(facility); < } < < if (extractStackTrace != null) { < mdcGelfMessageAssembler.setExtractStackTrace(extractStackTrace.equals("true")); < } < < if (filterStackTrace != null) { < mdcGelfMessageAssembler.setFilterStackTrace(filterStackTrace.equals("true")); < } < < if (maximumMessageSize != null) { < mdcGelfMessageAssembler.setMaximumMessageSize(Integer.parseInt(maximumMessageSize)); < } < < configureFields(mdcGelfMessageAssembler, fields); < < GelfLogAppender result = new GelfLogAppender(name, filter, mdcGelfMessageAssembler, gelfManager); < < if (testSenderClass != null) { < result.setTestSenderClass(testSenderClass); < } < < return result; < < } < < private static GelfManager getGelfManager(String graylogHost, String host, String graylogPort, String port) { < GelfConnectionSpec gelfConnectionSpec = new GelfConnectionSpec(); < < if (Strings.isNotEmpty(host)) { < gelfConnectionSpec.setHost(host); < } < < if (Strings.isNotEmpty(graylogHost)) { < gelfConnectionSpec.setHost(graylogHost); < } < < if (Strings.isNotEmpty(port)) { < gelfConnectionSpec.setPort(Integer.parseInt(port)); < } < < if (Strings.isNotEmpty(graylogPort)) { < gelfConnectionSpec.setPort(Integer.parseInt(graylogPort)); < } < < return GelfManager.getManager(GelfManager.class.getSimpleName() + "-" + gelfConnectionSpec.getHost() + ":" < + gelfConnectionSpec.getPort(), new GelfManagerFactory(), gelfConnectionSpec); < } < < /** < * Configure fields (literals, MDC, layout). < * < * @param mdcGelfMessageAssembler < * @param fields < */ < private static void configureFields(GelfMessageAssembler mdcGelfMessageAssembler, GelfLogField[] fields) { < < for (GelfLogField field : fields) { < < if (Strings.isNotEmpty(field.getMdc())) { < mdcGelfMessageAssembler.addField(new MdcMessageField(field.getName(), field.getMdc())); < } < < if (Strings.isNotEmpty(field.getLiteral())) { < mdcGelfMessageAssembler.addField(new StaticMessageField(field.getName(), field.getLiteral())); < } < < if (field.getPatternLayout() != null) { < mdcGelfMessageAssembler.addField(new PatternLogMessageField(field.getName(), field.getPatternLayout())); < } < } < } < < @Override < public void append(LogEvent event) { < if (event == null) { < return; < } < < GelfMessage gelfMessage = gelfMessageAssembler.createGelfMessage(event); < if (!gelfMessage.isValid()) { < LOGGER.error("GELF Message is invalid: " + gelfMessage.toJson()); < return; < } < < gelfManager.send(gelfMessage); < } < < @Override < public void stop() { < gelfManager.release(); < super.stop(); < } < < public void setTestSenderClass(String testSender) { < // This only used for testing < try { < if (null != testSender) { < final Class clazz = Class.forName(testSender); < gelfManager.setGelfSender((GelfSender) clazz.newInstance()); < } < } catch (final Exception e) { < // ignore < } < } < < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfLogField.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfLogField.java 1,92d0 < /* < * 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.gelf.appender; < < import org.apache.logging.log4j.Logger; < import org.apache.logging.log4j.core.config.Configuration; < 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.PluginConfiguration; < import org.apache.logging.log4j.core.config.plugins.PluginFactory; < import org.apache.logging.log4j.core.helpers.Strings; < import org.apache.logging.log4j.core.layout.PatternLayout; < import org.apache.logging.log4j.status.StatusLogger; < < /** < * Configuration for a log field. < * < */ < @Plugin(name = "Field", category = "Core", printObject = true) < public class GelfLogField { < < private static final Logger LOGGER = StatusLogger.getLogger(); < < private String name; < private String literal; < private String mdc; < private PatternLayout patternLayout; < < public GelfLogField(String name, String literal, String mdc, PatternLayout patternLayout) { < this.name = name; < this.literal = literal; < this.mdc = mdc; < this.patternLayout = patternLayout; < } < < public String getName() { < return name; < } < < public String getLiteral() { < return literal; < } < < public String getMdc() { < return mdc; < } < < public PatternLayout getPatternLayout() { < return patternLayout; < } < < @PluginFactory < public static GelfLogField createField(@PluginConfiguration final Configuration config, < @PluginAttribute("name") String name, @PluginAttribute("literal") String literalValue, < @PluginAttribute("mdc") String mdc, @PluginAttribute("pattern") String pattern) { < < final boolean isPattern = Strings.isNotEmpty(pattern); < final boolean isLiteralValue = Strings.isNotEmpty(literalValue); < final boolean isMDC = Strings.isNotEmpty(mdc); < < if (Strings.isEmpty(name)) { < LOGGER.error("The name is empty"); < return null; < } < < if ((isPattern && isLiteralValue) || (isPattern && isMDC) || (isLiteralValue && isMDC)) { < LOGGER.error("The pattern, literal, and mdc attributes are mutually exclusive."); < return null; < } < < if (isPattern) { < return new GelfLogField(name, null, null, PatternLayout.createLayout(pattern, config, null, null, "false")); < } < < return new GelfLogField(name, literalValue, mdc, null); < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfManager.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfManager.java 1,80d0 < /* < * 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.gelf.appender; < < import java.io.IOException; < import java.net.SocketException; < import java.net.UnknownHostException; < < import org.apache.logging.log4j.core.appender.AbstractManager; < < /** < * Resource manager for TCP/UDP Sender. < */ < public class GelfManager extends AbstractManager { < < private GelfConnectionSpec gelfConnectionSpec; < private GelfSender gelfSender; < < protected GelfManager(String name, GelfConnectionSpec gelfConnectionSpec) { < super(name); < this.gelfConnectionSpec = gelfConnectionSpec; < < } < < @Override < protected void releaseSub() { < if (gelfSender != null) { < gelfSender.close(); < gelfSender = null; < } < } < < private void start() { < if (null == gelfSender) { < try { < this.gelfSender = GelfSenderFactory.createSender(gelfConnectionSpec.getHost(), < gelfConnectionSpec.getPort()); < } catch (UnknownHostException e) { < LOGGER.error("Unknown Graylog2 hostname:" + gelfConnectionSpec.getHost(), e); < } catch (SocketException e) { < LOGGER.error("Socket exception", e); < } catch (IOException e) { < LOGGER.error("IO exception", e); < } < } < } < < public void send(GelfMessage message) { < if (gelfSender == null) { < start(); < } < try { < < if (null == gelfSender || !gelfSender.sendMessage(message)) { < LOGGER.error("Could not send GELF message"); < } < } catch (Exception e) { < LOGGER.error("Could not send GELF message", e); < } < } < < public void setGelfSender(GelfSender gelfSender) { < this.gelfSender = gelfSender; < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfManagerFactory.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfManagerFactory.java 1,33d0 < /* < * 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.gelf.appender; < < import org.apache.logging.log4j.core.appender.ManagerFactory; < < /** < * Factory for GELF Manager. < */ < class GelfManagerFactory implements ManagerFactory { < @Override < public GelfManager createManager(String name, GelfConnectionSpec gelfConnectionSpec) { < < GelfManager gelfManager = new GelfManager(name, gelfConnectionSpec); < < return gelfManager; < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfMessage.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfMessage.java 1,259d0 < /* < * 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.gelf.appender; < < import java.io.ByteArrayOutputStream; < import java.io.IOException; < import java.io.UnsupportedEncodingException; < import java.math.BigDecimal; < import java.nio.ByteBuffer; < import java.util.Arrays; < import java.util.HashMap; < import java.util.Map; < import java.util.zip.GZIPOutputStream; < < import org.json.simple.JSONValue; < < /** < * by https://github.com/t0xa/gelfj. < */ < public class GelfMessage { < < private static final String ID_NAME = "id"; < private static final String GELF_VERSION = "1.0"; < private static final byte[] GELF_CHUNKED_ID = new byte[] { 0x1e, 0x0f }; < private static final BigDecimal TIME_DIVISOR = new BigDecimal(1000); < < private String version = GELF_VERSION; < private String host; < private byte[] hostBytes = lastFourAsciiBytes("none"); < private String shortMessage; < private String fullMessage; < private long javaTimestamp; < private String level; < private String facility = "log4j-gelf"; < private Map additonalFields = new HashMap(); < private int maximumMessageSize = 8192; < < public GelfMessage() { < } < < public GelfMessage(String shortMessage, String fullMessage, long timestamp, String level) { < < this.shortMessage = shortMessage; < this.fullMessage = fullMessage; < this.javaTimestamp = timestamp; < this.level = level; < } < < public String toJson() { < Map map = new HashMap(); < < // map.put("version", getVersion()); < map.put("host", getHost()); < map.put("short_message", getShortMessage()); < map.put("full_message", getFullMessage()); < map.put("timestamp", getTimestamp()); < < map.put("level", getLevel()); < map.put("facility", getFacility()); < < for (Map.Entry additionalField : additonalFields.entrySet()) { < if (!ID_NAME.equals(additionalField.getKey())) { < map.put("_" + additionalField.getKey(), additionalField.getValue()); < } < } < < return JSONValue.toJSONString(map); < } < < public ByteBuffer[] toUDPBuffers() { < byte[] messageBytes = gzipMessage(toJson()); < // calculate the length of the datagrams array < int diagrams_length = messageBytes.length / maximumMessageSize; < // In case of a remainder, due to the integer division, add a extra datagram < if (messageBytes.length % maximumMessageSize != 0) { < diagrams_length++; < } < ByteBuffer[] datagrams = new ByteBuffer[diagrams_length]; < if (messageBytes.length > maximumMessageSize) { < sliceDatagrams(messageBytes, datagrams); < } else { < datagrams[0] = ByteBuffer.allocate(messageBytes.length); < datagrams[0].put(messageBytes); < datagrams[0].flip(); < } < return datagrams; < } < < public ByteBuffer toTCPBuffer() { < byte[] messageBytes; < try { < // Do not use GZIP, as the headers will contain \0 bytes < // graylog2-server uses \0 as a delimiter for TCP frames < // see: https://github.com/Graylog2/graylog2-server/issues/127 < String json = toJson(); < json += '\0'; < messageBytes = json.getBytes("UTF-8"); < } catch (UnsupportedEncodingException e) { < throw new RuntimeException("No UTF-8 support available.", e); < } < < ByteBuffer buffer = ByteBuffer.allocate(messageBytes.length); < buffer.put(messageBytes); < buffer.flip(); < return buffer; < } < < private void sliceDatagrams(byte[] messageBytes, ByteBuffer[] datagrams) { < int messageLength = messageBytes.length; < byte[] messageId = ByteBuffer.allocate(8).putInt(getCurrentMillis()) // 4 least-significant-bytes of the time in millis < .put(hostBytes) // 4 least-significant-bytes of the host < .array(); < < // Reuse length of datagrams array since this is supposed to be the correct number of datagrams < int num = datagrams.length; < for (int idx = 0; idx < num; idx++) { < byte[] header = concatByteArray(GELF_CHUNKED_ID, concatByteArray(messageId, new byte[] { (byte) idx, (byte) num })); < int from = idx * maximumMessageSize; < int to = from + maximumMessageSize; < if (to >= messageLength) { < to = messageLength; < } < byte[] datagram = concatByteArray(header, Arrays.copyOfRange(messageBytes, from, to)); < datagrams[idx] = ByteBuffer.allocate(datagram.length); < datagrams[idx].put(datagram); < datagrams[idx].flip(); < } < } < < public int getCurrentMillis() { < return (int) System.currentTimeMillis(); < } < < private byte[] gzipMessage(String message) { < ByteArrayOutputStream bos = new ByteArrayOutputStream(); < < try { < GZIPOutputStream stream = new GZIPOutputStream(bos); < byte[] bytes; < try { < bytes = message.getBytes("UTF-8"); < } catch (UnsupportedEncodingException e) { < throw new RuntimeException("No UTF-8 support available.", e); < } < stream.write(bytes); < stream.finish(); < stream.close(); < byte[] zipped = bos.toByteArray(); < bos.close(); < return zipped; < } catch (IOException e) { < return null; < } < } < < private byte[] lastFourAsciiBytes(String host) { < final String shortHost = host.length() >= 4 ? host.substring(host.length() - 4) : host; < try { < return shortHost.getBytes("ASCII"); < } catch (UnsupportedEncodingException e) { < throw new RuntimeException("JVM without ascii support?", e); < } < } < < public String getVersion() { < return version; < } < < public void setVersion(String version) { < this.version = version; < } < < public String getHost() { < return host; < } < < public void setHost(String host) { < this.host = host; < this.hostBytes = lastFourAsciiBytes(host); < } < < public String getShortMessage() { < return !isEmpty(shortMessage) ? shortMessage : ""; < } < < public String getFullMessage() { < return fullMessage; < } < < public String getTimestamp() { < return new BigDecimal(javaTimestamp).divide(TIME_DIVISOR).toPlainString(); < } < < public String getLevel() { < return level; < } < < public String getFacility() { < return facility; < } < < public void setFacility(String facility) { < this.facility = facility; < } < < public GelfMessage addField(String key, String value) { < getAdditonalFields().put(key, value); < return this; < } < < public Map getAdditonalFields() { < return additonalFields; < } < < public boolean isValid() { < return isShortOrFullMessagesExists() && !isEmpty(version) && !isEmpty(host) && !isEmpty(facility); < } < < private boolean isShortOrFullMessagesExists() { < return !isEmpty(shortMessage) || !isEmpty(fullMessage); < } < < public boolean isEmpty(String str) { < return str == null || "".equals(str.trim()); < } < < private byte[] concatByteArray(byte[] first, byte[] second) { < byte[] result = Arrays.copyOf(first, first.length + second.length); < System.arraycopy(second, 0, result, first.length, second.length); < return result; < } < < public int getMaximumMessageSize() { < return maximumMessageSize; < } < < public void setMaximumMessageSize(int maximumMessageSize) { < this.maximumMessageSize = maximumMessageSize; < } < < public String getField(String fieldName) { < return getAdditonalFields().get(fieldName); < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfMessageAssembler.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfMessageAssembler.java 1,196d0 < /* < * 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.gelf.appender; < < import java.io.PrintWriter; < import java.io.StringWriter; < import java.util.ArrayList; < import java.util.List; < import java.util.Map; < < import org.apache.logging.log4j.Level; < import org.apache.logging.log4j.core.LogEvent; < import org.apache.logging.log4j.gelf.MdcMessageField; < import org.apache.logging.log4j.gelf.MessageField; < import org.apache.logging.log4j.gelf.PatternLogMessageField; < import org.apache.logging.log4j.gelf.RuntimeContainer; < import org.apache.logging.log4j.gelf.StackTraceFilter; < import org.apache.logging.log4j.gelf.StaticMessageField; < < /** < * < * Assemble a Gelf Message. < * < */ < class GelfMessageAssembler { < < private static final int MAX_SHORT_MESSAGE_LENGTH = 250; < < public static final String FIELD_MESSAGE_PARAM = "MessageParam"; < public static final String FIELD_STACK_TRACE = "StackTrace"; < < private String originHost; < private String facility; < private boolean extractStackTrace; < private boolean filterStackTrace; < private int maximumMessageSize; < < private List fields = new ArrayList(); < < /** < * Producte a Gelf message. < * < * @param logEvent < * @return GelfMessage < */ < public GelfMessage createGelfMessage(LogEvent logEvent) { < String message = logEvent.getMessage().getFormattedMessage(); < < String shortMessage = message; < if (message.length() > MAX_SHORT_MESSAGE_LENGTH) { < shortMessage = message.substring(0, MAX_SHORT_MESSAGE_LENGTH - 1); < } < < int syslogLevel = levelToSyslogLevel(logEvent.getLevel()); < GelfMessage gelfMessage = new GelfMessage(shortMessage, message, logEvent.getMillis(), Integer.toString(syslogLevel)); < < for (MessageField field : fields) { < String value = getValue(logEvent, field); < if (value == null) { < continue; < } < < gelfMessage.addField(field.getName(), value); < } < < if (extractStackTrace) { < addStackTrace(logEvent, gelfMessage); < } < < if (logEvent.getMessage().getParameters() != null) { < Object[] parameters = logEvent.getMessage().getParameters(); < for (int i = 0; i < parameters.length; i++) { < Object param = parameters[i]; < gelfMessage.addField(FIELD_MESSAGE_PARAM + i, "" + param); < } < } < < gelfMessage.setHost(getOriginHost()); < < if (null != facility) { < gelfMessage.setFacility(facility); < } < < gelfMessage.setMaximumMessageSize(maximumMessageSize); < return gelfMessage; < } < < private String getValue(LogEvent logEvent, MessageField field) { < < if (field instanceof StaticMessageField) { < return getValue((StaticMessageField) field); < } < < if (field instanceof MdcMessageField) { < MdcMessageField mdcMessageField = (MdcMessageField) field; < return getMdc(logEvent, mdcMessageField.getMdcName()); < } < < if (field instanceof PatternLogMessageField) { < PatternLogMessageField patternLogMessageField = (PatternLogMessageField) field; < return patternLogMessageField.getPatternLayout().toSerializable(logEvent); < } < < throw new IllegalArgumentException("Field " + field + " not supported"); < < } < < private String getValue(StaticMessageField field) { < return field.getValue(); < } < < private void addStackTrace(LogEvent logEvent, GelfMessage gelfMessage) { < final Throwable thrown = logEvent.getThrown(); < if (null != thrown) { < if (filterStackTrace) { < gelfMessage.addField(FIELD_STACK_TRACE, StackTraceFilter.getFilteredStackTrace(thrown)); < } else { < final StringWriter sw = new StringWriter(); < thrown.printStackTrace(new PrintWriter(sw)); < gelfMessage.addField(FIELD_STACK_TRACE, sw.toString()); < } < } < } < < private int levelToSyslogLevel(final Level level) { < < switch (level) { < case FATAL: < return 2; < case ERROR: < return 3; < case WARN: < return 4; < case INFO: < return 6; < default: < return 7; < < } < } < < public String getMdc(LogEvent logEvent, String mdcName) { < Map mdcPropertyMap = logEvent.getContextMap(); < if (null != mdcPropertyMap && mdcPropertyMap.containsKey(mdcName)) { < return mdcPropertyMap.get(mdcName); < } < < return null; < } < < public void addField(MessageField field) { < this.fields.add(field); < } < < public String getOriginHost() { < if (null == originHost) { < originHost = RuntimeContainer.FQDN_HOSTNAME; < } < return originHost; < } < < public void setOriginHost(String originHost) { < this.originHost = originHost; < } < < public void setFacility(String facility) { < this.facility = facility; < } < < public void setExtractStackTrace(boolean extractStackTrace) { < this.extractStackTrace = extractStackTrace; < } < < public void setFilterStackTrace(boolean filterStackTrace) { < this.filterStackTrace = filterStackTrace; < } < < public void setMaximumMessageSize(int maximumMessageSize) { < this.maximumMessageSize = maximumMessageSize; < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfSender.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfSender.java 1,37d0 < /* < * 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.gelf.appender; < < /** < * by https://github.com/t0xa/gelfj. < */ < public interface GelfSender { < < /** < * Send the Message. < * < * @param message < * @return < */ < public boolean sendMessage(GelfMessage message); < < /** < * Free resources. < */ < public void close(); < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfSenderFactory.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfSenderFactory.java 1,49d0 < /* < * 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.gelf.appender; < < import java.io.IOException; < < /** < * Sender Factory. < * < */ < class GelfSenderFactory { < < /** < * Construct a sender by host/port. < * < * @param graylogHost udp:(host), tcp:(host) or just (host) < * @param graylogPort < * @return GelfUDPSender if host starts with udp: or no prefix, GelfTCPSender if host starts with tcp: < * @throws IOException < */ < public static GelfSender createSender(String graylogHost, int graylogPort) throws IOException { < < if (graylogHost.startsWith("tcp:")) { < String tcpGraylogHost = graylogHost.substring(4, graylogHost.length()); < return new GelfTCPSender(tcpGraylogHost, graylogPort); < } else if (graylogHost.startsWith("udp:")) { < String udpGraylogHost = graylogHost.substring(4, graylogHost.length()); < return new GelfUDPSender(udpGraylogHost, graylogPort); < } else { < return new GelfUDPSender(graylogHost, graylogPort); < } < < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfTCPSender.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfTCPSender.java 1,70d0 < /* < * 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.gelf.appender; < < import java.io.IOException; < import java.net.InetAddress; < import java.net.Socket; < < /** < * by https://github.com/t0xa/gelfj. < */ < class GelfTCPSender implements GelfSender { < private boolean shutdown = false; < private InetAddress host; < private int port; < private Socket socket; < < public GelfTCPSender(String host, int port) throws IOException { < this.host = InetAddress.getByName(host); < this.port = port; < this.socket = new Socket(host, port); < } < < public boolean sendMessage(GelfMessage message) { < if (shutdown || !message.isValid()) { < return false; < } < < try { < // reconnect if necessary < if (socket == null) { < socket = new Socket(host, port); < } < < socket.getOutputStream().write(message.toTCPBuffer().array()); < < return true; < } catch (IOException e) { < // if an error occours, signal failure < socket = null; < return false; < } < } < < public void close() { < shutdown = true; < try { < if (socket != null) { < socket.close(); < } < } catch (IOException e) { < e.printStackTrace(); < } < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/GelfUDPSender.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/GelfUDPSender.java 1,72d0 < /* < * 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.gelf.appender; < < import java.io.IOException; < import java.net.InetAddress; < import java.net.InetSocketAddress; < import java.nio.ByteBuffer; < import java.nio.channels.DatagramChannel; < < /** < * by https://github.com/t0xa/gelfj < */ < class GelfUDPSender implements GelfSender { < private InetAddress host; < private int port; < private DatagramChannel channel; < < public GelfUDPSender(String host, int port) throws IOException { < this.host = InetAddress.getByName(host); < this.port = port; < this.channel = initiateChannel(); < } < < private DatagramChannel initiateChannel() throws IOException { < DatagramChannel resultingChannel = DatagramChannel.open(); < resultingChannel.socket().bind(new InetSocketAddress(0)); < resultingChannel.connect(new InetSocketAddress(this.host, this.port)); < resultingChannel.configureBlocking(false); < < return resultingChannel; < } < < public boolean sendMessage(GelfMessage message) { < return message.isValid() && sendDatagrams(message.toUDPBuffers()); < } < < private boolean sendDatagrams(ByteBuffer[] bytesList) { < try { < for (ByteBuffer buffer : bytesList) { < channel.write(buffer); < } < } catch (IOException e) { < return false; < } < < return true; < } < < public void close() { < try { < channel.close(); < } catch (IOException e) { < e.printStackTrace(); < } < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/appender/package-info.java empty/src/main/java/org/apache/logging/log4j/gelf/appender/package-info.java 1,21d0 < /* < * 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. < */ < < /** < * log4j v2.x appender for logstash submission over GELF. < */ < package org.apache.logging.log4j.gelf.appender; diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/converter/HostnameConverter.java empty/src/main/java/org/apache/logging/log4j/gelf/converter/HostnameConverter.java 1,98d0 < /* < * 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.gelf.converter; < < import org.apache.logging.log4j.core.LogEvent; < import org.apache.logging.log4j.core.config.plugins.Plugin; < import org.apache.logging.log4j.core.pattern.ConverterKeys; < import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; < import org.apache.logging.log4j.gelf.RuntimeContainer; < < /** < * Provides the current Hostname. < * < * < * < * < * < * < * < * < * < * < * < * < *
OptionDescription
< * host
< *   {["fqdn"
< *   |"simple"
< *   |"address"]}
< *

< * Outputs either the FQDN hostname, the simple hostname or the local address. < *

< *

< * You can follow the throwable conversion word with an option in the form %host{option}. < *

< *

< * %host{fqdn} default setting, outputs the FQDN hostname, e.g. www.you.host.name.com. < *

< *

< * %host{simple} outputs simple hostname, e.g. www. < *

< *

< * %host{address} outputs the local IP address of the found hostname, e.g. 1.2.3.4 or affe:affe:affe::1. < *

< *
< * < */ < @Plugin(name = "HostnameConverter", category = "Converter") < @ConverterKeys({ "host" }) < public class HostnameConverter extends LogEventPatternConverter { < < public HostnameConverter(String style) { < super(HostnameConverter.class.getSimpleName(), style); < } < < public static HostnameConverter newInstance(String[] format) { < String style = null; < if (format.length > 0) { < style = format[0]; < } < return new HostnameConverter(style); < } < < @Override < public void format(LogEvent event, StringBuilder toAppendTo) { < if (getStyle() == null || getStyle().equals("") || getStyle().equals("fqdn")) { < toAppendTo.append(RuntimeContainer.FQDN_HOSTNAME); < } < < if (getStyle() != null && getStyle().equals("simple")) { < toAppendTo.append(RuntimeContainer.HOSTNAME); < < } < < if (getStyle() != null && getStyle().equals("address")) { < toAppendTo.append(RuntimeContainer.ADDRESS); < } < } < < public String getStyle() { < return getStyleClass(null); < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/main/java/org/apache/logging/log4j/gelf/package-info.java empty/src/main/java/org/apache/logging/log4j/gelf/package-info.java 1,21d0 < /* < * 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. < */ < < /** < * Base utilities for GELF (Graylog Extended Logging Format). < */ < package org.apache.logging.log4j.gelf; Binary files log4j-gelf/src/site/.DS_Store and empty/src/site/.DS_Store differ diff -r --unidirectional-new-file -N log4j-gelf/src/site/site.xml empty/src/site/site.xml 1,49d0 < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < diff -r --unidirectional-new-file -N log4j-gelf/src/site/xdoc/index.xml empty/src/site/xdoc/index.xml 1,216d0 < < < < < < Gelf Appender < Mark Paluch < < < <
< <

< The Gelf Appender allows applications to send events to Gelf (Graylog Extended Format) Log-Sinks. < Popular examples are <

< < <

Following settings can be used:

<
    < <
  • host (Mandatory): Hostname/IP-Address of the Logstasg Host <
      <
    • tcp:(the host) for TCP, e.g. tcp:127.0.0.1 or tcp:some.host.com
    • <
    • udp:(the host) for UDP, e.g. udp:127.0.0.1 or udp:some.host.com
    • <
    • (the host) for UDP, e.g. 127.0.0.1 or some.host.com
    • <
    <
  • <
  • port (Optional): Port, default 12201
  • <
  • originHost (Optional): Originating Hostname, default FQDN Hostname
  • <
  • extractStackTrace (Optional): Post Stack-Trace to StackTrace field, default false
  • <
  • filterStackTrace (Optional): Perform Stack-Trace filtering (true/false), default false
  • <
  • mdcProfiling (Optional): Perform Profiling (Call-Duration) based on MDC Data. See MDC Profiling, < default false. See < MDC Profiling < for details. <
  • <
  • facility (Optional): Name of the Facility, default logstash-gelf
  • <
<
< <

Log4j v2 supports an extensive and flexible configuration in contrast to other log frameworks < (JUL, log4j v1). This allows you to specify your needed fields you want to use in the GELF < message. An empty field configuration results in a message containing only <

< <
    <
  • timestamp
  • <
  • level (syslog level)
  • <
  • host
  • <
  • facility
  • <
  • message
  • <
  • short_message
  • <
<

You can add different fields:

< <
    <
  • Static Literals
  • <
  • MDC Fields
  • <
  • Log-Event fields (using Pattern Layout)
  • <
<

In order to do so, use nested Field elements below the Appender element.

<
< < <
 ]]>
<
< < < <
 ]]>
<                 
<
< < <

See also: < Pattern Layout < <

<

Set the desired pattern and the field will be sent using the specified pattern value.

<

Additionally, you can add the host-Field, which can supply you either the FQDN hostname, the < simple hostname or the local address. <

< < < < < < < < < < < < < < < <
Conversion PatternDescription
< host <
<   {["fqdn" <
<   |"simple" <
<   |"address"]} <
<

Outputs either the FQDN hostname, the simple hostname or the local address. You < can < follow the throwable conversion word with an option in the form < %host{option}. <

<

< %host{fqdn} < default setting, outputs the FQDN hostname, e.g. www.you.host.name.com. <

<

< %host{simple} < outputs simple hostname, e.g. www. <

<

< %host{address} < outputs < the local IP address of the found hostname, e.g. 1.2.3.4 or affe:affe:affe::1. <

<
< < <

<     
<         
<             
<             
<             
<             
<             
<             
<              
<              
<         
<     
<     
<         
<             
<         
<     
< 
<                         ]]>
<                 
<
< < <

< This artifact uses json-simple in order to marshal log messages into JSON format. You'll need the < json-simple < Including the Log4j gelf jar in your Maven-based project as a dependency should cause all the < transitive dependencies necessary to function to be included. < library in your project dependencies. <

<

<     
<         
<             com.googlecode.json-simple
<             json-simple
<             1.1
<         
<     
<     
<         
<             com.googlecode.json-simple
<             json-simple
<         
<     
< 
<   ]]>
<
< <
< <
<

< The Gelf Appender requires at least Java 6. <

<
< < <
\ No newline at end of file Binary files log4j-gelf/src/test/.DS_Store and empty/src/test/.DS_Store differ diff -r --unidirectional-new-file -N log4j-gelf/src/test/java/org/apache/logging/log4j/gelf/appender/GelfLogAppenderMinimalTest.java empty/src/test/java/org/apache/logging/log4j/gelf/appender/GelfLogAppenderMinimalTest.java 1,62d0 < package org.apache.logging.log4j.gelf.appender; < < import org.apache.logging.log4j.LogManager; < import org.apache.logging.log4j.Logger; < import org.apache.logging.log4j.ThreadContext; < import org.apache.logging.log4j.core.LoggerContext; < import org.apache.logging.log4j.core.config.ConfigurationFactory; < import org.junit.AfterClass; < import org.junit.Before; < import org.junit.BeforeClass; < import org.junit.Test; < < import static org.junit.Assert.assertEquals; < < /** < */ < public class GelfLogAppenderMinimalTest { < private static LoggerContext loggerContext; < < @BeforeClass < public static void beforeClass() { < System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "log4j2-minimal.xml"); < loggerContext = (LoggerContext) LogManager.getContext(false); < } < < @AfterClass < public static void afterClass() throws Exception { < System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); < loggerContext.reconfigure(); < } < < @Before < public void before() throws Exception { < GelfTestSender.getMessages().clear(); < ThreadContext.clear(); < } < < @Test < public void testSimpleDebug() throws Exception { < < Logger logger = loggerContext.getLogger(getClass().getName()); < assertEquals(0, GelfTestSender.getMessages().size()); < logger.debug("Blubb Test"); < assertEquals(0, GelfTestSender.getMessages().size()); < < } < < @Test < public void testSimpleInfo() throws Exception { < < Logger logger = loggerContext.getLogger(getClass().getName()); < < logger.info("Blubb Test"); < assertEquals(1, GelfTestSender.getMessages().size()); < < GelfMessage gelfMessage = GelfTestSender.getMessages().get(0); < assertEquals("Blubb Test", gelfMessage.getFullMessage()); < assertEquals("6", gelfMessage.getLevel()); < assertEquals("Blubb Test", gelfMessage.getShortMessage()); < < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/test/java/org/apache/logging/log4j/gelf/appender/GelfLogAppenderTest.java empty/src/test/java/org/apache/logging/log4j/gelf/appender/GelfLogAppenderTest.java 1,87d0 < package org.apache.logging.log4j.gelf.appender; < < import static org.junit.Assert.assertEquals; < < import org.apache.logging.log4j.LogManager; < import org.apache.logging.log4j.Logger; < import org.apache.logging.log4j.ThreadContext; < import org.apache.logging.log4j.core.LoggerContext; < import org.apache.logging.log4j.core.config.ConfigurationFactory; < import org.apache.logging.log4j.gelf.RuntimeContainer; < import org.junit.AfterClass; < import org.junit.Before; < import org.junit.BeforeClass; < import org.junit.Test; < < /** < */ < public class GelfLogAppenderTest { < private static LoggerContext loggerContext; < < @BeforeClass < public static void setupClass() { < System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "log4j2.xml"); < loggerContext = (LoggerContext) LogManager.getContext(false); < } < < @AfterClass < public static void afterClass() throws Exception { < System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); < loggerContext.reconfigure(); < } < < @Before < public void before() throws Exception { < GelfTestSender.getMessages().clear(); < ThreadContext.clear(); < } < < @Test < public void testSimpleDebug() throws Exception { < < Logger logger = loggerContext.getLogger(getClass().getName()); < assertEquals(0, GelfTestSender.getMessages().size()); < logger.debug("Blubb Test"); < assertEquals(0, GelfTestSender.getMessages().size()); < < } < < @Test < public void testSimpleInfo() throws Exception { < < Logger logger = loggerContext.getLogger(getClass().getName()); < < logger.info("Blubb Test"); < assertEquals(1, GelfTestSender.getMessages().size()); < < GelfMessage gelfMessage = GelfTestSender.getMessages().get(0); < assertEquals("Blubb Test", gelfMessage.getFullMessage()); < assertEquals("6", gelfMessage.getLevel()); < assertEquals("Blubb Test", gelfMessage.getShortMessage()); < assertEquals(8192, gelfMessage.getMaximumMessageSize()); < < assertEquals(RuntimeContainer.FQDN_HOSTNAME, gelfMessage.getField("server")); < assertEquals(RuntimeContainer.HOSTNAME, gelfMessage.getField("server.simple")); < assertEquals(RuntimeContainer.FQDN_HOSTNAME, gelfMessage.getField("server.fqdn")); < assertEquals(RuntimeContainer.ADDRESS, gelfMessage.getField("server.addr")); < < assertEquals(GelfLogAppenderTest.class.getSimpleName(), gelfMessage.getField("simpleClassName")); < < } < < @Test < public void testMDC() throws Exception { < < Logger logger = loggerContext.getLogger(getClass().getName()); < < ThreadContext.put("mdcField1", "my mdc value"); < < logger.info("Blubb Test"); < assertEquals(1, GelfTestSender.getMessages().size()); < < GelfMessage gelfMessage = GelfTestSender.getMessages().get(0); < < assertEquals("my mdc value", gelfMessage.getField("mdcField1")); < < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/test/java/org/apache/logging/log4j/gelf/appender/GelfTestSender.java empty/src/test/java/org/apache/logging/log4j/gelf/appender/GelfTestSender.java 1,27d0 < package org.apache.logging.log4j.gelf.appender; < < import java.util.ArrayList; < import java.util.List; < < /** < */ < public class GelfTestSender implements GelfSender { < private static List messages = new ArrayList(); < < @Override < public boolean sendMessage(GelfMessage message) { < synchronized (messages) { < messages.add(message); < } < return true; < } < < @Override < public void close() { < < } < < public static List getMessages() { < return messages; < } < } diff -r --unidirectional-new-file -N log4j-gelf/src/test/resources/log4j2-minimal.xml empty/src/test/resources/log4j2-minimal.xml 1,19d0 < < < < < < < < < < < < < < < < < \ No newline at end of file diff -r --unidirectional-new-file -N log4j-gelf/src/test/resources/log4j2.xml empty/src/test/resources/log4j2.xml 1,31d0 < < < < < < < < < < < < < < < < < < < < < < < < < < < < < \ No newline at end of file