# inspired by [lumberjack](https://github.com/bdurand/lumberjack_syslog_device) require 'syslog' require 'thread' module LogStasher module Device class Syslog SEMAPHORE = Mutex.new attr_reader :options def initialize(options = {}) @options = parse_options(default_options.merge(options)) @closed = false end def close SEMAPHORE.synchronize do ::Syslog.close if ::Syslog.opened? end @closed = true end def closed? @closed end def facility options[:facility] end def flags options[:flags] end def identity options[:identity] end def priority options[:priority] end def write(log) fail ::RuntimeError, 'Cannot write. The device has been closed.' if closed? with_syslog_open do ::Syslog.log(facility, log) end end private def default_options { :identity => 'logstasher', :facility => ::Syslog::LOG_LOCAL0, :priority => ::Syslog::LOG_INFO, :flags => ::Syslog::LOG_PID | ::Syslog::LOG_CONS } end def parse_option(value) case value when ::String ::Syslog.const_get(value.to_s) when ::Array value.reduce(0) { |all, current| all |= parse_option(current) } else value end end def parse_options(options) options[:facility] = parse_option(options[:facility]) options[:priority] = parse_option(options[:priority]) options[:flags] = parse_option(options[:flags]) options end def syslog_configured? ::Syslog.ident == identity && ::Syslog.options == flags && ::Syslog.facility == facility end def with_syslog_open SEMAPHORE.synchronize do if ::Syslog.opened? ::Syslog.reopen(identity, flags, facility) unless syslog_configured? else ::Syslog.open(identity, flags, facility) end yield end end end end end