Class: Observability::Observer

Inherits:
Object
  • Object
show all
Extended by:
Loggability
Defined in:
lib/observability/observer.rb

Constant Summary collapse

SNAKE_CASE_SEPARATOR =

Pattern for finding places for underscores when changing a camel-cased string to a snake-cased one.

/(\P{Upper}\p{Upper}|\p{Lower}\P{Lower})/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sender_type = nil) ⇒ Observer

Create a new Observer that will send events via the specified sender.



24
25
26
27
28
# File 'lib/observability/observer.rb', line 24

def initialize( sender_type=nil )
	@sender = self.configured_sender( sender_type )
	@event_stack = Concurrent::ThreadLocalVar.new( &Array.method(:new) )
	@context_stack = Concurrent::ThreadLocalVar.new( &Array.method(:new) )
end

Instance Attribute Details

#senderObject (readonly)

The Observability::Sender used to deliver events



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

def sender
  @sender
end

Instance Method Details

#add(object = nil, **fields) ⇒ Object

Add an object and/or a Hash of fields to the current event.



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/observability/observer.rb', line 104

def add( object=nil, **fields )
	self.log.debug "Adding %p" % [ object || fields ]
	event = @event_stack.value.last or return

	if object
		object_fields = self.fields_from_object( object )
		fields = fields.merge( object_fields )
	end

	event.merge( fields )
end

#add_context(object = nil, **fields) ⇒ Object

Add the specified fields to the current event and any that are created before the current event is finished.



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/observability/observer.rb', line 119

def add_context( object=nil, **fields )
	self.log.debug "Adding context from %p" % [ object || fields ]
	current_context = @context_stack.value.last or return

	if object
		object_fields = self.fields_from_object( object )
		fields = fields.merge( object_fields )
	end

	current_context.merge!( fields )
end

#event(type, **options, &block) ⇒ Object

Create a new event with the specified type and make it the current one.



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

def event( type, **options, &block )
	type = self.type_from_object( type )
	fields = self.fields_from_options( options )

	parent = @event_stack.value.last
	event = Observability::Event.new( type, parent, **fields )
	@event_stack.value.push( event )

	new_context = @context_stack.value.last&.dup || {}
	@context_stack.value.push( new_context )

	return self.finish_after_block( event.object_id, &block ) if block
	return event.object_id
end

#finish(event_marker = nil) ⇒ Object

Finish the and send the current event, comparing it against event_marker and raising an exception if it’s provided but doesn’t match. – :TODO: Instead of raising, dequeue events up to the given marker if it

exists in the queue?


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

def finish( event_marker=nil )
	raise "Event mismatch" if
		event_marker && @event_stack.value.last.object_id != event_marker

	event = @event_stack.value.pop
	context = @context_stack.value.pop
	self.log.debug "Adding context %p (%d left) to finishing event." %
		[ context, @context_stack.value.length ]
	event.merge( context )

	self.log.debug "Finishing event: %p" % [ event ]
	self.sender.enqueue( event )

	return event
end

#finish_after_block(event_marker = nil, &block) ⇒ Object

Call the given block, then when it returns, finish the event that corresponds to the given marker.



93
94
95
96
97
98
99
100
# File 'lib/observability/observer.rb', line 93

def finish_after_block( event_marker=nil, &block )
	block.call( self )
rescue Exception => err
	self.add( err )
	raise
ensure
	self.finish( event_marker )
end

#has_pending_events?Boolean Also known as: pending_events?

Returns true if the Observer has events that are under construction.

Returns:

  • (Boolean)


139
140
141
# File 'lib/observability/observer.rb', line 139

def has_pending_events?
	return self.pending_event_count.nonzero? ? true : false
end

#pending_event_countObject

Return the depth of the stack of pending events.



133
134
135
# File 'lib/observability/observer.rb', line 133

def pending_event_count
	return @event_stack.value.length
end

#startObject

Start recording events and sending them.



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

def start
	self.sender.start
end

#stopObject

Stop recording and sending events.



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

def stop
	self.sender.stop
end