class Puppet::Util::Instrumentation

Attributes

listeners[RW]
listeners_of[RW]

Public Class Methods

[](key) click to toggle source
# File lib/puppet/util/instrumentation.rb, line 145
def self.[](key)
  synchronize {
    @listeners[key.intern]
  }
end
[]=(key, value) click to toggle source
# File lib/puppet/util/instrumentation.rb, line 151
def self.[]=(key, value)
  synchronize {
    @listeners[key.intern] = value
    rehash
  }
end
clear() click to toggle source
# File lib/puppet/util/instrumentation.rb, line 137
def self.clear
  synchronize {
    @listeners = {}
    @listeners_of = {}
    @id = 0
  }
end
each_listener(label) { |l| ... } click to toggle source
# File lib/puppet/util/instrumentation.rb, line 73
def self.each_listener(label)
  synchronize {
    @listeners_of[label] ||= @listeners.select do |k,l|
      l.listen_to?(label)
    end
  }.each do |l|
    yield l
  end
end
init() click to toggle source
# File lib/puppet/util/instrumentation.rb, line 127
def self.init
  # let's init our probe indirection
  require 'puppet/util/instrumentation/indirection_probe'
  synchronize {
    @listeners ||= {}
    @listeners_of ||= {}
    instance_loader(:listener).loadall
  }
end
instrument(label, data = {}) { || ... } click to toggle source

Triggers an instrumentation

Call this method around the instrumentation point

Puppet::Util::Instrumentation.instrument(:my_long_computation) do
  ... a long computation
end

This will send an event to all the listeners of “my_long_computation”. Note: this method uses ruby yield directive to call the instrumented code. It is usually way slower than calling start and stop directly around the instrumented code. For high traffic code path, it is thus advisable to not use this method.

# File lib/puppet/util/instrumentation.rb, line 36
def self.instrument(label, data = {})
  id = self.start(label, data)
  yield
ensure
  self.stop(label, id, data)
end
new_listener(name, options = {}, &block) click to toggle source

Adds a new listener

Usage:

Puppet::Util::Instrumentation.new_listener(:my_instrumentation, pattern) do

  def notify(label, data)
    ... do something for data...
  end
end

It is possible to use a “pattern”. The listener will be notified only if the pattern match the label of the event. The pattern can be a symbol, a string or a regex. If no pattern is provided, then the listener will be called for every events

# File lib/puppet/util/instrumentation.rb, line 97
def self.new_listener(name, options = {}, &block)
  Puppet.debug "new listener called #{name}"
  name = name.intern
  listener = genclass(name, :hash => instance_hash(:listener), :block => block)
  listener.send(:define_method, :name) do
    name
  end
  subscribe(listener.new, options[:label_pattern], options[:event])
end
publish(label, event, data) click to toggle source
# File lib/puppet/util/instrumentation.rb, line 63
def self.publish(label, event, data)
  each_listener(label) do |k,l|
    l.notify(label, event, data)
  end
end
start(label, data) click to toggle source

Triggers a “start” instrumentation event

Important note:

For proper use, the data hash instance used for start should also
be used when calling stop. The idea is to use the current scope
where start is called to retain a reference to 'data' so that it is possible
to send it back to stop.
This way listeners can match start and stop events more easily.
# File lib/puppet/util/instrumentation.rb, line 51
def self.start(label, data)
  data[:started] = Time.now
  publish(label, :start, data)
  data[:id] = next_id
end
stop(label, id, data) click to toggle source

Triggers a “stop” instrumentation event

# File lib/puppet/util/instrumentation.rb, line 58
def self.stop(label, id, data)
  data[:finished] = Time.now
  publish(label, :stop, data)
end
subscribe(listener, label_pattern, event) click to toggle source
# File lib/puppet/util/instrumentation.rb, line 107
def self.subscribe(listener, label_pattern, event)
  synchronize {
    raise "Listener #{listener.name} is already subscribed" if @listeners.include?(listener.name)
    Puppet.debug "registering instrumentation listener #{listener.name}"
    @listeners[listener.name] = Listener.new(listener, label_pattern, event)
    listener.subscribed if listener.respond_to?(:subscribed)
    rehash
  }
end
unsubscribe(listener) click to toggle source
# File lib/puppet/util/instrumentation.rb, line 117
def self.unsubscribe(listener)
  synchronize {
    Puppet.warning("#{listener.name} hasn't been registered but asked to be unregistered") unless @listeners.include?(listener.name)
    Puppet.info "unregistering instrumentation listener #{listener.name}"
    @listeners.delete(listener.name)
    listener.unsubscribed if listener.respond_to?(:unsubscribed)
    rehash
  }
end