Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Commit

Permalink
Topic: merge Add a syslog sink and a tiny utility for testing logging…
Browse files Browse the repository at this point in the history
… to syslog

from the commandline.

Change-Id: I8e0c23b376b8e68fe7d8607f3e88c101da5d37e8
  • Loading branch information
mpage committed Jun 7, 2011
1 parent 9487d13 commit 7af3421
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
40 changes: 40 additions & 0 deletions vcap_logging/bin/test_syslog
@@ -0,0 +1,40 @@
#!/usr/bin/env ruby
# A very simple test script for logging to syslog
#
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))

require 'optparse'

require 'vcap/logging'

opts = {
:level => :info,
:name => 'test_syslog',
}
parser = OptionParser.new do |op|
op.banner = "Usage: test_syslog [opts] <message>"

op.on('-l [LEVEL]', '--level [LEVEL]', 'Foo') {|level| opts[:level] = level.to_sym }
op.on('-n [NAME]', '--name [NAME]', 'Bar') {|name| opts[:name] = name }

end
parser.parse!

unless ARGV.length > 0
puts parser.help
exit 1
end

formatter = VCAP::Logging::Formatter::DelimitedFormatter.new do
timestamp
log_level
fiber_shortid
thread_shortid
process_id
data
end
sink = VCAP::Logging::Sink::SyslogSink.new(opts[:name], :formatter => formatter)
VCAP::Logging.add_sink(nil, nil, sink)

log = VCAP::Logging.logger('test')
log.send(opts[:level], ARGV.join(' '))
4 changes: 4 additions & 0 deletions vcap_logging/lib/vcap/logging.rb
Expand Up @@ -71,6 +71,10 @@ def logger(name)
@loggers[name]
end

def add_sink(*args)
@sink_map.add_sink(*args)
end

# Sets the log level to _log_level_ for every logger whose name matches _path_regex_
#
# @param path_regex String Regular expression to use when matching against the logger name
Expand Down
1 change: 1 addition & 0 deletions vcap_logging/lib/vcap/logging/sink.rb
@@ -1,2 +1,3 @@
require 'vcap/logging/sink/base_sink'
require 'vcap/logging/sink/file_sink'
require 'vcap/logging/sink/syslog_sink'
2 changes: 2 additions & 0 deletions vcap_logging/lib/vcap/logging/sink/base_sink.rb
Expand Up @@ -2,6 +2,8 @@

require 'vcap/logging/log_record'

require 'thread'

module VCAP
module Logging
module Sink
Expand Down
68 changes: 68 additions & 0 deletions vcap_logging/lib/vcap/logging/sink/syslog_sink.rb
@@ -0,0 +1,68 @@
require 'syslog'

require 'vcap/logging/sink/base_sink'

module VCAP::Logging::Sink

# A sink for logging messages to the local syslog server.
# NB: The ruby syslog module is a thin wrapper around glibc syslog(). It will first
# attempt to open a unix stream socket to '/dev/log', and upon failure will attempt
# to open a unix datagram socket there. Make sure you configure your syslog server
# to use the appropriate type (probably dgram in our case).
#
# Beware that all messages will be silently lost if the syslog server goes away.
class SyslogSink < BaseSink

DEFAULT_LOG_LEVEL_MAP = {
:fatal => Syslog::LOG_CRIT,
:error => Syslog::LOG_ERR,
:warn => Syslog::LOG_WARNING,
:info => Syslog::LOG_INFO,
:debug => Syslog::LOG_DEBUG,
:debug1 => Syslog::LOG_DEBUG,
:debug2 => Syslog::LOG_DEBUG,
}

# @param prog_name String Program name to identify lines logged to syslog
# @param opts Hash :log_level_map Map of log level => syslog level
# :formatter LogFormatter
def initialize(prog_name, opts={})
super(opts[:formatter])

@prog_name = prog_name
@log_level_map = opts[:log_level_map] || DEFAULT_LOG_LEVEL_MAP
@syslog = nil
open
end

def open
@mutex.synchronize do
unless @opened
@syslog = Syslog.open(@prog_name, Syslog::LOG_CONS | Syslog::LOG_PID, Syslog::LOG_USER)
@opened = true
end
end
end

def close
@mutex.synchronize do
if @opened
@syslog.close
@syslog = nil
@opened = false
end
end
end

def add_record(log_record)
raise UsageError, "You cannot add a record until the sink has been opened" unless @opened
raise UsageError, "You must supply a formatter" unless @formatter

message = @formatter.format_record(log_record)

pri = @log_level_map[log_record.log_level]
@mutex.synchronize { @syslog.log(pri, message) }
end

end
end
23 changes: 23 additions & 0 deletions vcap_logging/spec/unit/syslog_sink_spec.rb
@@ -0,0 +1,23 @@
require File.join(File.dirname(__FILE__), '..', 'spec_helper')

require 'syslog'

describe VCAP::Logging::Sink::SyslogSink do
it 'should use the user facility for logging messages' do
Syslog.should_receive(:open).with('test', Syslog::LOG_CONS | Syslog::LOG_PID, Syslog::LOG_USER).and_return(nil)
sink = VCAP::Logging::Sink::SyslogSink.new('test')
end

it 'should map app log levels to syslog levels' do
msg = 'test message'
rec = mock(:test_record)
rec.should_receive(:log_level).and_return(:info)
fmt = mock(:test_formatter)
fmt.should_receive(:format_record).with(any_args()).and_return(msg)
Syslog.should_receive(:open).with('test', Syslog::LOG_CONS | Syslog::LOG_PID, Syslog::LOG_USER).and_return(Syslog)
Syslog.should_receive(:log).with(Syslog::LOG_INFO, msg).and_return(nil)
sink = VCAP::Logging::Sink::SyslogSink.new('test')
sink.formatter = fmt
sink.add_record(rec)
end
end

0 comments on commit 7af3421

Please sign in to comment.