Class: Puppet::Util::Instrumentation

Inherits:
Object
  • Object
show all
Extended by:
ClassGen, InstanceLoader
Defined in:
lib/puppet/util/instrumentation.rb

Defined Under Namespace

Modules: Instrumentable Classes: Data, IndirectionProbe, Listener

Constant Summary

Constants included from Puppet::Util

AbsolutePathPosix, AbsolutePathWindows, DEFAULT_POSIX_MODE, DEFAULT_WINDOWS_MODE

Constants included from POSIX

POSIX::LOCALE_ENV_VARS, POSIX::USER_ENV_VARS

Constants included from SymbolicFileMode

SymbolicFileMode::SetGIDBit, SymbolicFileMode::SetUIDBit, SymbolicFileMode::StickyBit, SymbolicFileMode::SymbolicMode, SymbolicFileMode::SymbolicSpecialToBit

Class Attribute Summary collapse

Class Method Summary collapse

Methods included from ClassGen

genclass, genmodule, rmclass

Methods included from Puppet::Util

absolute_path?, activerecord_version, benchmark, binread, chuser, classproxy, deterministic_rand, execfail, execpipe, execute, exit_on_fail, logmethods, memory, path_to_uri, pretty_backtrace, proxy, replace_file, safe_posix_fork, symbolizehash, thinmark, uri_to_path, which, withenv, withumask

Methods included from POSIX

#get_posix_field, #gid, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid

Methods included from SymbolicFileMode

#normalize_symbolic_mode, #symbolic_mode_to_int, #valid_symbolic_mode?

Methods included from MethodHelper

#requiredopts, #set_options, #symbolize_options

Methods included from InstanceLoader

instance_docs, instance_hash, instance_load, instance_loader, instance_loading?, loaded_instance, loaded_instances

Class Attribute Details

.listenersObject



19
20
21
# File 'lib/puppet/util/instrumentation.rb', line 19

def listeners
  @listeners
end

.listeners_ofObject



19
20
21
# File 'lib/puppet/util/instrumentation.rb', line 19

def listeners_of
  @listeners_of
end

Class Method Details

.[](key) ⇒ Object



134
135
136
# File 'lib/puppet/util/instrumentation.rb', line 134

def self.[](key)
  @listeners[key.intern]
end

.[]=(key, value) ⇒ Object



138
139
140
141
# File 'lib/puppet/util/instrumentation.rb', line 138

def self.[]=(key, value)
  @listeners[key.intern] = value
  rehash
end

.clearObject



128
129
130
131
132
# File 'lib/puppet/util/instrumentation.rb', line 128

def self.clear
  @listeners = {}
  @listeners_of = {}
  @id = 0
end

.each_listener(label) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/puppet/util/instrumentation.rb', line 72

def self.each_listener(label)
  @listeners_of[label] ||= @listeners.select do |k,l|
    l.listen_to?(label)
  end.each do |l|
    yield l
  end
end

.initObject



120
121
122
123
124
125
126
# File 'lib/puppet/util/instrumentation.rb', line 120

def self.init
  # let's init our probe indirection
  require 'puppet/util/instrumentation/indirection_probe'
  @listeners ||= {}
  @listeners_of ||= {}
  instance_loader(:listener).loadall
end

.instrument(label, data = {}) ⇒ Object

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.



35
36
37
38
39
40
# File 'lib/puppet/util/instrumentation.rb', line 35

def self.instrument(label, data = {})
  id = self.start(label, data)
  yield
ensure
  self.stop(label, id, data)
end

.new_listener(name, options = {}, &block) ⇒ Object

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



94
95
96
97
98
99
100
101
102
# File 'lib/puppet/util/instrumentation.rb', line 94

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) ⇒ Object



62
63
64
65
66
# File 'lib/puppet/util/instrumentation.rb', line 62

def self.publish(label, event, data)
  each_listener(label) do |k,l|
    l.notify(label, event, data)
  end
end

.start(label, data) ⇒ Object

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.


50
51
52
53
54
# File 'lib/puppet/util/instrumentation.rb', line 50

def self.start(label, data)
  data[:started] = Time.now
  publish(label, :start, data)
  data[:id] = next_id
end

.stop(label, id, data) ⇒ Object

Triggers a “stop” instrumentation event



57
58
59
60
# File 'lib/puppet/util/instrumentation.rb', line 57

def self.stop(label, id, data)
  data[:finished] = Time.now
  publish(label, :stop, data)
end

.subscribe(listener, label_pattern, event) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/puppet/util/instrumentation.rb', line 104

def self.subscribe(listener, label_pattern, event)
  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) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/puppet/util/instrumentation.rb', line 112

def self.unsubscribe(listener)
  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