Search Results for: error 0

rsyslog 7.4.9 (v7-stable) released

We have just released 7.4.9 of the v7-stable branch.

While we initially did not intend to do another v7.4 release, we got some important fixes which we wanted to be available for 7.4, so we decided to do one more release. Note that also a new feature is included. The “processInternalMessages” global parameter now permits to tell rsyslog to send it’s own error messages to another system logger. This is most beneficial for systemd-based systems, where this permits rsyslog messages to show up in the service status command (but note that this requires configuration).

More detailed information is available in the ChangeLog.

ChangeLog:

http://www.rsyslog.com/changelog-for-7-4-9-v7-stable/

Download:

http://www.rsyslog.com/rsyslog-7-4-9-v7-stable/

As always, feedback is appreciated.

Best regards,
Florian Riedl

Changelog for 7.4.9 (v7-stable)

Version 7.4.9  [v7.4-stable] 2014-01-22

  • added ProcessInternalMessages global system parameter
    This permits to inject rsyslog status messages into *another* main syslogd or the journal.
  • bugfix: imuxsock input parameters were not accepted due to copy&paste error. Thanks to Andy Goldstein for the fix.
  • bugfix: potential double-free in RainerScript equal comparison happens if the left-hand operand is JSON object and the right-hand operand is a non-string that does not convert to a number (for example, it can be another JSON object, probably the only case that could happen in practice). This is very unlikely to be triggered.
  • bugfix: some RainerScript Json(Variable)/string comparisons were wrong

Parsing JSON (CEE) Logs and Sending them to Elasticsearch

Original post: Structured Logging with rsyslog and Elasticsearch via @sematext

When your applications generate a lot of logs, you’d probably want to make some sense of them through searches and statistics. Here’s when structured logging comes in handy, and I would like to share some thoughts and configuration examples of how you could use a popular syslog daemon like rsyslog to handle both structured and unstructured logs. Then I’ll show you how to:

  • take a JSON from a syslog message and index it in Elasticsearch (which eats JSON documents)
  • append other syslog properties (like the date) to the existing JSON to make a bigger JSON document that would be indexed in Elasticsearch. This is how we set up rsyslog to handle CEE-formatted messages in our log analytics tool, Logsene

On structured logging

If we take an unstructured log message, like:

Joe bought 2 apples

And compare it with a similar one in JSON, like:

{“name”: “Joe”, “action”: “bought”, “item”: “apples”, “quantity”: 2}

We can immediately spot a good and a bad point of structured logging: if we index these logs, it will be faster and more precise to search for “apples” in the “item” field, rather than in the whole document. At the same time, the structured log will take up more space than the unstructured one.

But in most use-cases there will be more applications that would log the same subset of fields. So if you want to search for the same user across those applications, it’s nice to be able to pinpoint the “name” field everywhere. And when you add statistics, like who’s the user buying most of our apples, that’s when structured logging really becomes useful.

Finally, it helps to have a structure when it comes to maintenance. If a new version of the application adds a new field, and your log becomes:

Joe bought 2 red apples

it might break some log-parsing, while structured logs rarely suffer from the same problem.

Enter CEE and Lumberjack: structured logging with syslog

With syslog, as defined by RFC3164, there is already a structure in the sense that there’s a priority value (severity*8 + facility), a header (timestamp and hostname) and a message. But this usually isn’t the structure we’re looking for.

CEE and Lumberjack are efforts to introduce structured logging to syslog in a backwards-compatible way. The process is quite simple: in the message part of the log, one would start with a cookie string “@cee:”, followed by an optional space and then a JSON or XML. From this point on I will talk about JSON, since it’s the format that both rsyslog and Elasticsearch prefer. Here’s a sample CEE-enhanced syslog message:

@cee: {“foo”: “bar”}

This makes it quite easy to use CEE-enhanced syslog with existing syslog libraries, although there are specific libraries like liblumberlog, which make it even easier. They’ve also defined a list of standard fields, and applications should use those fields where they’re applicable – so that you get the same field names for all applications. But the schema is free, so you can add custom fields at will.

CEE-enhanced syslog with rsyslog

rsyslog has a module named mmjsonparse for handling CEE-enhanced syslog messages. It checks for the “CEE cookie” at the beginning of the message, and then tries to parse the following JSON. If all is well, the fields from that JSON are loaded and you can then use them in templates to extract whatever information seems important. Fields from your JSON can be accessed like this: $!field-name. An example of how they can be used is shown here.

To get started, you need to have at least rsyslog version 6.6.0, and I’d recommend using version 7 or higher. If you don’t already have that, check out the repositories for RHEL/CentOS and Ubuntu.

Also, mmjsonparse is not enabled by default. If you use the repositories, install the rsyslog-mmjsonparse package. If you compile rsyslog from sources, specify –enable-mmjsonparse when you run the configure script. In order for that to work you’d probably have to install libjson and liblognorm first, depending on your operating system.

For a proof of concept, we can take this config:

#load needed modules
module(load="imuxsock") # provides support for local system logging
module(load="imklog") # provides kernel logging support
module(load="mmjsonparse") #for parsing CEE-enhanced syslog messages

#try to parse structured logs
*.* :mmjsonparse:

#define a template to print field "foo"
template(name="justFoo" type="list") {
  property(name="$!foo")
  constant(value="\n") #we'll separate logs with a newline
}

#and now let's write the contents of field "foo" in a file
*.* action(type="omfile"
           template="justFoo"
           file="/var/log/foo")

To see things, better, you can start rsyslog in foreground and in debug mode:

rsyslogd -dn

And in another terminal, you can send a structured log, then see the value in your file:

# logger ‘@cee: {“foo”:”bar”}’
# cat /var/log/foo
bar

If we send an unstructured log, or an invalid JSON, nothing will be added

# logger ‘test’
# logger ‘@cee: test2’
# cat /var/log/foo
bar

But you can see in the debug output of rsyslog why:

mmjsonparse: no JSON cookie: ‘test’
[…]
mmjsonparse: toParse: ‘ test2’
mmjsonparse: Error parsing JSON ‘ test2’: boolean expected

Indexing logs in Elasticsearch

To index our logs in Elasticsearch, we will use an output module of rsyslog called omelasticsearch. Like mmjsonparse, it’s not compiled by default, so you will have to add the –enable-elasticsearch parameter to the configure script to get it built when you run make. If you use the repositories, you can simply install the rsyslog-elasticsearch package.

omelasticsearch expects a valid JSON from your template, to send it via HTTP to Elasticsearch. You can select individual fields, like we did in the previous scenario, but you can also select the JSON part of the message via the $!all-json property. That would produce the message part of the log, without the “CEE cookie”.

The configuration below should be good for inserting the syslog message to an Elasticsearch instance running on localhost:9200, under the index “system” and type “events“.

#load needed modules
module(load="imuxsock") # provides support for local system logging
module(load="imklog") # provides kernel logging support
module(load="mmjsonparse") #for parsing CEE-enhanced syslog messages
module(load="omelasticsearch") #for indexing to Elasticsearch

#try to parse a structured log
*.* :mmjsonparse:

#define a template to print all fields of the message
template(name="messageToES" type="list") {
  property(name="$!all-json")
}

#write the JSON message to the local ES node
*.* action(type="omelasticsearch"
           template="messageToES")

After restarting rsyslog, you can see your JSON will be indexed:

# logger ‘@cee: {“foo”: “bar”, “foo2”: “bar2″}’
# curl -XPOST localhost:9200/system/events/_search?q=foo2:bar2 2>/dev/null | sed s/.*_source//
” : { “foo”: “bar”, “foo2”: “bar2” }}]}}

As for unstructured logs, $!all-json will produce a JSON with a field named “msg”, having the message as a value:

# logger test
# curl -XPOST localhost:9200/system/events/_search?q=test 2>/dev/null | sed s/.*_source//
” : { “msg”: “test” }}]}}

It’s “msg” because that’s rsyslog’s property name for the syslog message.

Including other properties

But the message isn’t the only interesting property. I would assume most would want to index other information, like the timestamp, severity, or host which generated that message.

To do that, one needs to play with templates and properties. In the future it might be made easier, but at the time of this writing (rsyslog 7.2.3), you need to manually craft a valid JSON to pass it to omelasticsearch. For example, if we want to add the timestamp and the syslogtag, a working template might look like this:

template(name="customTemplate"
   type="list") {
#- open the curly brackets,
#- add the timestamp field surrounded with quotes
#- add the colon which separates field from value
#- open the quotes for the timestamp itself
   constant(value="{\"timestamp\":\"")
#- add the timestamp from the log,
# format it in RFC-3339, so that ES detects it by default
   property(name="timereported" dateFormat="rfc3339")
#- close the quotes for timestamp,
#- add a comma, then the syslogtag field in the same manner
   constant(value="\",\"syslogtag\":\"")
#- now the syslogtag field itself
# and format="json" will ensure special characters
# are escaped so they won't break our JSON
   property(name="syslogtag" format="json")
#- close the quotes for syslogtag
#- add a comma
#- then add our JSON-formatted syslog message,
# but start from the 2nd position to omit the left
# curly bracket
   constant(value="\",")
   property(name="$!all-json" position.from="2")
}

Summary

If you’re interested in searching or analyzing lots of logs, structured logging might help. And you can do it with the existing syslog libraries, via CEE-enhanced syslog. If you use a newer version of rsyslog, you can parse these logs with mmjsonparse and index them in Elasticsearch with omelasticsearch.  If you are interested in indexing/searching logs in general, check out other Sematext logging posts or follow @sematext.

rsyslog 7.5.8 (v7-devel) released

This is a candidate for the 7.6.0 release. As such, it is probably the last v7-devel release. It contains a select few enhancements, with very limited bug potential as well as some bug fixes.

Users are suggested to try out this versions and report errors. If we don’t learn of serious problems, we will most probably release 7.6.0 next week based on this code here.

More detailed information is available in the changelog.

ChangeLog:

http://www.rsyslog.com/changelog-for-7-5-8-v7-devel/

Download:

http://www.rsyslog.com/rsyslog-7-5-8-v7-devel/

As always, feedback is appreciated.

Best regards,
Florian Riedl

Changelog for 7.4.8 (v7-stable)

Version 7.4.8  [v7.4-stable] 2014-01-08

  • rsgtutil provides better error messages on unfinished signature blocks
  • bugfix: guard against control characters in internal (error) messages
    Thanks to Ahto Truu for alerting us.
  • bugfix: immark did emit messages under kern.=info instead of syslog.=info
    Note that his can potentially break exisiting configurations that rely on immark sending as kern.=info. Unfortunately, we cannot leave this unfixed as we never should emit messages under the kern facilit

rsyslog statistic counter plugin omelasticsearch

Plugin – omelasticsearch

This plugin maintains global statistics, which accumulate all action instances. The statistic is named “omelasticsearch”. Parameters are:

  • submitted – number of messages submitted for processing (with both success and error result)
  • fail.httprequests – the number of times a http request failed. Note that a single http request may be used to submit multiple messages, so this number may be (much) lower than fail.http.
  • fail.http – number of message failures due to connection like-problems (things like remote server down, broken link etc)
  • fail.es – number of failures due to elasticsearch error reply; Note that this counter does NOT count the number of failed messages but the number of times a failure occured (a potentially much smaller number). Counting messages would be quite performance-intense and is thus not done.

The fail.httprequests and fail.http counters reflect only failures that omelasticsearch detected. Once it detects problems, it (usually, depends on circumstances) tell the rsyslog core that it wants to be suspended until the situation clears (this is a requirement for rsyslog output modules). Once it is suspended, it does NOT receive any further messages. Depending on the user configuration, messages will be lost during this period. Those lost messages will NOT be counted by impstats (as it does not see them).

Note that some previous (pre 7.4.5) versions of this plugin had different counters. These were experimental and confusing. The only ones really used were “submits”, which were the number of successfully processed messages and “connfail” which were equivalent to “failed.http”.

 

Back to statistics counter overview

action.execOnlyWhenPreviousIsSuspended preciseness

The “action.execOnlyWhenPreviousIsSuspended” parameter permits to conditionally execute an action only if the previous one is suspended. When an action actually gets suspended depends on the output module implementing the action, but the general rule is that an action suspends itself if there is a problem doing it’s job (e.g. a target server is down). This setting is generally used to implement failover destinations. So let’s call actions which have this attribute set “failover actions”.

Note that many action implement transactions to improve performance. If so, usually the success or error state of the action is only available after the transaction has been comitted. At this point, the messages have already been submitted to the action and the action could not set suspension state — simply because at that point everything looked fine. So when the failover action was about to be executed, the suspended flag was not set and the action not executed. Depending on system configuration, this can lead to loss of some messages during the failover process. If this seems totally unacceptable to you, you need to make sure that the transaction is committed after each message — this permits the output to obtain the actual success state (note that with some technologies, even this is not totally possible – a prime example is plain TCP syslog protocol).

To ensure commit of each message, the queue’s maximum batch size needs to be reduced to one. This can be done via the “queue.dequeuebatchsize” parameter. Note that reducing the batch size can have severe performance impact. Unfortunately, it is impossible to to have both high performance and precise failover actions. The simple reason is that for precise failover actions we need to know the result of the commit operation, which makes it necessary to do immediate commits.

Changelog for 7.5.6 (v7-devel)

Version 7.5.6 [devel] 2013-10-29

  • improved performance of RainerScript variable access
    by refactoring the whole body of variable handling code. This also
    solves some of the anomalies experienced in some versions of rsyslog.
    All variable types are now handled in unified code, including
    access via templates.
  • RainerScript: make use of 64 bit for numbers where available
    Thanks to Pavel Levshin for enhancement.
  • slight performance optimization if GCC is used
    We give branch prediction hints for the frequent RETiRet macro which is
    used for error handling. Some slight performance gain is to be expected
    from that.
  • removed global variable support
    The original idea was not well thought out and global variables, as
    implemented, worked far different from what anybody would expect. As
    such, we consider the current approach as an experiment that did not
    work out and opt to removing it, clearing the way for a better future
    solution. Note: global vars were introduced in 7.5.3 on Sept, 11th 2013.
  • new module mmsequence, primarily used for action load balancing
    Thanks to Pavel Levshin for contributing this module.
  • bugfix: unset statement always worked on message var, even if local
    var was given
  • bugfix: segfault if variable was assigned to non-container subtree
    Thanks to Pavel Levshin for the fix
  • bugfix: imuxsock did not suport addtl sockets if syssock was disabled
    Thanks to Pavel Levshin for the fix
  • bugfix: running imupd on multiple threads lead to segfault if recvmmsg
    is available
  • bugfix: segfault if re_extract() function was used and no match found
  • bugfix: omelasticsearch did not compile on platforms without atomic
    instructions
  • bugfix: potential misadressing on startup if property-filter was used
    This could happen if the property name was longer than 127 chars, a case
    that would not happen in practice.
  • bugfix: invalid property filter was not properly disabled in ruleset
    Note: the cosmetic memory leak introduced with that patch in 7.4.5 is
    now also fixed.

Changelog for 7.5.4 (v7-devel)

Version 7.5.4 [devel] 2013-10-07

  • mmpstrucdata: new module to parse RFC5424 structured data into json message properties
  • change main/ruleset queue defaults to be more enterprise-like
    new defaults are queue.size 100,000 max workers 2, worker activation after 40,000 msgs are queued, batch size 256. These settings are much more useful for enterprises and will not hurt low-end systems that much. This is part of our re-focus on enterprise needs.
  • omfwd: new action parameter “maxErrorMessages” added
  • omfile: new module parameters to set action defaults added
    * dirCreateMode
    * fileCreateMode
  • mmutf8fix: new module to fix invalid UTF-8 sequences
  • imuxsock: handle unlimited number of additional listen sockets
  • doc: improve usability by linking to relevant web ressources
    The idea is to enable users to quickly find additional information, samples, HOWTOs and the like on the main site. At the same time, (very) slightly remove memory footprint when few listeners are monitored.
  • bugfix: omfwd parameter streamdrivermmode was not properly handled
    It was always overwritten by whatever value was set via the legacy directive $ActionSendStreamDriverMode
  • imtcp: add streamdriver.name module parameter
    permits overriding the system default stream driver (gtls, ptcp)
  • bugfix: build system: libgcrypt.h needed even if libgrcypt was disabled
    Thanks to Jonny Törnbom for reporting this problem
  • imported bugfixes from 7.4.4

Changelog for 7.5.3 (v7-devel)

Version 7.5.3 [devel] 2013-09-11

  • imfile: support for escaping LF characters added embedded LF in syslog messages cause a lot of trouble. imfile now has the capability to escape them to “#012″ (just like the regular control character escape option). This requires new-style input statements to be used. If legacy configuration statements are used, LF escaping is always turned off to preserve compatibility.
    NOTE: if input() statements were already used, there is a CHANGE OF BEHAVIOUR: starting with this version, escaping is enabled by default. So if you do not want it, you need to add escapeLF=”off” to the input statement. Given the trouble LFs cause and the fact that the majority of installations still use legacy config, we considered this behaviour change acceptable and useful.
    see also: http://blog.gerhards.net/2013/09/imfile-multi-line-messages.html
  • add support for global and local variables
  • bugfix: queue file size was not correctly processed
    this could lead to using one queue file per message for sizes >2GiB
    Thanks to Tomas Heinrich for the patch.
  • add main_queue() configuration object to configure main message queue
  • bugfix: stream compression in imptcp caused timestamp to be corrupted
  • imudp: add ability to specify SO_RCVBUF size (rcvbufSize parameter)
  • imudp: use inputname for statistics, if configured
  • impstats: add process resource usage counters [via getrusage()]
  • impstats: add paramter “resetCounters” to report delta values possible for most, but not all, counters. See doc for details.
  • librelp 1.2.0 is now required
  • make use of new librelp generic error reporting facility
    This leads to more error messages being passed to the user and thus simplified troubleshooting.
  • bugfix: very small memory leak in imrelp
    more or less cosmetic, a single memory block was not freed, but this only happens immediately before termination (when the OS automatically frees all memory). Still an annoyance e.g. in valgrind.
  • fix compile problem in debug build
  • imported fixes from 7.4.4
Scroll to top