Version 3.13 of syslog-ng introduced a graylog2() destination and a GELF (Graylog Extended Log Format) template to make sending syslog messages to Graylog easier. You can also use them to forward simple name-value pairs where the name starts with a dot or underscore. If names of your name-value pairs include dots other than the first character, you should use JSON formatting directly instead of the GELF template and send logs to a raw tcp port in Graylog, which can then extract fields from nested JSON.

# Before you begin

The graylog2() destination was added in syslog-ng version 3.13. If you want to utilize the GELF template, you need to use this or a later version. Sending JSON formatted messages is possible with any recent syslog-ng versions. For my tests, I used a ready-to-go Graylog 2.3.2 virtual appliance and syslog-ng 3.13.2.

# Using the graylog2() destination

Starting with syslog-ng version 3.13, you can now send syslog messages to Graylog using the grayog2() destination. It uses the GELF template, the native data format of Graylog.

On the Graylog side, you have to configure a GELF TCP input.

On the syslog-ng side, configuration is also quite simple. All you need to configure is the name or IP address of the host running Graylog.

destination d_graylog {
graylog2(
host("172.16.146.142")
);
};

If you parsed your messages using syslog-ng, the template also forwards any name-value pairs where the name starts with a dot or underscore.

Note that if there is a dot in a field name other than the first character, syslog-ng creates nested JSON while formatting the message. Nested JSON is not automatically parsed in GELF messages.

# Sending nested JSON to Graylog

While sending nested JSON inside GELF is possible, it is not really convenient. If you make heavy use of parsing and normalization in syslog-ng and use dot notation in field names, you should rather use pure JSON instead of GELF to forward your messages.

On the Graylog side, create a new raw TCP input. Once it is ready, add a JSON extractor to it.

On the syslog-ng side, use a network destination combined with a template utilizing format-json:

destination d_jsontcp {
network(
"172.16.146.142"
port("5555")
transport(tcp)
template("\$(format-json --scope all-nv-pairs)\n")
);
};

You are now ready to query any of the fields sent to Graylog.