5

I am very new playing with syslog.

We have decided to use syslog to track some special events in our Rails application.

The problem is that I don't want to use the default /var/log/system.log file but use a custom one like /var/log/myapp_events.log.

I see that for that I have to define my own facility in /etc/syslog.conf like this:

myapp_events.* /var/log/myapp_events.log

After restarting syslogd I see that I can play with it directly into the bash console:

syslog -s -k Facility myapp_events Message "this is my message"

The message appears into the /var/log/myapp_events.log as expected, but I cannot reproduce this behavior using the syslog ruby gem. I have tried:

require 'syslog'
Syslog.open('myapp_events', Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.warning 'this is my message' }  # sends the message to system.log
Syslog.open('myapp_events', Syslog::LOG_PID | Syslog::LOG_CONS, 'myapp_events') { |s| s.warning 'this is my message' }  # error because 'myapp_event' can't be converted to int.

I see that Syslog.open has a third argument which is the facility but it has to be an integer and what I have is a string.

Any suggestion?

Rodrigue
  • 3,617
  • 2
  • 37
  • 49
fguillen
  • 36,125
  • 23
  • 149
  • 210
  • I'm seeing that the ruby `syslog` gem uses the `syslog` C implementation and this C function only accepts integer as **facility** value: http://www.gnu.org/s/libc/manual/html_node/syslog_003b-vsyslog.html#syslog_003b-vsyslog – fguillen Oct 28 '10 at 14:19

4 Answers4

14

Definitely the syslog ruby implementation doesn't allow us to use custom facilities.

The syslog ruby implementation is using the syslog [C implementation] (http://github.com/ruby/ruby/blob/trunk/ext/syslog/syslog.c#L36).

The syslog C implementation only allows us to use a very short list of facility names: LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS, LOG_UUCP, UUCP , LOG_CRON, LOG_AUTHPRIV, LOG_FTP, LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7.

So in the end what I did was to use one of the LOG_LOCALX facilities that are already there for personal use.

Now I can configure syslog like this:

# /etc/syslog.conf
local5.*    /var/log/myapp_events.log

And in Ruby do this:

Syslog.open('myapp', Syslog::LOG_PID, Syslog::LOG_LOCAL5) { |s| s.info 'this is my message' }

I think is the way that syslog wants you to define custom facilities.

Rodrigue
  • 3,617
  • 2
  • 37
  • 49
fguillen
  • 36,125
  • 23
  • 149
  • 210
  • For those wanting to use Syslog::Logger and on < Ruby 2.1, you can use `Syslog::Logger.syslog = Syslog.open('myapp', Syslog::LOG_PID, Syslog::LOG_LOCAL5); my_logger = Syslog::Logger.new` to set the facility. – Mike Campbell Feb 03 '16 at 11:19
3

Logger isn't useful when you have multiple workers or threads, since the log messages get interleaved. This is why the default logger in Rails 3 is BufferedLogger.

This is also why you must use a buffering syslogger like rsyslog, or it will kill your performance. (I believe syslogd uses fsync() which is a synchronous call that waits to return.)

Duke
  • 7,070
  • 3
  • 38
  • 28
3

Take a look at Lumberjack.

It has support for Syslog as a log device, and you can specify facility as an option:

require 'lumberjack'
require 'lumberjack_syslog_device'

syslog_device = Lumberjack::SyslogDevice.new(:facility => 'myapp_events')
logger = Lumberjack::Logger.new(syslog_device)
logger.info "Hello, Syslog!"

Lumberjack also has quite a few other features that makes it worth a look.

Lars Haugseth
  • 14,721
  • 2
  • 45
  • 49
  • The Lumberjack syslog device gives the same error stated in the original question: TypeError: can't convert String into Integer at /var/lib/gems/1.9.1/gems/lumberjack_syslog_device-1.0.0/lib/lumberjack_syslog_device.rb:99:in `open' – Fabian Zeindl Apr 16 '12 at 13:30
  • looks like Lumberjack expects only a fixed list of Syslog Facilities, e.g. listed in the source code of https://github.com/bdurand/lumberjack_syslog_device/blob/master/lib/lumberjack_syslog_device.rb -- that's an enumeration, e.g. Integers. If you hand in a String it complains.. – Tilo Nov 20 '12 at 20:00
0

You might want to look into using Logger, which is very similar to syslog, only it is a bit more user-friendly. It has multiple levels of criticality, like Syslog, and offers log rolling based on size or age.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • 1
    The point is that we want to use the `syslog` daemon, so we can use its unix features by free. – fguillen Oct 28 '10 at 12:32
  • My point is that Syslog in Ruby is poorly documented. You'll probably need to read the source for it to do much beyond the fundamentals. Logger is a reaction to that and is easier to use and a lot of people use it instead because it is more accessible. I use syslog all the time but still think its a PITA and could do with a major facelift to make it more appealing. – the Tin Man Oct 28 '10 at 19:24
  • 2
    I have travel deep into the `syslog` ruby implementation and it is used the `syslog` C implementation and there is not any posibility to send to this C function a custom facility, you have to choose between the oficial ones: http://search.cpan.org/~saper/Sys-Syslog/Syslog.pm#Facilities .. think this is the end of the history :) – fguillen Oct 29 '10 at 12:30
  • 2
    Seriously? Suggesting another tool when Syslog was specifically asked for is like answering "Use Java" when someone asks a Ruby question .. Utterly pointless – Kiall Feb 23 '11 at 17:45
  • Wow, timely comment. As you can see, the OP had to go to great lengths to find a work-around. I suggested a Ruby solution that is used by a lot of Ruby-based apps, including Rails, not a Java one, because, sometimes, on SO we suggest workarounds when they might be easier paths to a solution. – the Tin Man Feb 23 '11 at 21:58