# 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