rec 1.2.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +6 -1
- data/README +2 -0
- data/RUNNING +26 -0
- data/lib/rec/correlator.rb +3 -7
- data/lib/rec/rule.rb +6 -5
- data/lib/rec/state.rb +28 -2
- metadata +5 -4
data/CHANGELOG
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
===
|
1
|
+
=== Version 1.3.0
|
2
|
+
- Allow for pre-setting the file descriptors: $stdin, $stdout, $stderr, $miss
|
3
|
+
- Prevent events being logged as missed when they matched but not fully
|
4
|
+
- Added Notify_duration and Log_duration as State shortcuts
|
5
|
+
|
6
|
+
=== Version 1.2.3
|
2
7
|
- Recognise more date patterns
|
3
8
|
- Improved performance
|
4
9
|
|
data/README
CHANGED
@@ -231,3 +231,5 @@ refer to any parameter succinctly instead of a cumbersome hash notation, so:
|
|
231
231
|
state.threshold === state.params['threshold']
|
232
232
|
|
233
233
|
For more examples, see the link:file.EXAMPLES.html page.
|
234
|
+
For an example of how to execute a ruleset, see link:file.RUNNING page.
|
235
|
+
|
data/RUNNING
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
== Running REC
|
2
|
+
Here is an example script for executing REC as a daemon with a given name:
|
3
|
+
|
4
|
+
#!/usr/local/bin/ruby
|
5
|
+
# change process name. shows as "ruby: mymonitord"
|
6
|
+
$0 = "mymonitord"
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'rec'
|
10
|
+
include REC
|
11
|
+
|
12
|
+
$stdin = File.open("/var/mymon/logs/mymon.log", "r")
|
13
|
+
$stdout = File.open("/var/mymon/logs/rec.log" ,"a")
|
14
|
+
$miss = File.open("/var/mymon/logs/miss.log" ,"a")
|
15
|
+
$sterr = File.open("/var/mymon/logs/summary.log" ,"a")
|
16
|
+
|
17
|
+
load '/var/mymon/rulesets/credentials.rec'
|
18
|
+
load '/var/mymon/rulesets/mymon.rec'
|
19
|
+
|
20
|
+
Correlator::start(:debug=>true)
|
21
|
+
|
22
|
+
The credentials for sending emails and IMs are held in credentials, and the rules in mymon.rec
|
23
|
+
|
24
|
+
I find it easier to set up file descriptor redirection in this way than using command line notation.
|
25
|
+
|
26
|
+
|
data/lib/rec/correlator.rb
CHANGED
@@ -44,11 +44,7 @@ class Correlator
|
|
44
44
|
run()
|
45
45
|
}
|
46
46
|
$stderr.puts("rec is starting...")
|
47
|
-
|
48
|
-
$miss = IO.open(3, "a") # for missed events
|
49
|
-
rescue
|
50
|
-
$miss = nil
|
51
|
-
end
|
47
|
+
$miss ||= IO.open(3, "a") # write out to &3 for missed events, unless $miss is pre-defined
|
52
48
|
@running = true
|
53
49
|
run()
|
54
50
|
end
|
@@ -71,8 +67,8 @@ class Correlator
|
|
71
67
|
State.expire_states() # remove expired states before we check the rules
|
72
68
|
eventMatched = false
|
73
69
|
Rule.each { |rule|
|
74
|
-
title = rule.check(message)
|
75
|
-
eventMatched
|
70
|
+
matchok, title = rule.check(message)
|
71
|
+
eventMatched ||= matchok
|
76
72
|
next if title.nil?
|
77
73
|
break if title.empty? # match without a message means 'swallow this event'
|
78
74
|
state = State[title] || rule.create_state(title)
|
data/lib/rec/rule.rb
CHANGED
@@ -108,19 +108,20 @@ class Rule
|
|
108
108
|
end
|
109
109
|
|
110
110
|
# Checks the original +logMessage+ against the rule, looking for a match.
|
111
|
+
# Returns a boolean (true if entry matched the pattern), and a string
|
111
112
|
def check(logMessage)
|
112
113
|
@@checked[@rid] += 1
|
113
|
-
matchData = @pattern.match(logMessage)
|
114
|
+
return [false, nil] unless matchData = @pattern.match(logMessage)
|
114
115
|
@matches = Hash[@details.zip(matchData.to_a()[1..-1])] # map matched values to detail keys
|
115
116
|
# if any notstates are specified, make sure none are present
|
116
|
-
@notstates.each { |str| return if State[str.sprinth(@matches)] }
|
117
|
+
@notstates.each { |str| return([true, nil]) if State[str.sprinth(@matches)] }
|
117
118
|
# if any allstates are specified, they all need to be present
|
118
|
-
@allstates.each { |str| return unless State[str.sprinth(@matches)] }
|
119
|
+
@allstates.each { |str| return([true, nil]) unless State[str.sprinth(@matches)] }
|
119
120
|
# if anystates are specified, we must find one that matches
|
120
|
-
return unless @anystates.empty? or @anystates.detect {|str| State[str.sprinth(@matches)] }
|
121
|
+
return([true, nil]) unless @anystates.empty? or @anystates.detect {|str| State[str.sprinth(@matches)] }
|
121
122
|
title = @message.sprinth(@matches)
|
122
123
|
@@matched[@rid] += 1
|
123
|
-
return(title)
|
124
|
+
return([true, title])
|
124
125
|
end
|
125
126
|
|
126
127
|
# Creates a state with the given title at the specified time
|
data/lib/rec/state.rb
CHANGED
@@ -22,9 +22,8 @@ class State
|
|
22
22
|
state.generate()
|
23
23
|
}
|
24
24
|
|
25
|
-
# shortcut action to ignore an event
|
25
|
+
# shortcut action to ignore an event, but leave the state to expire
|
26
26
|
Ignore = Proc.new { |state|
|
27
|
-
state.release()
|
28
27
|
}
|
29
28
|
|
30
29
|
# shortcut action to generate a message and release the state immediately
|
@@ -58,6 +57,28 @@ class State
|
|
58
57
|
state.release()
|
59
58
|
}
|
60
59
|
|
60
|
+
Notify_duration = Proc.new { |state|
|
61
|
+
# We must have only one allstate, which is the original state (eg. "server down")
|
62
|
+
orig = state.params[:allstates][0] # get the original state's key
|
63
|
+
duration = state.find(original).age
|
64
|
+
# we expect to have :alert containing "%duration$d minutes"
|
65
|
+
state.details["duration"] = duration.to_i()/60 # store the outage duration
|
66
|
+
Notify.normal(state.generate()) # send the notice
|
67
|
+
state.release(original) # forget both
|
68
|
+
state.release()
|
69
|
+
}
|
70
|
+
|
71
|
+
Log_duration = Proc.new { |state|
|
72
|
+
# We must have only one allstate, which is the original state (eg. "process started")
|
73
|
+
orig = state.params[:allstates][0] # get the original state's key
|
74
|
+
duration = state.find(original).age
|
75
|
+
# we expect to have :alert containing "%duration$d minutes"
|
76
|
+
state.details["duration"] = duration.to_i()/60 # store the duration
|
77
|
+
state.generate() # record the event
|
78
|
+
state.release(original) # forget both
|
79
|
+
state.release()
|
80
|
+
}
|
81
|
+
|
61
82
|
# A array of Timeouts. A Timeout struct has two elements:
|
62
83
|
# - timestamp at which to expire
|
63
84
|
# - key of the state to be expired
|
@@ -248,6 +269,11 @@ class State
|
|
248
269
|
generate(sym) if @count == 1
|
249
270
|
end
|
250
271
|
|
272
|
+
# Convenience method to find another state, based on parameters in this state
|
273
|
+
def find(template)
|
274
|
+
self.find(template, self)
|
275
|
+
end
|
276
|
+
|
251
277
|
# Allow access to any parameter by a convenience method
|
252
278
|
# state.capture
|
253
279
|
# is more succinct than
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
- 2
|
9
8
|
- 3
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 1.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Richard Kernahan
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-10-
|
18
|
+
date: 2012-10-03 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: xmpp4r
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- EXAMPLES
|
64
64
|
- MULTIPLEX
|
65
65
|
- LICENSE
|
66
|
+
- RUNNING
|
66
67
|
- CHANGELOG
|
67
68
|
homepage: http://rubygems.org/gems/rec
|
68
69
|
licenses: []
|