module EventMachine

EM::Monitor adds a few methods to eventmachine that can help you keep track of ‘lag’ caused by long-running CPU spans on the reactor thread.

Public Class Methods

monitor_histogram(opts = {}, &block) click to toggle source

Set the block to be called periodically with histogram data.

This is a convenience wrapper around {monitor_spans} for the common use-case of wanting to plot a histogram of loop utilisation split into time-chunks.

In the normal case you can plot these values directly and it will tell you how much CPU-time was used by spans shorter than a given length. However, care should be taken if CPU-spans are often of similar length to :interval. This can cause the actual delay between calls to the block to vary significantly and so if you’re trying to plot a line of CPU-utilization then it can give you misleading answers. If this is a concern to you then you might want to use the :cumulative mode and ask your graphing library to plot the derivative of the values over time.

@param [Hash] opts Configuration for the histogram @param [Proc] block the block to call.

@option opts [Number] :interval (60)

The approximate number of seconds between calls to your block.
If your event loop regularly runs long CPU-spans then the actual time between
calls can vary significantly.

@option opts [Array<Number>] :buckets ([0.001, 0.01, 0.1, 1, 10, Infinity])

The boundaries of the histogram buckets, Infinity will be added even if it's not
specified by you to ensure that all spans are included.
CPU-spans are put into the smallest bucket with a limit longer than the span.

@option opts [Boolean] :stacked (false)

When true larger buckets include the sum of all smaller buckets in addition to
the number of seconds spent in CPU-spans that fell into that bucket directly.
When false each CPU-span will be put into exactly one bucket

@option opts [Boolean] :cumulative (false)

When true the values of each bucket will increase monotonically and the
derivative over time can be used to tell how much CPU was used by spans
in each bucket in the current monitoring interval.
When false the values of each bucket are only the amount of time spent
by CPU-spans in that bucket in the current monitoring interval.

@yieldparam [Hash<Float,Float>] histogram A histogram from bucket-size to

amount of CPU-time spent in that bucket.

@yieldparam [Time] from The start of the monitoring interval @yieldparam [Time] to The end of the monitoring interval

@example

# Create an input file suitable for feeding to gnuplot.
#
EM::monitor_histogram(stacked: true) do |hist, from, to|
  gnuplot_input.puts #{to.iso8601} #{hist.values.join(" ")}"
end
# File lib/em-monitor.rb, line 97
def self.monitor_histogram(opts = {}, &block)
  stacked    = !!opts[:stacked]
  cumulative = !!opts[:cumulative]
  interval   =   opts[:interval] || Monitor::DEFAULT_INTERVAL
  buckets    =  (opts[:buckets]  || Monitor::DEFAULT_BUCKETS).sort
  buckets << (1/0.0)

  # ensure the histogram keys are in the right order
  hist = buckets.each_with_object({}){ |bucket, h| h[bucket] = 0 }

  monitor_spans(opts) do |spans, from, to|

    unless cumulative
      hist = buckets.each_with_object({}){ |bucket, h| h[bucket] = 0 }
    end

    if stacked
      spans.each do |span|
        buckets.each do |bucket|
          hist[bucket] += span if bucket > span
        end
      end
    else
      spans.each do |span|
        hist[buckets.detect{ |bucket| bucket > span }] += span
      end
    end

    block.call hist, from, to
  end
end
monitor_spans(opts = {}, &block) click to toggle source

Set the block to be called periodically with timing data.

@param [Hash] opts Configuration @param [Proc] block the block to call.

@option opts [Number] :interval (60)

The approximate number of seconds between calls to your block.
If your event loop regularly runs long CPU-spans then the actual time between
calls can vary significantly.

@yieldparam [Array<Float>] spans The number of seconds spent by each CPU-span in the

monitoring interval

@yieldparam [Time] from The start of the monitoring interval @yieldparam [Time] to The end of the monitoring interval

@example

EM::monitor_spans do |spans, from, to|
  puts "Used %.2f seconds of CPU in the last %.2f seconds." % (spans.inject(&:+), to - from)
end
# File lib/em-monitor.rb, line 43
def self.monitor_spans(opts = {}, &block)
  raise "EventMachine not initialized" unless @monitor
  @monitor.monitor_spans(opts[:interval] || Monitor::DEFAULT_INTERVAL, &block)
end
run(*args, &block) click to toggle source

Run the eventmachine reactor with monitoring.

# File lib/em-monitor.rb, line 13
def self.run(*args, &block)
  run_without_monitor(*args) do |*a, &b|
    EM::Monitor.new do |monitor|
      @monitor = monitor
      block.call(*a, &b) if block_given?
    end
  end
ensure
  @monitor = nil
end
Also aliased as: run_without_monitor
run_without_monitor(*args, &block)
Alias for: run