Class: REC::State
- Inherits:
-
Object
- Object
- REC::State
- Defined in:
- lib/rec/state.rb
Overview
A State is an object that represents the memory of something having happened. For example, “server terra is down”. It also remembers useful statistics about what caused this state to be (the original log entries and the rule they matched), for how long it should remain in memory, what it pertains to (eg. the server called ‘terra’).
A state is also useful for other rules to refer to. For example, a second rule matching “host terra is up” can check if the server is currently down by reference to the state with a title of “host terra is down”.
This is much more useful than matching log entries one by one without any memory of what has gone before. You cannot correlate events without keeping State.
Constant Summary collapse
- Generate =
shortcut action to generate a message on each event
Proc.new { |state| state.generate() }
- Generate_and_release =
shortcut action to generate a message and release the state immediately
Proc.new { |state| state.generate() state.release() }
- Generate_first_only =
shortcut action to generate a message on first event only
Proc.new { |state| state.generate_first_only() }
- @@timeouts =
A array of Timeouts. A Timeout struct has two elements:
-
timestamp at which to expire
-
key of the state to be expired
-
[]
- @@states =
A hash of states, keyed on state title
{}
- @@eventsOut =
A count of new events sent to output
0
Instance Attribute Summary collapse
-
#alert ⇒ Object
readonly
An alert message to be sent if subsequent events warrant it.
-
#count ⇒ Object
readonly
Number of times this state has been matched.
-
#created ⇒ Object
readonly
time when this state was created.
-
#details ⇒ Object
readonly
Hash of custom fields to be remembered.
-
#final ⇒ Object
readonly
An alert message to be sent when the state expires.
-
#lifespan ⇒ Object
readonly
How long this state shoudl live before being automatically forgotten.
-
#logs ⇒ Object
readonly
Array of original log entries matching this state.
-
#params ⇒ Object
readonly
Hash of parameters of the rule that created this state.
-
#rid ⇒ Object
readonly
unique ID of the rule which gave rise to this state.
-
#title ⇒ Object
readonly
The unique title for this state (eg. “server earth is down”).
-
#updated ⇒ Object
readonly
last time this state was updated.
Class Method Summary collapse
-
.[](key) ⇒ Object
Returns the state matching the given key (title).
-
.expire_states ⇒ Object
Deletes all expired states, executing :onexpiry blocks before deletion.
-
.find(template, state) ⇒ Object
Returns a matching state or nil.
-
.stats ⇒ Object
Returns a 2-element array containing: - the number of states - the number of new events sent to output.
-
.timeout_at(time, title) ⇒ Object
Add a Timeout for the given time and specified state.
Instance Method Summary collapse
-
#age ⇒ Object
Returns the age of this state.
-
#extend_for(dur) ⇒ Object
Resets the expiry time to be
dur
seconds after current time (this may be shorter than the original lifetime). -
#generate(sym = :alert) ⇒ Object
Creates a new event, writes it to the output log, and returns the event.
-
#generate_first_only(sym = :alert) ⇒ Object
Creates a new event when this state is created, but ignores later occurrences.
-
#initialize(title, lifespan, params = {}) ⇒ State
constructor
Creates a new state with the given (unique)
title
, thelifespan
before the state is forgotten, and a hash of parameters. -
#method_missing(symbol, *args) ⇒ Object
Allow access to any parameter by a convenience method state.capture is more succinct than state.params.
-
#release(pattern = nil) ⇒ Object
Forget a state.
-
#stats ⇒ Object
Returns the details of the state (ie. whatever custom fields were defined, eg. userid) merged with the standard statistics: - count: number of matches so far - age: age of the state - created: time when this state was created - updated: time last updated (eg. when the latest event matched this state).
-
#update(rid, matches, logLine = nil) ⇒ Object
Updates the statistics of this state (following a match).
Constructor Details
#initialize(title, lifespan, params = {}) ⇒ State
Creates a new state with the given (unique) title
, the lifespan
before the state is forgotten, and a hash of parameters.
Note that the time is not necessarily ‘now’ because REC can be executed against historical log files. It uses the timestamp of the original log entry, not the current clock time.
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/rec/state.rb', line 135 def initialize(title, lifespan, params={}) @created = @updated = Correlator.now() @title = title @lifespan = lifespan.to_f @params = params @count = 0 @rid = 0 @logs = [] # array of remembered logLines @details = {} # hash of remembered details @@states[title] = self State.timeout_at(@created + @lifespan, @title) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args) ⇒ Object
Allow access to any parameter by a convenience method state.capture is more succinct than state.params
229 230 231 |
# File 'lib/rec/state.rb', line 229 def method_missing(symbol, *args) @params[symbol] end |
Instance Attribute Details
#alert ⇒ Object (readonly)
An alert message to be sent if subsequent events warrant it
113 114 115 |
# File 'lib/rec/state.rb', line 113 def alert @alert end |
#count ⇒ Object (readonly)
Number of times this state has been matched
119 120 121 |
# File 'lib/rec/state.rb', line 119 def count @count end |
#created ⇒ Object (readonly)
time when this state was created
121 122 123 |
# File 'lib/rec/state.rb', line 121 def created @created end |
#details ⇒ Object (readonly)
Hash of custom fields to be remembered
125 126 127 |
# File 'lib/rec/state.rb', line 125 def details @details end |
#final ⇒ Object (readonly)
An alert message to be sent when the state expires
115 116 117 |
# File 'lib/rec/state.rb', line 115 def final @final end |
#lifespan ⇒ Object (readonly)
How long this state shoudl live before being automatically forgotten
111 112 113 |
# File 'lib/rec/state.rb', line 111 def lifespan @lifespan end |
#logs ⇒ Object (readonly)
Array of original log entries matching this state
127 128 129 |
# File 'lib/rec/state.rb', line 127 def logs @logs end |
#params ⇒ Object (readonly)
Hash of parameters of the rule that created this state
117 118 119 |
# File 'lib/rec/state.rb', line 117 def params @params end |
#rid ⇒ Object (readonly)
unique ID of the rule which gave rise to this state
107 108 109 |
# File 'lib/rec/state.rb', line 107 def rid @rid end |
#title ⇒ Object (readonly)
The unique title for this state (eg. “server earth is down”)
109 110 111 |
# File 'lib/rec/state.rb', line 109 def title @title end |
#updated ⇒ Object (readonly)
last time this state was updated
123 124 125 |
# File 'lib/rec/state.rb', line 123 def updated @updated end |
Class Method Details
.[](key) ⇒ Object
Returns the state matching the given key (title)
50 51 52 |
# File 'lib/rec/state.rb', line 50 def self.[](key) @@states[key] end |
.expire_states ⇒ Object
Deletes all expired states, executing :onexpiry blocks before deletion
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/rec/state.rb', line 69 def self.expire_states() timeout = @@timeouts.first() while @@timeouts.length > 0 and timeout.expiry < Correlator.now() do state = State[timeout.key] if state.nil? @@timeouts.shift timeout = @@timeouts.first() next end #$stderr.puts("Releasing state #{state.title} with count of #{state.count}") final = Rule[state.rid].params[:final] final.call(state) if final @@states.delete(@@timeouts.shift().key) timeout = @@timeouts.first() end end |
.find(template, state) ⇒ Object
Returns a matching state or nil.
This is used to locate a state, typically the other state created by a pair of rules. For example, in a rule handling “Server earth is up” we want to find the state corresponding to “Server earth is down”
-
template is a string like “Server %host$s is down”
-
state is the current state
101 102 103 104 |
# File 'lib/rec/state.rb', line 101 def self.find(template, state) title = template.sprinth(state.params) @@states[title] end |
.stats ⇒ Object
Returns a 2-element array containing:
-
the number of states
-
the number of new events sent to output
89 90 91 92 |
# File 'lib/rec/state.rb', line 89 def self.stats() statesCount = @@states.keys.length [statesCount, @@eventsOut] end |
.timeout_at(time, title) ⇒ Object
Add a Timeout for the given time and specified state. This timeout is sorted into the correct sequence of timeouts to make State::expire_states more efficient.
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/rec/state.rb', line 56 def self.timeout_at(time, title) tnew = Struct::Timeout.new(time, title) n = @@timeouts.find_index { |to| to.expiry > time } if n.nil? @@timeouts = @@timeouts << tnew else @@timeouts[n..n] = [tnew, @@timeouts[n]] end end |
Instance Method Details
#age ⇒ Object
Returns the age of this state
166 167 168 |
# File 'lib/rec/state.rb', line 166 def age Correlator.now() - @created end |
#extend_for(dur) ⇒ Object
Resets the expiry time to be dur
seconds after current time (this may be shorter than the original lifetime)
186 187 188 189 190 191 192 193 |
# File 'lib/rec/state.rb', line 186 def extend_for(dur) n = @@timeouts.find_index { |to| to.title == @title } @@timeouts[n..n] = [] unless n.nil? expiry = Correlator.now() + dur self.timeout_at(expiry, @title) end |
#generate(sym = :alert) ⇒ Object
Creates a new event, writes it to the output log, and returns the event. An event (or ‘log entry’) is a timestamp followed by a message
Returns the message only (without the timestamp).
209 210 211 212 213 214 215 216 217 218 |
# File 'lib/rec/state.rb', line 209 def generate(sym = :alert) = @params[sym].sprinth(stats()) if .length > 0 event = "%s %s" % [@created.iso8601, ] + @logs.join("\n") print("> ") if $debug puts(event) @@eventsOut = @@eventsOut + 1 end end |
#generate_first_only(sym = :alert) ⇒ Object
Creates a new event when this state is created, but ignores later occurrences
221 222 223 |
# File 'lib/rec/state.rb', line 221 def generate_first_only(sym = :alert) generate(sym) if @count == 1 end |
#release(pattern = nil) ⇒ Object
Forget a state. - if no pattern is provided, forget this state. - if a pattern is provided, use the stats for this state to determine the title of the other state, and remove that from memory. For example, if the server is back up again, we no longer need to remember that the server was down.
176 177 178 179 180 181 182 |
# File 'lib/rec/state.rb', line 176 def release(pattern=nil) if pattern.nil? @@states.delete(@title) else @@states.delete(pattern.sprinth(stats())) end end |
#stats ⇒ Object
Returns the details of the state (ie. whatever custom fields were defined, eg. userid) merged with the standard statistics:
-
count: number of matches so far
-
age: age of the state
-
created: time when this state was created
-
updated: time last updated (eg. when the latest event matched this state)
201 202 203 |
# File 'lib/rec/state.rb', line 201 def stats() @details.merge({"count"=>@count, "age"=>age(), "created"=>@created, "updated"=>@updated}) end |
#update(rid, matches, logLine = nil) ⇒ Object
Updates the statistics of this state (following a match). Remembers lots of useful things: - the number of matches so far
-
time last updated
-
age of this state
-
the ID of the rule which last matched
-
more details (custom fields) may be added to memory
-
message templates (for values to be interpolated into)
-
a list of the original log entries pertaining to this state
157 158 159 160 161 162 163 |
# File 'lib/rec/state.rb', line 157 def update(rid, matches, logLine=nil) @count = @count.succ @updated = Correlator.now() @rid = rid @details.merge!(matches) @logs << logLine if @params[:capture] end |