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