Class: Arborist::Observer::Action

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

Overview

An action taken by an Observer.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(within: 0, after: 1, during: nil, ignore_flapping: false, &block) ⇒ Action

Create a new Action that will call the specified block during the given schedule, but only after the specified number of events have arrived within the given time threshold.

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/arborist/observer/action.rb', line 22

def initialize( within: 0, after: 1, during: nil, ignore_flapping: false, &block )
	raise ArgumentError, "Action requires a block" unless block

	@block           = block
	@time_threshold  = within
	@schedule        = Schedulability::Schedule.parse( during ) if during
	@ignore_flapping = ignore_flapping

	if within.zero?
		@count_threshold = after
	else
		# It should always be 2 or more if there is a time threshold
		@count_threshold = [ after, 2 ].max
	end

	@event_history = {}
end

Instance Attribute Details

#blockObject (readonly)

The object to #call when the action is triggered.



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

def block
  @block
end

#count_thresholdObject (readonly)

The minimum number of events that cause the action to be called when the #time_threshold is met.



56
57
58
# File 'lib/arborist/observer/action.rb', line 56

def count_threshold
  @count_threshold
end

#event_historyObject (readonly)

The Hash of recent events, keyed by their arrival time.



69
70
71
# File 'lib/arborist/observer/action.rb', line 69

def event_history
  @event_history
end

#ignore_flappingObject (readonly)

Take no action if the node the event belongs to is in a flapping state.



65
66
67
# File 'lib/arborist/observer/action.rb', line 65

def ignore_flapping
  @ignore_flapping
end

#scheduleObject (readonly)

The schedule that applies to this action.



60
61
62
# File 'lib/arborist/observer/action.rb', line 60

def schedule
  @schedule
end

#time_thresholdObject (readonly)

The maximum number of seconds between events that cause the action to be called



51
52
53
# File 'lib/arborist/observer/action.rb', line 51

def time_threshold
  @time_threshold
end

Instance Method Details

#call_block(event) ⇒ Object

Execute the action block with the specified event.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/arborist/observer/action.rb', line 81

def call_block( event )
	if self.block.arity >= 2 || self.block.arity < 0
		self.block.call( event.dup, self.event_history.dup )
	else
		self.block.call( event.dup )
	end
rescue => err
	self.log.error "Exception while running observer: %s: %s\n%s" % [
		err.class.name,
		err.message,
		err.backtrace.join("\n  ")
	]
ensure
	self.event_history.clear
end

#count_threshold_exceeded?Boolean

Returns true if the number of events in the event history meet or exceed the #count_threshold.

Returns:

  • (Boolean)


140
141
142
# File 'lib/arborist/observer/action.rb', line 140

def count_threshold_exceeded?
	return self.event_history.size >= self.count_threshold
end

#flapping?(event) ⇒ Boolean

Returns true if this observer respects the flapping state of a node, and the generated event is attached to a flapping node.

Returns:

  • (Boolean)


118
119
120
# File 'lib/arborist/observer/action.rb', line 118

def flapping?( event )
	return self.ignore_flapping && event[ 'flapping' ]
end

#handle_event(event) ⇒ Object

Call the action for the specified event.



73
74
75
76
# File 'lib/arborist/observer/action.rb', line 73

def handle_event( event )
	self.record_event( event )
	self.call_block( event ) if self.should_run? && ! self.flapping?( event )
end

#record_event(event) ⇒ Object

Record the specified event in the event history if within the scheduled period(s).



99
100
101
102
103
104
105
106
# File 'lib/arborist/observer/action.rb', line 99

def record_event( event )
	return if self.schedule && !self.schedule.now?
	self.event_history[ Time.now ] = event
	self.event_history.keys.sort.each do |event_time|
		break if self.event_history.size <= self.count_threshold
		self.event_history.delete( event_time )
	end
end

#should_run?Boolean

Returns true if the threshold is exceeded and the current time is within the action’s schedule.

Returns:

  • (Boolean)


111
112
113
# File 'lib/arborist/observer/action.rb', line 111

def should_run?
	return self.time_threshold_exceeded? && self.count_threshold_exceeded?
end

#time_threshold_exceeded?Boolean

Returns true if the time between the first and last event in the #event_history is less than the #time_threshold.

Returns:

  • (Boolean)


125
126
127
128
129
130
131
132
133
134
135
# File 'lib/arborist/observer/action.rb', line 125

def time_threshold_exceeded?
	return true if self.time_threshold.zero?
	return false unless self.count_threshold_exceeded?

	first = self.event_history.keys.min
	last = self.event_history.keys.max

	self.log.debug "Time between the %d events in the record (%p): %0.5fs" %
		[ self.event_history.size, self.event_history, last - first ]
	return last - first <= self.time_threshold
end