Module: Sensu::Daemon

Includes:
Utilities
Included in:
API::Process, Client::Process, Server::Process
Defined in:
lib/sensu/daemon.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utilities

#deep_merge, #find_attribute_value, #random_uuid, #redact_sensitive, #retry_until_true, #substitute_tokens, #testing?

Instance Attribute Details

#start_timeObject (readonly)

Returns the value of attribute start_time.



37
38
39
# File 'lib/sensu/daemon.rb', line 37

def start_time
  @start_time
end

Instance Method Details

#initialize(options = {}) ⇒ Object

Initialize the Sensu process. Set the start time, initial service state, set up the logger, load settings, load extensions, and optionally daemonize the process and/or create a PID file. A subclass may override this method.

Parameters:

  • options (Hash) (defaults to: {})


45
46
47
48
49
50
51
52
53
# File 'lib/sensu/daemon.rb', line 45

def initialize(options={})
  @start_time = Time.now.to_i
  @state = :initializing
  @timers = {:run => []}
  setup_logger(options)
  load_settings(options)
  load_extensions(options)
  setup_process(options)
end

#load_extensions(options = {}) ⇒ Object

Load Sensu extensions and log any concerns. Set the logger and settings for each extension instance. This method creates the extensions instance variable: ‘@extensions`.

github.com/sensu/sensu-extensions github.com/sensu/sensu-extension

Parameters:

  • options (Hash) (defaults to: {})


124
125
126
127
128
129
130
131
132
# File 'lib/sensu/daemon.rb', line 124

def load_extensions(options={})
  @extensions = Extensions.get(options)
  log_concerns(@extensions.warnings)
  extension_settings = @settings.to_hash.dup
  @extensions.all.each do |extension|
    extension.logger = @logger
    extension.settings = extension_settings
  end
end

#load_settings(options = {}) ⇒ Object

Load Sensu settings and validate them. If there are validation failures, log them (concerns), then cause the Sensu process to exit (2). This method creates the settings instance variable: ‘@settings`. If the `print_config` option is true, this method calls `print_settings()` to output the compiled configuration settings and then exit the process.

github.com/sensu/sensu-settings

Parameters:

  • options (Hash) (defaults to: {})


103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/sensu/daemon.rb', line 103

def load_settings(options={})
  @settings = Settings.get(options)
  log_concerns(@settings.warnings)
  failures = @settings.validate
  unless failures.empty?
    @logger.fatal("invalid settings")
    log_concerns(failures, :fatal)
    @logger.fatal("SENSU NOT RUNNING!")
    exit 2
  end
  print_settings(@settings) if options[:print_config]
end

#log_concerns(concerns = [], level = :warn) ⇒ Object

Log setting or extension loading concerns, sensitive information is redacted.

Parameters:

  • concerns (Array) (defaults to: [])

    to be logged.

  • level (Symbol) (defaults to: :warn)

    to log the concerns at.



72
73
74
75
76
77
# File 'lib/sensu/daemon.rb', line 72

def log_concerns(concerns=[], level=:warn)
  concerns.each do |concern|
    message = concern.delete(:message)
    @logger.send(level, message, redact_sensitive(concern))
  end
end

#pauseObject

Pause the Sensu service and set the service state to ‘:paused`. This method will likely be overridden by a subclass.



151
152
153
# File 'lib/sensu/daemon.rb', line 151

def pause
  @state = :paused
end

Print the Sensu settings and immediately exit the process. This method is used while troubleshooting configuration issues, triggered by a CLI argument, e.g. ‘–print_config`. Sensu settings with sensitive values (e.g. passwords) are first redacted.

Parameters:

  • settings (Object)


86
87
88
89
90
91
# File 'lib/sensu/daemon.rb', line 86

def print_settings(settings)
  redacted_settings = redact_sensitive(settings.to_hash)
  @logger.warn("outputting compiled configuration and exiting")
  puts Sensu::JSON.dump(redacted_settings, :pretty => true)
  exit
end

#resumeObject

Resume the paused Sensu service and set the service state to ‘:running`. This method will likely be overridden by a subclass.



157
158
159
# File 'lib/sensu/daemon.rb', line 157

def resume
  @state = :running
end

#setup_logger(options = {}) ⇒ Object

Set up the Sensu logger and its process signal traps for log rotation and debug log level toggling. This method creates the logger instance variable: ‘@logger`.

github.com/sensu/sensu-logger

Parameters:

  • options (Hash) (defaults to: {})


62
63
64
65
# File 'lib/sensu/daemon.rb', line 62

def setup_logger(options={})
  @logger = Logger.get(options)
  @logger.setup_signal_traps
end

#setup_process(options) ⇒ Object

Manage the current process, optionally daemonize and/or write the current process ID to a PID file.

Parameters:

  • options (Hash)


138
139
140
141
# File 'lib/sensu/daemon.rb', line 138

def setup_process(options)
  daemonize if options[:daemonize]
  write_pid(options[:pid_file]) if options[:pid_file]
end

#setup_redis {|Object| ... } ⇒ Object

Set up the Redis connection. Sensu uses Redis as a data store, to store the client registry, current events, etc. The Sensu service will stop gracefully in the event of a Redis error, and pause/resume in the event of connectivity issues. This method creates the Redis instance variable: ‘@redis`.

github.com/sensu/sensu-redis

Yields:

  • (Object)

    passes initialized and connected Redis connection object to the callback/block.



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/sensu/daemon.rb', line 244

def setup_redis
  @logger.debug("connecting to redis", :settings => @settings[:redis])
  Redis.connect(@settings[:redis]) do |connection|
    @redis = connection
    @redis.on_error do |error|
      @logger.error("redis connection error", :error => error.to_s)
    end
    @redis.before_reconnect do
      unless testing?
        @logger.warn("reconnecting to redis")
        pause
      end
    end
    @redis.after_reconnect do
      @logger.info("reconnected to redis")
      resume
    end
    yield(@redis)
  end
end

#setup_signal_trapsObject

Set up process signal traps. This method uses the ‘STOP_SIGNALS` constant to determine which process signals will result in a graceful service stop. A periodic timer must be used to poll for received signals, as Mutex#lock cannot be used within the context of `trap()`.



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/sensu/daemon.rb', line 175

def setup_signal_traps
  @signals = []
  STOP_SIGNALS.each do |signal|
    Signal.trap(signal) do
      @signals << signal
    end
  end
  EM::PeriodicTimer.new(1) do
    signal = @signals.shift
    if STOP_SIGNALS.include?(signal)
      @logger.warn("received signal", :signal => signal)
      stop
    end
  end
end

#setup_transport {|Object| ... } ⇒ Object

Set up the Sensu transport connection. Sensu uses a transport API, allowing it to use various message brokers. By default, Sensu will use the built-in “rabbitmq” transport. The Sensu service will stop gracefully in the event of a transport error, and pause/resume in the event of connectivity issues. This method creates the transport instance variable: ‘@transport`.

github.com/sensu/sensu-transport

Yields:

  • (Object)

    passes initialized and connected Transport connection object to the callback/block.



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/sensu/daemon.rb', line 202

def setup_transport
  transport_name = @settings[:transport][:name]
  transport_settings = @settings[transport_name]
  @logger.debug("connecting to transport", {
    :name => transport_name,
    :settings => transport_settings
  })
  Transport.logger = @logger
  Transport.connect(transport_name, transport_settings) do |connection|
    @transport = connection
    @transport.on_error do |error|
      @logger.error("transport connection error", :error => error.to_s)
      if @settings[:transport][:reconnect_on_error]
        @transport.reconnect
      else
        stop
      end
    end
    @transport.before_reconnect do
      unless testing?
        @logger.warn("reconnecting to transport")
        pause
      end
    end
    @transport.after_reconnect do
      @logger.info("reconnected to transport")
      resume
    end
    yield(@transport)
  end
end

#startObject

Start the Sensu service and set the service state to ‘:running`. This method will likely be overridden by a subclass.



145
146
147
# File 'lib/sensu/daemon.rb', line 145

def start
  @state = :running
end

#stopObject

Stop the Sensu service and set the service state to ‘:stopped`. This method will likely be overridden by a subclass. This method should stop the EventMachine event loop.



164
165
166
167
168
# File 'lib/sensu/daemon.rb', line 164

def stop
  @state = :stopped
  @logger.warn("stopping reactor")
  EM::stop_event_loop
end