Class: Puppet::Util::Instrumentation

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

Defined Under Namespace

Modules: Instrumentable Classes: Data, IndirectionProbe, Listener

Constant Summary

Constants included from Puppet::Util

AbsolutePathPosix, AbsolutePathWindows

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, #execfail, #execpipe, execute, execute_posix, execute_windows, logmethods, memory, path_to_uri, proxy, replace_file, safe_posix_fork, symbolize, symbolizehash, symbolizehash!, synchronize_on, thinmark, #threadlock, uri_to_path, wait_for_output, which, withumask

Methods included from POSIX

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

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

Returns the value of attribute listeners.



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

def listeners
  @listeners
end

.listeners_ofObject

Returns the value of attribute listeners_of.



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

def listeners_of
  @listeners_of
end

Class Method Details

.[](key) ⇒ Object



145
146
147
148
149
# File 'lib/vendor/puppet/util/instrumentation.rb', line 145

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

.[]=(key, value) ⇒ Object



151
152
153
154
155
156
# File 'lib/vendor/puppet/util/instrumentation.rb', line 151

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

.clearObject



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

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

.each_listener(label) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/vendor/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

.initObject



127
128
129
130
131
132
133
134
135
# File 'lib/vendor/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 = {}) ⇒ 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.



36
37
38
39
40
41
# File 'lib/vendor/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) ⇒ 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



97
98
99
100
101
102
103
104
105
# File 'lib/vendor/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) ⇒ Object



63
64
65
66
67
# File 'lib/vendor/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) ⇒ 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.


51
52
53
54
55
# File 'lib/vendor/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) ⇒ Object

Triggers a “stop” instrumentation event



58
59
60
61
# File 'lib/vendor/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) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/vendor/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) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/vendor/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