Class: RightSupport::Log::Syslog::Remote

Inherits:
Object
  • Object
show all
Defined in:
lib/right_support/log/syslog/remote.rb

Overview

partially implements the Syslog interface for a remote syslog connection. the Syslog.open method is restricted to only using the ‘/dev/log’ socket (or darwin equivalent).

Defined Under Namespace

Modules: Severity Classes: RemoteSyslogError

Instance Method Summary collapse

Constructor Details

#initialize(uri, program_name, facility, options = {}) ⇒ Remote

Returns a new instance of Remote.



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/right_support/log/syslog/remote.rb', line 56

def initialize(uri, program_name, facility, options = {})
  @uri = ::URI.parse(uri.to_s)
  @program_name = program_name
  @facility = facility
  @identity = "#{program_name}[#{$$}]"
  @hostname = ::Socket.gethostname.split('.').first
  @mutex = ::Mutex.new
  @socket = nil
  @error_handler = options[:error_handler]
  @error_mode = false
end

Instance Method Details

#alert(message) ⇒ Object



126
127
128
# File 'lib/right_support/log/syslog/remote.rb', line 126

def alert(message)
  log(@facility, Severity::ALERT, message)
end

#closeObject



112
113
114
115
116
117
118
119
120
# File 'lib/right_support/log/syslog/remote.rb', line 112

def close
  if @socket && !@socket.closed?
    @socket.close
  end
rescue => e
  STDERR.puts("Failed to close syslog socket: #{e.message}")
ensure
  @socket = nil
end

#connectObject



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/right_support/log/syslog/remote.rb', line 68

def connect
  close if @socket
  opener = nil
  case @uri.scheme
  when 'tcp'
    opener = lambda do
      ::TCPSocket.new(@uri.host, @uri.port)
    end
  when 'udp'
    opener = lambda do
      s = ::UDPSocket.new
      s.connect(@uri.host, @uri.port)
      s
    end
  else
    raise RemoteSyslogError, "Unxpected URI scheme: #{@uri.scheme}"
  end

  # backoff/retry connection. each log call will attempt to reconnect on
  # write failure but only the first will backoff/retry the connection.
  # the issue is to try and keep the service running and logging while
  # syslog is being restarted for routine maintainance. if syslog is offline
  # indefinitely then the app must continue without slowing. the caller can
  # provide an error_handler to perform graceful shutdown, etc.
  sleeper = 1
  attempts = 0
  begin
    @socket = opener.call
    @socket.sync = true
  rescue => e
    # do not repeat backoff/retry when already in error mode.
    raise if @error_mode
    attempts += 1
    if attempts <= 6   # about one minute
      STDERR.puts("Sleeping #{sleeper}s due to failure to (re)connect to syslog: #{e.message}\n")
      sleep(sleeper)
      sleeper *= 2
      retry
    else
      raise
    end
  end
end

#crit(message) ⇒ Object



130
131
132
# File 'lib/right_support/log/syslog/remote.rb', line 130

def crit(message)
  log(@facility, Severity::CRIT, message)
end

#debug(message) ⇒ Object



150
151
152
# File 'lib/right_support/log/syslog/remote.rb', line 150

def debug(message)
  log(@facility, Severity::DEBUG, message)
end

#emerg(message) ⇒ Object



122
123
124
# File 'lib/right_support/log/syslog/remote.rb', line 122

def emerg(message)
  log(@facility, Severity::EMERG, message)
end

#err(message) ⇒ Object



134
135
136
# File 'lib/right_support/log/syslog/remote.rb', line 134

def err(message)
  log(@facility, Severity::ERR, message)
end

#info(message) ⇒ Object



146
147
148
# File 'lib/right_support/log/syslog/remote.rb', line 146

def info(message)
  log(@facility, Severity::INFO, message)
end

#log(facility, severity, message) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/right_support/log/syslog/remote.rb', line 154

def log(facility, severity, message)
  # Normally, use a mutex to ensure threadsafe logging
  @mutex.synchronize do
    log_without_thread_safety(facility, severity, message)
  end
  true
rescue ThreadError => e
  # Sometimes the mutex can't be acquired (e.g. when servicing a trap);
  #
  log_without_thread_safety(facility, severity, message)
  true
end

#notice(message) ⇒ Object



142
143
144
# File 'lib/right_support/log/syslog/remote.rb', line 142

def notice(message)
  log(@facility, Severity::NOTICE, message)
end

#warning(message) ⇒ Object



138
139
140
# File 'lib/right_support/log/syslog/remote.rb', line 138

def warning(message)
  log(@facility, Severity::WARNING, message)
end