Class: RightSupport::Log::SystemLogger

Inherits:
Logger
  • Object
show all
Defined in:
lib/right_support/log/system_logger.rb

Overview

A logger that forwards log entries to the Unix syslog facility, but complies with the interface of the Ruby Logger object and faithfully translates log severities and other concepts. Provides optional cleanup/filtering in order to keep the syslog from having weird characters or being susceptible to log forgery.

Constant Summary collapse

SEVERITY_MAP =
{
  UNKNOWN => :alert,
  FATAL   => :err,
  ERROR   => :warning,
  WARN    => :notice,
  INFO    => :info,
  DEBUG   => :debug
}
FACILITY_MAP =

Translation table that maps human-readable syslog facility names to integer constants used by the Syslog module. Compiled from the Linux header file ‘sys/syslog.h’ (see linux.die.net/include/sys/syslog.h)

{
  'kern'     => (0<<3),
  'user'     => (1<<3),
  'mail'     => (2<<3),
  'daemon'   => (3<<3),
  'auth'     => (4<<3),
  'syslog'   => (5<<3),
  'lpr'      => (6<<3),
  'news'     => (7<<3),
  'uucp'     => (8<<3),
  'cron'     => (9<<3),
  'authpriv' => (10<<3),
  'ftp'      => (11<<3),
  'local0'   => (16<<3),
  'local1'   => (17<<3),
  'local2'   => (18<<3),
  'local3'   => (19<<3),
  'local4'   => (20<<3),
  'local5'   => (21<<3),
  'local6'   => (22<<3),
  'local7'   => (23<<3),
}
DEFAULT_OPTIONS =
{
  :split=>false,
  :color=>false,
  :facility=>'local0',
  :connection=>:autodetect
}
@@syslog =
nil
@@mutex =
Mutex.new
@@program_name =
nil

Instance Method Summary collapse

Constructor Details

#initialize(program_name = 'ruby', options = {}) ⇒ SystemLogger

Initialize this process’s syslog facilities and construct a new syslog logger object.

Parameters

program_name(String)

the syslog program name, ‘ruby’ by default

options(Hash)

(optional) configuration options to use, see below

Options

facility

the syslog facility to use for messages, ‘local0’ by default

split(true|false)

if true, splits multi-line messages into separate syslog entries

color(true|false)

if true, passes ANSI escape sequences through to syslog

connection(type)

if :local, connects using local Unix socket. if :autodetect,

it may choose a remote connection if the 'syslog' host is known. otherwise
a URI such as 'tcp://127.0.0.1:514' can be passed explicitly.
error_handler(callback)

callback for write failures in order to give

the application a change to gracefully shutdown, etc.
default is to dump errors to STDERR and continue.
parameters = [exception]
currently only called by remote syslog

Raise

ArgumentError

if an invalid facility is given



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/right_support/log/system_logger.rb', line 102

def initialize(program_name='ruby', options={})
  @options = DEFAULT_OPTIONS.merge(options)
  @level   = Logger::DEBUG

  facility = FACILITY_MAP[@options[:facility].to_s]
  if facility.nil?
    raise ArgumentError, "Invalid facility '#{@options[:facility]}'"
  end

  @@mutex.synchronize do
    if @@syslog && (@@program_name  != program_name)
      @@syslog.close ; @@syslog = nil
    end

    unless @@syslog
      if @options[:connection] == :autodetect
        # don't even want to know if this code is supported on older Ruby.
        # this logic is intended to help dockerization, which for us
        # begins at Ruby v2.1+
        @options[:connection] = :local  # local if all attempts fail
        if RUBY_VERSION >= '2.1'
          # only choose the 'syslog' host when explicitly declared in
          # '/etc/hosts'. use built-in Resolv module to check.
          begin
            require 'resolv'
            host = ::Resolv::Hosts.new.getaddress('syslog')
            begin
              ::TCPSocket.new(host, 514).close
              @options[:connection] = 'tcp://syslog:514'
            rescue ::Errno::ECONNREFUSED, Errno::EHOSTUNREACH
              # not listening on TCP port 514
            end
          rescue ::Resolv::ResolvError
            # not set
          end
        end
      end

      # connect
      @@program_name = program_name
      @@facility = facility
      establish_connection
    end
  end
  @@syslog.info("Connected to syslog: #{@options[:connection].inspect}")
end

Instance Method Details

#<<(msg) ⇒ Object

Emit a log entry at INFO severity.

Parameters

msg(Object)

the message to log

Return

true

always returns true



206
207
208
# File 'lib/right_support/log/system_logger.rb', line 206

def <<(msg)
  info(msg)
end

#add(severity, message = nil, progname = nil, &block) ⇒ Object

Log a message if the given severity is high enough. This is the generic logging method. Users will be more inclined to use #debug, #info, #warn, #error, and #fatal.

Parameters

severity(Integer)

one of the severity constants defined by Logger

message(Object)

the message to be logged

progname(String)

ignored, the program name is fixed at initialization

Block

If message is nil and a block is supplied, this method will yield to obtain the log message.

Return

true

always returns true



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/right_support/log/system_logger.rb', line 176

def add(severity, message = nil, progname = nil, &block)
  severity ||= UNKNOWN
  if @@syslog.nil? or severity < @level
    return true
  end

  progname ||= @progname

  if message.nil?
    if block_given?
      message = yield
    else
      message = progname
      progname = @progname
    end
  end

  parts = clean(message)
  parts.each { |part| emit_syslog(severity, part) }
  return true
end

#closeObject

Do nothing. This method is provided for Logger interface compatibility.

Return

true

always returns true



215
216
217
# File 'lib/right_support/log/system_logger.rb', line 215

def close
  return true
end

#reconnectTrueClass

Reconnects using the established connection details. This is useful to ensure the rainbows child processes show their own PID, etc.

Returns:

  • (TrueClass)

    always true



153
154
155
156
157
158
# File 'lib/right_support/log/system_logger.rb', line 153

def reconnect
  @@mutex.synchronize do
    establish_connection
  end
  true
end