Module: Observability::Instrumentation

Extended by:
Loggability
Included in:
Bunny, CZTop, Grape, PG, Rack, Sequel
Defined in:
lib/observability/instrumentation.rb

Overview

Utilities for loading and installing pre-packaged instrumentation for common libraries.

Defined Under Namespace

Modules: Bunny, CZTop, Grape, PG, Rack, Sequel

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#modulesObject (readonly)

:singleton-method: The Set of Instrumentation modules that are laoded



23
24
25
# File 'lib/observability/instrumentation.rb', line 23

def modules
  @modules
end

Class Method Details

.check_for_module(mod) ⇒ Object

Returns true if mod is defined and is a Module.



75
76
77
78
# File 'lib/observability/instrumentation.rb', line 75

def self::check_for_module( mod )
	self.log.debug "Checking for presence of `%s` module..." % [ mod ]
	Object.const_defined?( mod ) && Object.const_get( mod ).is_a?( Module )
end

.dependencies_met?(*module_names) ⇒ Boolean

Returns true if each of the given module_names are defined and are Module objects.

Returns:

  • (Boolean)


67
68
69
70
71
# File 'lib/observability/instrumentation.rb', line 67

def self::dependencies_met?( *module_names )
	return module_names.flatten.all? do |mod|
		self.check_for_module( mod )
	end
end

.extended(mod) ⇒ Object

Extension callback – declare some instance variables in the extending mod.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/observability/instrumentation.rb', line 40

def self::extended( mod )
	super

	if self.modules.add?( mod )
		self.log.info "Loaded %p" % [ mod ]
		mod.extend( Loggability )
		mod.log_to( :observability )
		mod.instance_variable_set( :@depends_on, Set.new )
		mod.instance_variable_set( :@requires, Set.new )
		mod.instance_variable_set( :@installation_callbacks, Set.new )
		mod.singleton_class.attr_reader( :installation_callbacks )
	else
		self.log.warn "Already loaded %p" % [ mod ]
	end
end

.installObject

Install loaded instrumentation if the requisite modules are present.



58
59
60
61
62
# File 'lib/observability/instrumentation.rb', line 58

def self::install
	self.modules.each do |mod|
		mod.install if mod.available?
	end
end

.load(*libraries) ⇒ Object

Load instrumentation for the specified libraries.



28
29
30
31
32
33
34
35
# File 'lib/observability/instrumentation.rb', line 28

def self::load( *libraries )
	libraries.flatten.each do |library|
		libfile = "observability/instrumentation/%s" % [ library ]
		require( libfile )
	end

	return self
end

Instance Method Details

#available?Boolean

Returns true if all of the modules registered with #depends_on are defined.

Returns:

  • (Boolean)


105
106
107
# File 'lib/observability/instrumentation.rb', line 105

def available?
	return Observability::Instrumentation.dependencies_met?( self.depends_on.to_a )
end

#depends_on(*modules) ⇒ Object

Declare modules that must be available for instrumentation to be loaded. If they are not present when the instrumentation loads, it will be skipped entirely.



84
85
86
87
# File 'lib/observability/instrumentation.rb', line 84

def depends_on( *modules )
	@depends_on.merge( modules.flatten )
	return @depends_on
end

#installObject

Call installation callbacks which meet their prerequistes.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/observability/instrumentation.rb', line 111

def install
	self.requires.each do |file|
		require( file )
	end
	self.installation_callbacks.each do |callback, dependencies|
		missing = dependencies.
			reject {|mod| Observability::Instrumentation.check_for_module(mod) }

		if missing.empty?
			self.log.debug "Instrumenting %s: %p" % [ dependencies.join(', '), callback ]
			callback.call
		else
			self.log.info "Skipping %p: missing %s" % [ callback, missing.join(', ') ]
		end
	end
rescue LoadError => err
	raise "%p while loading instrumentation"
end

#requires(*files) ⇒ Object

Specified files to require if this instrumentation is loaded.



91
92
93
94
# File 'lib/observability/instrumentation.rb', line 91

def requires( *files )
	@requires.merge( files.flatten )
	return @requires
end

#when_installed(*modules, &callback) ⇒ Object

Register a callback that will be called when instrumentation is installed, if and only if all of the given modules are present (may be empty).



99
100
101
# File 'lib/observability/instrumentation.rb', line 99

def when_installed( *modules, &callback )
	self.installation_callbacks.add( [callback, modules] )
end