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.2.0'
REVISION =

Version control revision

%q$Revision$

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.



37
38
39
# File 'lib/observability.rb', line 37

def observer_hooks
  @observer_hooks
end

Class Method Details

.[](mod) ⇒ Object

Get the observer hooks for the specified mod.



43
44
45
46
# File 'lib/observability.rb', line 43

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

.extended(mod) ⇒ Object

Extension callback



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/observability.rb', line 50

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.



64
65
66
67
# File 'lib/observability.rb', line 64

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.



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/observability.rb', line 95

def self::make_wrapped_method( name, context, options, &callback )
	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

.observerObject

Return the current Observer, creating it if necessary.



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/observability.rb', line 71

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.



87
88
89
90
# File 'lib/observability.rb', line 87

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.



125
126
127
# File 'lib/observability.rb', line 125

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.



112
113
114
115
116
117
118
119
120
121
# File 'lib/observability.rb', line 112

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