Module: Observability

Extended by:
Loggability
Defined in:
lib/observability.rb

Overview

A mixin that adds effortless Observability to your systems.

Defined Under Namespace

Modules: Instrumentation, ObserverHooks Classes: Collector, Event, Observer, Sender

Constant Summary collapse

VERSION =

Package version

'0.4.0'
REVISION =

Version control revision

%q$Revision$
DEFAULT_PORT =

The default port to use for network communications

15775

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#observer_hooksObject (readonly)

Returns the value of attribute observer_hooks.



40
41
42
# File 'lib/observability.rb', line 40

def observer_hooks
  @observer_hooks
end

Class Method Details

.[](mod) ⇒ Object

Get the observer hooks for the specified mod.



46
47
48
49
# File 'lib/observability.rb', line 46

def self::[]( mod )
  mod = mod.class unless mod.is_a?( Module )
  return self.observer_hooks[ mod ]
end

.extended(mod) ⇒ Object

Extension callback



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/observability.rb', line 53

def self::extended( mod )
  super

  Observability.observer_hooks.compute_if_absent( mod ) do
    observer_hooks = Observability::ObserverHooks.dup
    mod.prepend( observer_hooks )
    observer_hooks
  end

  mod.singleton_class.extend( Observability ) unless mod.singleton_class?
end

.install_instrumentation(*libraries) ⇒ Object

Install the default instrumentatin for one or more libraries.



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

def self::install_instrumentation( *libraries )
  Observability::Instrumentation.load( *libraries )
  Observability::Instrumentation.install
end

.make_wrapped_method(name, context, options, &callback) ⇒ Object

Make a body for a wrapping method for the method with the given name and context, passing the given options.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/observability.rb', line 98

def self::make_wrapped_method( name, context, options, &callback )

  # Supering into arity-zero methods with (empty) *args and **options raises an
  # ArgumentError for some reason.
  if context.first.arity.zero?
    return Proc.new do |*m_args, **m_options, &block|
      Loggability[ Observability ].debug "Wrapped zero-arity method %p: %p" %
        [ name, context ]
      Observability.observer.event( context, **options ) do
        callback.call( *m_args, **m_options, &block ) if callback
        super( *m_args, &block )
      end
    end
  else
    return Proc.new do |*m_args, **m_options, &block|
      Loggability[ Observability ].debug "Wrapped method %p: %p" %
        [ name, context ]
      Observability.observer.event( context, **options ) do
        # :TODO: Freeze or dup the arguments to prevent accidental modification?
        callback.call( *m_args, **m_options, &block ) if callback
        super( *m_args, **m_options, &block )
      end
    end
  end
end

.observerObject

Return the current Observer, creating it if necessary.



74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/observability.rb', line 74

def self::observer
  unless @observer.complete?
    self.log.debug "Creating the observer agent."
    @observer.try_set do
      obs = Observability::Observer.new
      obs.start
      obs
    end
  end

  return @observer.value!
end

.resetObject

Reset all per-process Observability state. This should be called, for instance, after a fork or between tests.



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

def self::reset
  @observer.value.stop if @observer.complete?
  @observer = Concurrent::IVar.new
end

Instance Method Details

#observe_class_method(method_name, *details, **options, &callback) ⇒ Object

Wrap a class method in an observer call.



142
143
144
# File 'lib/observability.rb', line 142

def observe_class_method( method_name, *details, **options, &callback )
  self.singleton_class.observe_method( method_name, *details, **options, &callback )
end

#observe_method(method_name, *details, **options, &callback) ⇒ Object

Wrap an instance method in an observer call.



129
130
131
132
133
134
135
136
137
138
# File 'lib/observability.rb', line 129

def observe_method( method_name, *details, **options, &callback )
  hooks = Observability.observer_hooks[ self ] or
    raise "No observer hooks installed for %p?!" % [ self ]

  context = self.instance_method( method_name )
  context = [ context, *details ]
  method_body = Observability.make_wrapped_method( method_name, context, options, &callback )

  hooks.define_method( method_name, &method_body )
end