Coder Social home page Coder Social logo

logback-gelf's Introduction

logback-gelf

A Logback appender that encodes logs to GELF and transports them to Graylog servers.

Disclaimer: This repo is no longer maintained as of v0.3 as I've stopped using Graylog (different job). Please reach out at [email protected] if you wish to take over the repo. Some alternative GELF appenders for logback are listed below

Dependency information

Latest version:

<dependency>
  <groupId>me.moocar</groupId>
  <artifactId>logback-gelf</artifactId>
  <version>0.3</version>
</dependency>

Features

  • Append via TCP or UDP (with chunking) to a remote graylog server
  • MDC k/v converted to fields
  • Fields may have types
  • Auto include logger_name
  • Auto include Markers
  • Auto include Thread name
  • Static fields (E.g facility)
  • Very Few dependencies (Logback and GSON)

Configuring Logback

Note, 0.2 is a breaking version. It is NOT compatible with 0.12 and previous versions. Read about the changes here

The minimal possible logback.xml you can write is something like.

<configuration>
    <appender name="GELF UDP APPENDER" class="me.moocar.logbackgelf.GelfUDPAppender">
        <encoder class="me.moocar.logbackgelf.GZIPEncoder">
            <layout class="me.moocar.logbackgelf.GelfLayout"/>
        </encoder>
    </appender>
   <root level="debug">
    <appender-ref ref="GELF UDP APPENDER" />
  </root>
</configuration>

A more complete example that shows how you would overwrite many default values:

<configuration>
    <!--Use TCP instead of UDP-->
    <appender name="GELF TCP APPENDER" class="me.moocar.logback.net.SocketEncoderAppender">
        <remoteHost>somehost.com</remoteHost>
        <port>12201</port>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="me.moocar.logbackgelf.GelfLayout">
                <!--An example of overwriting the short message pattern-->
                <shortMessageLayout class="ch.qos.logback.classic.PatternLayout">
                    <pattern>%ex{short}%.100m</pattern>
                </shortMessageLayout>
                <!-- Use HTML output of the full message. Yes, any layout can be used (please don't actually do this)-->
                <fullMessageLayout class="ch.qos.logback.classic.html.HTMLLayout">
                    <pattern>%relative%thread%mdc%level%logger%msg</pattern>
                </fullMessageLayout>
                <useLoggerName>true</useLoggerName>
                <useThreadName>true</useThreadName>
                <useMarker>true</useMarker>
                <host>Test</host>
                <additionalField>ipAddress:_ip_address</additionalField>
                <additionalField>requestId:_request_id</additionalField>
                <includeFullMDC>true</includeFullMDC>
                <fieldType>requestId:long</fieldType>
                <!--Facility is not officially supported in GELF anymore, but you can use staticFields to do the same thing-->
                <staticField class="me.moocar.logbackgelf.Field">
                  <key>_facility</key>
                  <value>GELF</value>
                </staticField>
            </layout>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="GELF TCP APPENDER" />
    </root>
</configuration>

GelfLayout

me.moocar.logbackgelf.GelfLayout

This is where most configuration resides, since it's the part that actually converts a log event into a GELF compatible JSON string.

  • useLoggerName: If true, an additional field call "_loggerName" will be added to each gelf message. Its contents will be the fully qualified name of the logger. e.g: com.company.Thingo. Default: false
  • useThreadName: If true, an additional field call "_threadName" will be added to each gelf message. Its contents will be the name of the thread. Default: false
  • host The hostname of the host from which the log is being sent. Displayed under source on web interface. Default: getLocalHostName()
  • useMarker: If true, and the user has set a slf4j Marker on their log, then the marker.toString() will be added to the gelf message as the field "_marker". Default: false
  • shortMessageLayout: The Layout used to create the gelf short_message field. Shows up in the message column of the log summary in the web interface. Default: "%ex{short}%.100m" (PatternLayout)
  • fullMessageLayout: The Layout used to create the gelf full_message field. Shows up in the message field of the log details in the web interface. Default: "%rEx%m" (PatternLayout)
  • additionalFields: See additional fields below. Default: empty
  • fieldType: See field type conversion below. Default: empty (fields sent as string)
  • staticFields: See static fields below. Note, now that facility is deprecated, use this to set a facility Default: empty
  • staticAdditionalFields: deprecated. Use staticFields. Default: empty
  • includeFullMDC: See additional fields below. Default: false

Transports

Both UDP and TCP transports are supported. UDP is the recommended graylog transport.

UDP

UDP can be configured using the me.moocar.logbackgelf.GelfUDPAppender appender. Once messages reach a certain size, they will be chunked according to the gelf spec. A maximum of 128 chunks can be sent per log. If the encoded log is bigger than that, the log will be dropped. Assuming the default 512 max packet size, this allows for 65536 bytes (64kb) total per log message (unzipped).

  • remoteHost: The remote graylog server host to send log messages to (DNS or IP). Default: "localhost"
  • port: The remote graylog server port. Default: 12201
  • maxPacketSize: The maximum number of bytes per datagram packet. Once the limit is reached, packets will be chunked. Default: 512

GZIP

For UDP, you have the option of Gzipping the Gelf JSON before sending over UDP. To do this, replace the ch.qos.logback.core.encoder.LayoutWrappingEncoder encoder with the me.moocar.logbackgelf.GZIPEncoder encoder. E.g

<appender name="GELF UDP APPENDER" class="me.moocar.logbackgelf.GelfUDPAppender">
    <encoder class="me.moocar.logbackgelf.GZIPEncoder">
        <layout class="me.moocar.logbackgelf.GelfLayout"/>
    </encoder>
</appender>

Remember, The GZIP encoder should NOT be used with TCP

TCP

TCP transport can be configured using the me.moocar.logback.net.SocketEncoderAppender appender. Unfortunately, the built in Logback Socket Appender doesn't give you control of how logs are encoded before being sent over TCP, which is why you have to use this appender. To make the system as flexible as possible, I moved this new appender into its own library. Note that due to an unresolved Graylog issue, GZIP is not supported when using TCP.

<appender name="GELF TCP APPENDER" class="me.moocar.logback.net.SocketEncoderAppender">
    <port>12201</port>
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="me.moocar.logbackgelf.GelfLayout">
            ....
        </layout>
    </encoder>
</appender>
  • remoteHost: The remote graylog server host to send log messages to (DNS or IP). Default: "localhost"
  • port: The remote graylog server port. Required.
  • maxPacketSize: The number of logs to keep in memory while the graylog server can't be reached. Default: 128
  • acceptConnectionTimeout: Milliseconds to wait for a connection to be established to the server before failing. Default: 1000

Extra features

Additional Fields

Additional Fields are extra k/v pairs that can be added to the GELF json, and thus searched as structured data using graylog. In the slf4j world, MDC (Mapped Diagnostic Context) is an excellent way of programmatically adding fields to your GELF messages.

Let's take an example of adding the ip address of the client to every logged message. To do this we add the ip address as a key/value to the MDC so that the information persists for the length of the request, and then we inform logback-gelf to look out for this mapping every time a message is logged.

  1. Store IP address in MDC
// Somewhere in server code that wraps every request
...
org.slf4j.MDC.put("ipAddress", getClientIpAddress());
...
  1. Inform logback-gelf of MDC mapping
<layout class="me.moocar.logbackgelf.GelfLayout">
    <additionalField>ipAddress:_ip_address</additionalField>
</layout>

If the property includeFullMDC is set to true, all fields from the MDC will be added to the gelf message. Any key, which is not listed as additionalField will be prefixed with an underscore. Otherwise the field name will be obtained from the corresponding additionalField mapping.

If the property includeFullMDC is set to false (default value) then only the keys listed as additionalField will be added to a gelf message.

Static Fields

Use static additional fields when you want to add a static key value pair to every GELF message. Key is the additional field key (and should thus begin with an underscore). The value is a static string.

Now that the GELF facility is deprecated, this is how you add a static facility. StaticFields replace staticAdditionalFields

E.g in the appender configuration:

<layout class="me.moocar.logbackgelf.GelfLayout">
  <staticField class="me.moocar.logbackgelf.Field">
    <key>_facility</key>
    <value>GELF</value>
  </staticField>
  <staticField class="me.moocar.logbackgelf.Field">
    <key>_node_name</key>
    <value>www013</value>
  </staticField>
</layout>

Static Additional Fields (deprecated)

Static Additional fields have been deprecated and superceded by staticFields. While they offered a more concise way of expressing the key/value pair, it was impossible to include a colon in the value. staticFields are fully structured and don't have this problem.

Field type conversion

You can configure a specific field to be converted to a numeric type. Key is the additional field key as inserted into the MDC, value is the type to convert to. Currently supported types are int, long, float and double.

<layout class="me.moocar.logbackgelf.GelfLayout">
    <additionalField>requestId:_request_id</additionalField>
    <fieldType>requestId:long</fieldType>
</layout>

If the conversion fails, logback-gelf will leave the field value alone (i.e.: send it as String) and print the stacktrace

Tests in Clojure

Logback-gelf tests are written in Clojure. I could try and justify this by saying that the tests are better than they were in java, which is true, but mostly it's because I love Clojure and have been using it in my day job for over 3 years. I'm aware this will make it harder for others to submit PRs, and that pains me a little, but look, treat it as an exercise. Clojure will make you a better programmer.

The good news is that running the tests is just as easy as before. Simply run mvn test.

The other good news, is that we're now using generative testing via test.check. Tests are generated based on specs and then properties are asserted. It means that much more of the possible value space is tested.

If you want to test interactively, you can start a repl using mvn clojure:repl, or if you want to connect via nrepl, use mvn clojure:nrepl

V0.2 Changes

In logback-gelf v0.2, configuration has been reworked to fit better into the logback ecosystem. The primary driver was adding TCP transport. Under 0.12 configuration, a transport option would have been added to the main appender, but then there would be no logical place to put TCP specific configuration such as connectTimeout. UDP also has its own quirks, requiring chunking and the option of GZIP.

So the new configuration follows the logback way and provides both UDP and TCP appenders, and the GELF serialization logic is now in a GelfLayout. This required a significant refactor but will provide more flexibility going forward. For example, adding a Kafka or AMPQ appender should now be trivial, and you won't even need to modify this library.

Because it's such a big change, I deliberately broke backwards compatibility. Here's a list of all the changes:

  • me.moocar.logbackgelf.GelfAppender has been removed and replaced with me.moocar.logbackgelf.GelfUDPAppender and me.moocar.logback.net.SocketEncoderAppender (all non transport configuration is now under the GelfLayout Layout)
  • graylog2ServerHost is now GelfUDPAppender.remoteHost or SocketEncoderAppender.remoteHost
  • graylog2ServerPort is now GelfUDPAppender.port or SocketEncoderAppender.port
  • facility is deprecated in GELF 1.1, so I've removed it. It can be added using Static Additional Fields.
  • hostName is now host (to be inline with Gelf spec)
  • graylog2ServerVersion no longer exists since it's assumed that you are using graylog 1.0 or above.
  • chunkThreshold is now GelfUDPAppender.maxPacketSize and the default is 512 bytes.
  • messagePattern is now fullMessageLayout and is no longer assumed to be a PatternLayout, rather it is a generic Layout, giving you full flexibility over how a message string is transformed. For example, if you really wanted, you could use a XML or HTML layout.
  • shortMessagePattern same as above. Note that auto truncation no longer occurs. You must now describe how to format the log message using Layouts.
  • Testing is now in Clojure

Change Log

  • Development version 0.4-SNAPSHOT (current Git master)
  • Release [0.3] on 2016-Jan-19
    • Add Structured Static Fields #57
  • Release [0.2beta3] on 2015-May-31
    • Handle IO errors in UDP appender #54
  • Release [0.2beta2] on 2015-Apr-06
    • added clojars repository
    • added TCP socket encoder to dependencies
  • Release [0.2beta1] on 2015-Apr-05
    • Breaking change version
    • Refactor to support multiple appenders
    • UDP config now under GelfUDPAppender
    • View complete changes
  • Release [0.12] on 2014-Nov-04
    • Explicitly set Zipper string encoding to UTF-8 #41
  • Release [0.11] on 2014-May-18
    • Added field type conversion #30
    • Use FQDN or fallback to hostname #32
    • Update dependencies #36
    • Remove copyright notice on InternetUtils #38
    • Better testing of line and file in exceptions #34
  • Release [0.10p2] on 2014-Jan-12
    • Added hostName property #28
    • Reverted Windows timeout #29

logback-gelf's People

Contributors

amir343 avatar athou avatar captaininspiration avatar danieljamesscott avatar e-tothe-ipi avatar guw avatar ibuildthecloud avatar lijsselstein avatar moocar avatar quhw avatar solidjb avatar timclemons avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

logback-gelf's Issues

GelfAppender class not found in tomcat

I downloaded logback-gelf-0.9.6-jar-with-dependencies.jar and put it in my tomcat's shared lib folder, and created a symlink for "logback-gelf.jar".

I then added an appender as per the logback-gelf readme, and restarted tomcat.

Once it did restart, instead of getting logs sent to my graylog2 server, I started getting stack traces in catalina.out.

What am I missing or doing wrong?

Thank you.

My appender is:

<appender name="GELF" class="me.moocar.logbackgelf.GelfAppender">
  <facility>${contextName}</facility>
    <graylog2ServerHost>MyGraylog2Server</graylog2ServerHost>
    <graylog2ServerPort>12201</graylog2ServerPort>
    <useLoggerName>true</useLoggerName>
    <useThreadName>true</useThreadName>
    <graylog2ServerVersion>0.9.6</graylog2ServerVersion>
    <chunkThreshold>1000</chunkThreshold>
</appender>

Stacktrace snippets follow:

09:29:34,049 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [me.moocar.logbackgelf.GelfAppender]
09:29:34,049 |-ERROR in ch.qos.logback.core.joran.action.AppenderAction - Could not create an Appender of type [me.moocar.logbackgelf.GelfAppender]. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type me.moocar.logbackgelf.GelfAppender
at ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type me.moocar.logbackgelf.GelfAppender

Caused by: java.lang.ClassNotFoundException: me.moocar.logbackgelf.GelfAppender

at ... 57 common frames omitted
09:29:34,050 |-ERROR in ch.qos.logback.core.joran.spi.Interpreter@19:68 - ActionException in Action for tag [appender] ch.qos.logback.core.joran.spi.ActionException: ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type me.moocar.logbackgelf.GelfAppender
at ch.qos.logback.core.joran.spi.ActionException: ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type me.moocar.logbackgelf.GelfAppender

Caused by: ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type me.moocar.logbackgelf.GelfAppender

at ... 55 common frames omitted
Caused by: java.lang.ClassNotFoundException: me.moocar.logbackgelf.GelfAppender

at ... 57 common frames omitted

NPE when there is no callerData

I am building the log forwarder which forwards the LoggingEventVO to a GelfAppender. But the event has no callerData, so that the GelfConverter does not work.

We should check if hasCallerData before using it.

private void stackTraceField(Map<String, Object> map, ILoggingEvent eventObject) {
    IThrowableProxy throwableProxy = eventObject.getThrowableProxy();
    if (throwableProxy != null ) {
        StackTraceElementProxy[] proxyStackTraces = throwableProxy.getStackTraceElementProxyArray();
        if (proxyStackTraces != null && proxyStackTraces.length > 0) {
            StackTraceElement[] callStackTraces = eventObject.getCallerData();
            if (callStackTraces.length > 0) {
                StackTraceElement lastStack = callStackTraces[0];
                map.put("file", lastStack.getFileName());
                map.put("line", String.valueOf(lastStack.getLineNumber()));
            }
        }
    }
}

Setting a pattern

Is it possible to set a pattern, and if so, what is the syntax? We've tried to add this to the appender...

       <layout class="ch.qos.logback.classic.PatternLayout">            <pattern> %d{HH:mm:ss.SSS} %contextName [%t] %level %logger{36} - %msg%n </pattern>        </layout>

and this:

            <pattern>
                %d{HH:mm:ss.SSS} %contextName [%t] %level %logger{36} - %msg%n
            </pattern>
        </encoder>```

but with no joy. Basically we're trying to pass through our contextName to make sure it comes out when it is centrally logged. There are a number of apps deployed in the same server so we wanted to distinguish where the log has come from.

Many thanks

Sending under Windows fails due to new loopback

When I run the appender on my local Windows machine, it operates like it is sending messages but they are never received by a remote graylog2 server. When I removed the line:
private final SocketAddress loopbackAddress = new InetSocketAddress("localhost", 0);
which was just added in the most recent commit (and just used DatagramSocket's no-arg constructor), it worked just fine.

I also changed the code so that it wouldn't create,use and close a DatagramSocket each time. Instead it opens one and caches it for all subsequent sends. Like this:

private DatagramSocket getDatagramSocket() {
try {
if(datagramSocket == null) {
datagramSocket = new DatagramSocket();
}
return datagramSocket;
} catch (SocketException ex) {
throw new RuntimeException(ex);
}
}

I'm sure the loopbackAddress was added for a reason, but...

Redis support

I am totally new to GELF land and I would like to evaluate GELF with Logstash. In our scenario our application servers will log their output to Redis. Is there any support for logging to Redis with GELF?

sl4j Warnings with 1.6.4

When using logback-gelf with slf4j 1.6.4, i have some warnings like :

SLF4J: The following loggers will not work because they were created
SLF4J: during the default configuration phase of the underlying logging system.
SLF4J: See also http://www.slf4j.org/codes.html#substituteLogger
SLF4J: me.moocar.logbackgelf.GelfConverter

It's due to the class GelfConverter who use a private final Logger logger = LoggerFactory.getLogger(this.getClass());

If a remove the call to the logger, i don't have any more warnings.

Sorry for my bad english :)

Allow use logback-access with logback-gelf

Hello,

I'm trying to use logback-gelf with logback-access [ jetty ] to send compressed gelf message to logstash server on UDP port.

I was looking a way to configure this but appears to be not possible.

Do you have in mind implement this in a short period?

Thanks

XML configuration

Hi, and thank you for your project.

You explain how to setup logback gelf in groovy, but not in XML, and i've have an issue with the additionalField parameter.

        <appender name="GELF" class="me.moocar.logbackgelf.GelfAppender">
            <graylog2ServerHost>localhost</graylog2ServerHost>
            <graylog2ServerPort>12201</graylog2ServerPort>
            <useLoggerName>true</useLoggerName>
            <graylog2ServerVersion>0.9.5</graylog2ServerVersion>
            <additionalFields>
                <app>${APP:-AppNotSet}</app>
            </additionalFields>
        </appender>

In this way additonalField are not taken into account. I got the error :

23:47:31,364 |-ERROR in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Could not find an appropriate class for property [additionalFields]

Do you know how it could be done ?

Thank you.

Startup suceeds even if exception is thrown

In GelfAppender.initExecutor, let's say an exception is thrown. (This isn't the bug, but I don't see any logging of this, perhaps a sysout can be added?)

But in start(), when initExecutor() was called, super.start() has already been called, which means that the startup was successful.

The order of the two statements in start() should be reversed, like this:

@OverRide
public void start() {
initExecutor();
super.start();
}

so that start() won't be called when exception occurs.

Error initializing static fields

Hi,

I'm using the template from the README.md, but my logger fails to initialize the static fields. The error message is:

-ERROR in ch.qos.logback.core.joran.spi.Interpreter@38:66 - no applicable action for [staticField], current ElementPath  is [[configuration][appender][encoder][layout][staticField]]
-ERROR in ch.qos.logback.core.joran.spi.Interpreter@39:24 - no applicable action for [key], current ElementPath  is [[configuration][appender][encoder][layout][staticField][key]]
-ERROR in ch.qos.logback.core.joran.spi.Interpreter@40:26 - no applicable action for [value], current ElementPath  is [[configuration][appender][encoder][layout][staticField][value]]

The fields are not available in graylog2.

part of my prod-logger.xml

<appender name="GELF UDP APPENDER" class="me.moocar.logbackgelf.GelfUDPAppender">
   ...
   <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
      <layout class="me.moocar.logbackgelf.GelfLayout">
         ...
         <staticField class="me.moocar.logbackgelf.Field">
            <key>_environment</key>
            <value>prod</value>
         </staticField>
      </layout>
   </encoder>
</appender>

My library dependencies

  • "ch.qos.logback" % "logback-core" % "1.1.2"
  • "ch.qos.logback" % "logback-classic" % "1.1.2"
  • "org.slf4j" % "slf4j-api" % "1.7.6"
  • "me.moocar" % "logback-gelf" % "0.2"

no colons supported in property values

would be nice to be able to have properties with colons (":") in it (eg: url).

Currrently not supported (v0.12), IllegalArgumentException is thrown:
"staticAdditionalField must be of the format key:value, where key is the additional field key (therefore should have a leading underscore), and value is a static string. e.g. _node_name:www013"

Chuncking issue

Hi,
we are using graylog2 (0.20.x) and will move to 1.x really soon but we noticed that we are not able to send message bigger than the chuncktreshold(they get "lost"). On this site https://www.graylog.org/resources/gelf-2/ its said the library should be sending "1.1" as version and various other elements for the chucking to work.
Can this library work with newer version than 0.9.6 ?

Regards,
Cloon_

Question: no exception or message if graylog2 server unreachable

I use logback-gelf send log to graylog2, all the things are good but I know nothing if the graylog2 server unreachable. can you give some suggestion?

and how to debug if I send a message, log out in my client console, but graylog2 server get nothing.
for example:
I change the configuration as follows: (want to display java naming conversion in graylog2)
<additionalField>applicationId:_applicationId</additionalField>

thanks a lot.

====================
me.moocar:logback-gelf:0.12
Graylog v2.4.3+2c41897

Unexpected IO failure

We had just experienced this error on projects using 0.2beta2 version, and not on projects communicating with same gl2 server with 0.1x versions of gelf appender. After this error, logs were no longer sent to gl2 server (though connection was just fine).

08:23:54,482 |-ERROR in me.moocar.logbackgelf.GelfUDPAppender[graylogComm] - IO failure in appender java.net.PortUnreachableException: ICMP Port Unreachable
    at java.net.PortUnreachableException: ICMP Port Unreachable
    at  at java.net.PlainDatagramSocketImpl.send(Native Method)
    at  at java.net.DatagramSocket.send(Unknown Source)
    at  at me.moocar.logbackgelf.GelfChunkingOutputStream.sendBytes(GelfChunkingOutputStream.java:175)
    at  at me.moocar.logbackgelf.GelfChunkingOutputStream.flush(GelfChunkingOutputStream.java:149)
    at  at ch.qos.logback.core.encoder.LayoutWrappingEncoder.doEncode(LayoutWrappingEncoder.java:137)
    at  at ch.qos.logback.core.OutputStreamAppender.writeOut(OutputStreamAppender.java:194)
    at  at me.moocar.logbackgelf.GelfUDPAppender.writeOut(GelfUDPAppender.java:96)
    at  at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:219)
    at  at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:103)
    at  at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:88)
    at  at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
    at  at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:273)
    at  at ch.qos.logback.classic.Logger.callAppenders(Logger.java:260)
    at  at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:442)
    at  at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:396)
    at  at ch.qos.logback.classic.Logger.info(Logger.java:600)
    at  at ...

Sending root exception

Hi,

Is it possible to have an option to send the root exception like the pattern %rEx ?
See http://logback.qos.ch/manual/layouts.html#rootException

Maybe in the GelfConverter at ligne 80, you could iterate over all getCause(), something like that

StringBuffer message = new StringBuffer() while (proxy != null ) buffer.append(proxy.getClassName() + ": " + proxy.getMessage() + "\n" + toStackTraceString(proxy.getStackTraceElementProxyArray())); proxy=proxy.getCause(); }

Thanks

How to install for a Java newbie

Hello!

I'm running DataStax Enterprise 4.7, which is a packaged commercial version of Cassandra. As of 4.7, it looks like the whole thing switched from log4j to logback. If I wanted to use this GELF appender, how would I go about dropping this in?

I was assuming I'd need to compile this somehow and drop it into a my classpath, but wasn't sure how to get started on the former (my background is primarily Python-oriented). Do you have any suggestions as far as how to proceed? It seems like this is exactly what I'm looking for, so I'd love to use it.

Log messages sent from logback appender appear to be garbled

The following is from graylog2's debug log when I set up logback-gelf.

2013-04-01 15:34:06,266 INFO : org.graylog2.inputs.syslog.SyslogProcessor - Syslog message is missing date or date could not be parsed. (Possibly set allow_override_syslog_date to true) Not further handling. Message was: ï¿ï¿½ï¿½AK�@��ʲ�l�61���Pï¿x�߼?J��J��4Ee¿½ï¿½ï¿½"�9L��L{�����*��3���z���gp��"����Ð
��MSVMQgRG=�_�Z�6�c�=�=� ���Qw�)����h$&���!F�>D��Q��0��m���%�Z��iÆ$Y6/��7ÔJ��
2013-04-01 15:34:06,266 ERROR: org.graylog2.inputs.syslog.SyslogProcessor - Could not parse syslog message. Not further handling.
java.lang.IllegalStateException

I've captured the message being sent using Wireshark on the machine that is sending the message and it appears to be completely garbled as well there.

I also have been getting error messages on start up if I have shortMessagePattern, staticAdditionalField, or includeFullMDC set up in my appender configuration.

Here's what I have right now:

<appender name="GELF" class="me.moocar.logbackgelf.GelfAppender">
    <facility>logback-gelf-test</facility>
    <graylog2ServerHost>devu01</graylog2ServerHost>
    <graylog2ServerPort>513</graylog2ServerPort>
    <useLoggerName>true</useLoggerName>
    <useThreadName>true</useThreadName>
    <graylog2ServerVersion>0.9.6</graylog2ServerVersion>
    <chunkThreshold>1000</chunkThreshold>
    <messagePattern>%m%rEx</messagePattern>
    <shortMessagePattern>%.-100(%m%rEx)</shortMessagePattern>
    <additionalField>ipAddress:_ip_address</additionalField>
    <additionalField>requestId:_request_id</additionalField>
    <staticAdditionalField>_node_name:www013</staticAdditionalField>
    <includeFullMDC>true</includeFullMDC>
</appender>

Sorry that this doesn't give you much to go on; if I have time I'll download the code and see if stepping through it tells me anything.

Appender reference is left null if local hostname cannot be resolved.

Repro steps

  1. Set the system's hostname to something not resolvable via DNS nor listed in the /etc/hosts file.
  2. Startup a webapp where the logback-gelf appender is listed in the logback.xml.
  3. Review the log.

Result

There will be multiple NPEs in the log as an exception is thrown during the call to GelfAppender.initExecutor() on the following line:

String hostname = InetAddress.getLocalHost().getHostName();

This leaves the appender reference null.

Expected result

If the local hostname cannot be resolve, used the IP address instead.

mvn build fails with unresolved dependency com.stuartsierra:component

This issue pertains to 0.2beta1.

Assuming you want to keep compatibility with using plain vanilla maven central.

Out of the box, it cannot be built because the following dependencies are not in maven central:

[ERROR] Failed to execute goal on project logback-gelf: Could not resolve dependencies for project me.moocar:logback-gelf:jar:0.2beta2-SNAPSHOT: The following artifacts could not be resolved: com.stuartsierra:component:jar:0.2.3, org.mockito:mockito-core:jar:1.10.9: Failure to find com.stuartsierra:component:jar:0.2.3 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]

org.mockito:mockito-core:jar:1.10.9 is an easy fix... I just replaced it with 1.10.19.
com.stuartsierra:component:jar:0.2.3 is not in maven central, but rather in clojars or something.

Maybe you can add a section to the readme on how you have maven set up to get the build to succeed?

Invalid repository URL

The repository URL seems to be not working anymore.

In the readme, under "Add the following repository to your pom.xml or settings.xml", it says that the maven repository URL is: http://moocar.me/maven2

<repositories>
        <repository>
            <releases><enabled>true</enabled></releases>
            <id>Moocar</id>
            <url>http://moocar.me/maven2</url>
        </repository>
</repositories>

If you open this URL in a browser, this redirects to http://zerply.com/Moocarmaven2 and a message "Profile Not Found" appears.

support for 0.10

Hi,
We are using Server version: 0.10.0 in our production deployment. i tried by specifying
0.10.0
in the appender configuration. It works for some cases , but in the rest of cases i get the following error

2013-06-10 13:58:47,023 WARN : org.graylog2.inputs.gelf.GELFDispatcher - Could not handle GELF message.
java.lang.IllegalStateException: Could not extract sequence number
at org.graylog2.gelf.GELFMessageChunk.extractSequenceNumber(GELFMessageChunk.java:132)
at org.graylog2.gelf.GELFMessageChunk.read(GELFMessageChunk.java:107)
at org.graylog2.gelf.GELFMessageChunk.(GELFMessageChunk.java:77)
at org.graylog2.gelf.GELFMessageChunk.(GELFMessageChunk.java:81)

2013-06-10 13:58:47,519 DEBUG: org.graylog2.gelf.GELFChunkManager - Dumping GELF chunk map [4]:
Message <5fe3a6c91e282fe5> Chunks:
ID: 5fe3a6c91e282fe5 Sequence: 74/14 Arrival: 1370887125 Data size: 1038
Message <5b6c72af050dc21c> Chunks:
ID: 5b6c72af050dc21c Sequence: 25/112 Arrival: 1370887126 Data size: 1038
Message <611cfe1079577f74> Chunks:
ID: 611cfe1079577f74 Sequence: 79/92 Arrival: 1370887127 Data size: 1038
Message Chunks:
ID: d290ba683ae20c47 Sequence: 25/27 Arrival: 1370887125 Data size: 1038

2013-06-10 13:58:47,519 DEBUG: org.graylog2.gelf.GELFChunkManager - Message <5fe3a6c91e282fe5> does not even contain first chunk. Not complete!
2013-06-10 13:58:47,519 DEBUG: org.graylog2.gelf.GELFChunkManager - Message <5b6c72af050dc21c> does not even contain first chunk. Not complete!
2013-06-10 13:58:47,519 DEBUG: org.graylog2.gelf.GELFChunkManager - Message <611cfe1079577f74> does not even contain first chunk. Not complete!
2013-06-10 13:58:47,519 DEBUG: org.graylog2.gelf.GELFChunkManager - Message does not even contain first chunk. Not complete!

So i am assuming this issue is due to the header format inconsistencies as outlined in other mailing lists.

Is there an ETA to add support for 0.10.0
-thanks
-venkat

NPE in GelfAppender.append kills the host app

Using these dependencies:

ch.qos.logback.logback-core 1.1.2
ch.qos.logback.logback-classic 1.1.2
me.moocar.logback-gelf 0.12
com.google.code.gson.gson 2.2.4

I somehow managed to product this stacktrace:

java.lang.NullPointerException
at me.moocar.logbackgelf.GelfAppender.append(GelfAppender.java:60)
at me.moocar.logbackgelf.GelfAppender.append(GelfAppender.java:21)
at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:85)
at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:273)
at ch.qos.logback.classic.Logger.callAppenders(Logger.java:260)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:442)
at ch.qos.logback.classic.Logger.filterAndLog0Or3Plus(Logger.java:396)
at ch.qos.logback.classic.Logger.debug(Logger.java:503)

And it killed my app.

I can see that the try/catch in GelfAppender.append re-throws the exception. Should it now swallow it?

Copyright notice in InternetUtils?

The copyright notice in InternetUtils is rather off putting, and seems to contradict the Apache license in the LICENSE file.

OCLC proprietary information: the enclosed materials contain proprietary information of OCLC Online Computer Library Center, Inc. and shall not be disclosed in whole or in any part to any third party or used by any person for any purpose, without written consent of OCLC, Inc.

Strange versioning of releases

I wonder why version 0.12 comes before 0.2. If it would be 0.1.2 and 0.2 it would be clear, but with the current schema it is confusing not just for me, but for Gradle as well. If you use something like 0.+ as version number in the dependencies, it picks up 0.12 and not 0.2.
What do you think about using semantic versioning (http://semver.org/spec/v2.0.0.html), which is a nice standard, in my opinion?

<fieldType> uses MDC name, not ES field name

The documentation shows:
requestId:_request_id
_request_id:long
Based on how the code looks and what I was able to get to work, should use the MDC key value, which in this case would be "requestId", not the ElasticSearch field name.

Feature Request: JMS or AMQP transport

Now that there is native support for AMPQ support in GrayLog, it would be really neat to be able to log messages using this technology.

JMS and AMPQ both have their advantages and disadvantages... JMS is protocol independent, so it'd run on a wide variety of Java platforms and servers. The other advantage is that this could like be implemented using provided dependencies, meaning that logback-gelf wouldn't bring in any transitive baggage. Since the server manages the connections, no connection information is specified in the configuration, just a target queue. The disadvantage, well its JNDI lookups. They're terrible. Example: http://grepcode.com/file/repo1.maven.org/maven2/ch.qos.logback/logback-classic/0.9.19/ch/qos/logback/classic/net/JMSQueueAppender.java#92

AMQP is a wire level protocol, so while would likely need a compile dependency on a Java AMQP library, this frees you from having to use a traditional Java server like tomcat, Glassfish, TomEE, Wildfly. You could connect straight to the server, but that means logging information is stored on a per application basis, which for some environments may pose a flexibility problem.

Thanks for listening :) And great work on this implementation, it's awesome.

Inconsistent field type conversion

Hi,

In my humble opinion, there is an inconsistent within the treatment of the field type conversion.

The doc says:
"You can configure a specific field to be converted to a numeric type. Key is the additional field key (and should thus begin with an underscore), value is the type to convert to. Currently supported types are int, long, float and double."

But this is only true when you set the flag "includeFullMDC" to true.

If you don't set the explicit flag, and you create explicit mapping for additional fields, then the field type conversion is in the form:

requestId:_request_id
requestId:long

I think that this could be easily changed with a minimun change in the file GelfConverter.java to unified criteria:
Proposed change (line 202)
Replace:
map.put(additionalFields.get(key), convertFieldType(field, key));
With:
map.put(additionalFields.get(key), convertFieldType(field, additionalFields.get(key)));

Another aproach could be:

Replace (line 193 and line 195)
map.put(additionalFields.get(e.getKey()), convertFieldType(e.getValue(), additionalFields.get(e.getKey())));
map.put("" + e.getKey(), convertFieldType(e.getValue(), "" + e.getKey()));

With
map.put(additionalFields.get(e.getKey()), convertFieldType(e.getValue(), e.getKey()));
map.put("_" + e.getKey(), convertFieldType(e.getValue(), e.getKey()));

But this impies also changing the main doc page.

Feature request: Adding numeric field to a gelf message through logback

At the moment I don't see any way to (dynamically) add a numeric field (with a number, not with a string value) to a message logged through logback-gelf. This would be great to have, because it would allow us to filter, graph etc. these messages in graylog based on that numeric value (e.g. "only warnings for messages where _size > 500"). The MDC seems to be of no help, because it only takes String values for each key.

Any ideas if this is even remotely possible?

Problem with TCP appender

The TCP transport stays alive until it gets shut down explicitly, which LogBack obviously does not automatically. What to do?
Logback config

<appender name="GELF TCP APPENDER" class="me.moocar.logback.net.SocketEncoderAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
        <remoteHost>localhost</remoteHost>
        <port>12201</port>
        <acceptConnectionTimeout>100</acceptConnectionTimeout>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="me.moocar.logbackgelf.GelfLayout">
                <shortMessageLayout class="ch.qos.logback.classic.PatternLayout">
                    <pattern>%ex{short}%.100m</pattern>
                </shortMessageLayout>
                <useLoggerName>true</useLoggerName>
                <useThreadName>true</useThreadName>
                <useMarker>true</useMarker>
                <host>${app.env}</host>
                <includeFullMDC>true</includeFullMDC>
                <staticAdditionalField>application:${project.name}</staticAdditionalField>
            </layout>
        </encoder>
    </appender>

And Main class code

public class Main {

    private static Logger LOG = LoggerFactory.getLogger(Main.class);

    public static void main(String[] argv) {
        LOG.warn("ERROR");
    }
}

I've try to close connections by LgggerContext

LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.stop();

But none of that happened.

Transport is broken in Linux

Commit d810172 has seemed to have broken the Transport on linux. You get the following error:

java.lang.RuntimeException: java.io.IOException: Invalid argument
        at me.moocar.logbackgelf.Transport.sendPacket(Transport.java:61)
        at me.moocar.logbackgelf.Transport.send(Transport.java:35)
        at me.moocar.logbackgelf.AppenderExecutor.append(AppenderExecutor.java:40)
        at me.moocar.logbackgelf.GelfAppender.append(GelfAppender.java:56)
        at me.moocar.logbackgelf.GelfAppender.append(GelfAppender.java:21)
        at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:85)

Wrong IP address with ${HOSTNAME}

I have the following interfaces on a remote AWS machine:

$ ifconfig

docker0   Link encap:Ethernet  HWaddr 02:42:BB:13:E8:25
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

eth0      Link encap:Ethernet  HWaddr 0A:8C:15:E6:AF:9D
          inet addr:172.30.2.229  Bcast:172.30.2.255  Mask:255.255.255.0
          inet6 addr: fe80::88c:15ff:fee6:af9d/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:2741444 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1601099 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:3543604947 (3.3 GiB)  TX bytes:170417798 (162.5 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:51692380 errors:0 dropped:0 overruns:0 frame:0
          TX packets:51692380 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:3391639364 (3.1 GiB)  TX bytes:3391639364 (3.1 GiB)

My app however, is not using docker and is deployed by simply copying it to home directory and running from there. I set the host in logger.xml:

...
      <layout class="me.moocar.logbackgelf.GelfLayout">
        <host>${HOSTNAME} </host>
      </layout>
...

Now, I go to Graylog where I send my log messages and see docker's IP as the source: 172.17.0.1. Since all the instances that got docker running seem to have the same IP, I cannot really tell which instance is producing which messages! How can I get the eth0 IP? Or identify the host in some other way?

mention that input in the graylog server should be gelf udp

Great plugin 👍

It would be really useful if somewhere in readme.md you'd mention that logback-gelf creates upd gelf messages. I had to look in the sourcecode and figure out that it's creating datagrams and I should configure the graylog server to listen to upd (create a gelf upd input).

logback-gelf fails if gson is not in classpath

I am using https://github.com/downloads/Moocar/logback-gelf/logback-gelf-0.9.6.jar in a fresh Java maven project. I had to upload the jar in my own maven repository (nexus), because the jar is not available in any public maven repository yet.

On startup, I get the following error:

Failed to instantiate [ch.qos.logback.classic.LoggerContext]
Reported exception:
java.lang.NoClassDefFoundError: com/google/gson/GsonBuilder
at me.moocar.logbackgelf.GelfConverter.(GelfConverter.java:42)
at me.moocar.logbackgelf.GelfAppender.initExecutor(GelfAppender.java:86)
at me.moocar.logbackgelf.GelfAppender.start(GelfAppender.java:60)

In order to solve this, I had to add the following dependency to my pom.xml:

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.1</version>
</dependency>

Additional debug possibilities

One of my environment is not logging to graylog and I am not possible to analyse it what's happening inside logback and lockback-gelf. The logging configuration very similar to other environment. Only fields facility, hostName and staticAdditionalFields are different in configuration of logback-gelf.

Message are not sent form my app. They are no obstacles on the network, because I checked it

  1. I was not able to capture packets sent from my app to my graylog server: windump udp port 12212
  2. I sent successfully a test message via command-line from my machine to graylog
    echo {"version": "1.1","host":"simulation-machine.com","short_message":"A test message from simulation", "full_message":"Backtrace here\n\nmore stuff","level":1,"_user_id":9001,"_some_info":"foo","_some_env_var":"bar"} | ncat -vvv -w 1 -u graylog-machine.com 12212

Do you have suggestion how can I analyse cause of the problem?

integration tomcat-slf4j-logback with logback-gelf issue.

issue represent:
in $CATALINA_HOME/logs/catalina.out
[caused by: org.apache.juli.logging.ch.qos.logback.core.util.IncompatibleClassException]

root:

in tomcat-slf4j-logback package: https://github.com/grgrzybek/tomcat-slf4j-logback
change the "ch.qos.logback" to "org.apache.juli.logging.ch.qos.logback"

so to integrate tomcat-slf4j-logback with logback-gelf, we need change

[GelfAppender.java]

from
" import ch.qos.logback.core.AppenderBase;"
to
"org.apache.juli.logging.ch.qos.logback.core.AppenderBase;"

[GelfConverter.java]

from:
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.util.LevelToSyslogSeverity;

to:
import org.apache.juli.logging.ch.qos.logback.classic.LoggerContext;
import org.apache.juli.logging.ch.qos.logback.classic.PatternLayout;
import org.apache.juli.logging.ch.qos.logback.classic.spi.ILoggingEvent;
import org.apache.juli.logging.ch.qos.logback.classic.util.LevelToSyslogSeverity;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.