module Startback::Support::Robustness

This module provides helper methods for robustness of a software design.

It is included by main Startback abstractions, and can be included by specific software components who needs fine-tuning of monitoring, logging and error handling.

All public methods here follow the following free args parameters:

  1. First (& second) argument(s) form the log message.

    A full log message is a Hash having :op (required), :op_took (optional), and :op_data (optional) keys.

    If a String (or two) are used instead, a log message will be built taking the former as the executer (a class or instance) and the second as a method. `{ op: “executer#method” }`

  2. The second (or third) argument should be a Logger instance, a Context, or an instance knowing its context. The best logger is extracted from it and used for actual logging.

Examples:

log(:info, op: "hello", op_data: {foo: 12})    => logged as such on STDOUT
log(:info, "A simple message")                 => { op: "A simple message" } on STDOUT
log(:info, Startback, "hello")                 => { op: "Startback#hello"  } on STDOUT
log(:info, Event.new, "hello")                 => { op: "Event#hello" }      on STDOUT
log(:info, Event.new, "hello", "hello world")  => { op: "Event#hello", op_data: { message: "hello world" } } on STDOUT
log(:info, self, context)                      => { op: "..." } on context's logger or STDOUT
log(:info, self, event)                        => { op: "..." } on event context's logger or STDOUT
...

Public Instance Methods

log(severity, *args) click to toggle source

Logs a specific message with a given severity.

Severity can be :debug, :info, :warn, :error or :fatal. The args must follow module's conventions, see above.

# File lib/startback/support/robustness.rb, line 94
def log(severity, *args)
  Tools.send(severity, args)
end
monitor(*args, &bl) click to toggle source

Calls the block and monitors then log its execution time.

The args must follow module's conventions, see above.

# File lib/startback/support/robustness.rb, line 101
def monitor(*args, &bl)
  result = nil
  took = Benchmark.realtime {
    result = bl.call
  }
  Tools.info(args, op_took: took)
  result
rescue => ex
  raise
end
stop_errors(*args, &bl) click to toggle source

Executes the block without letting errors propagate. Errors are logged, though. Nothing is logged if everything goes fine.

The args must follow module's conventions, see above.

# File lib/startback/support/robustness.rb, line 117
def stop_errors(*args, &bl)
  result = nil
  took = Benchmark.realtime {
    result = bl.call
  }
  result
rescue => ex
  Tools.fatal(args, op_took: took, error: ex)
  nil
end
try_max_times(n, *args, &bl) click to toggle source

Tries executing the block up to `n` times, until an attempt succeeds (then returning the result). Logs the first and last fatal error, if any.

The args must follow module's conventions, see above.

# File lib/startback/support/robustness.rb, line 133
def try_max_times(n, *args, &bl)
  retried = 0
  took = 0
  begin
    result = nil
    took += Benchmark.realtime {
      result = bl.call
    }
    result
  rescue => ex
    Tools.error(args + [{op_took: took, error: ex}]) if retried == 0
    retried += 1
    if retried < n
      sleep(retried)
      retry
    else
      Tools.fatal(args + [{op_took: took, error: ex}])
      raise
    end
  end
end