redis_alerting 1.1.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NDAxYmIwZDg4OWI1NzkxMWU3NjYwYTNhYjBhMDgyZWE4OGU4OTQ1Yg==
5
- data.tar.gz: !binary |-
6
- ODRlY2JlMTIyMzZiOWU5YTgwM2NlMjE4YjNlZGU2NGI3MDlkNmM2ZQ==
2
+ SHA1:
3
+ metadata.gz: 9002db58d2b36ba06bb23317c3bf5da1fe8a7699
4
+ data.tar.gz: 43fecfbb4fa2a032d0aa384b085504fa0c5c19a9
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ODlkNjRiMTQ3MzE3MzUwYzU1ZTU2OWI5YzdkMjYyYzk0ZmI4OGQ3NWEyOGE1
10
- NzRlNDM5YjA1NmU4MDkzNjQyN2E3ZWUzZDE4ZjIyYjI5Y2Q2OWIyMzQ0NTkx
11
- NjE0ZmE3ZDZlYTVlMjZmMmI3MGI2YzIwYTE2NzE1ZTZiMTVhYTg=
12
- data.tar.gz: !binary |-
13
- MTg2YWNiODQyZTg4NzgwNTVkZGIzZTAzMDVjMDE2OGUyYTcwMWE3MjBiMjUy
14
- MjlkM2M3Zjk5ZmEzOTkxOWRiYzY0ZmM3NDBkZmY1YTEyYWNkZjUwN2U5ZjZl
15
- N2UyZjQ1ZTA2NTljMGZlNGI4MzQ0Y2Q5NGRhYmZkMWZmZDlhMTg=
6
+ metadata.gz: 0693caadb5119b3cb42855c85d82a95155645455d3568f0641d80ee33c16bbe50e13f17522adf6cf9d5a03acfc839417d68724c4b9138d17c1b8369aeffe59f0
7
+ data.tar.gz: 95509af5f6264bb945082dc2dae47495b487d2159cf07bf6aa1c65473e0c6ad300b170319d17b5c48498987e7aefb725a34551f2ae91e8e01efbae91d26b1d28
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Robert McLeod
1
+ Copyright (c) 2014 Autogrow Systems Limited
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -20,12 +20,19 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- To start the engine:
23
+ To start and daemonize the engine:
24
24
 
25
25
  ```sh
26
26
  redis-alerting start -- -c path/to/config.yml
27
27
  ```
28
28
 
29
+ To run it with logging output:
30
+
31
+ ```sh
32
+ redis-alerting run -- -c path/to/config.yml -l info
33
+ #redis-alerting run -- -c path/to/config.yml -l debug # this will be noisy!
34
+ ```
35
+
29
36
  Check the status:
30
37
 
31
38
  ```sh
@@ -46,17 +53,43 @@ Given the config file below we will describe how the gem would check some limits
46
53
 
47
54
  ```yaml
48
55
  ---
49
- alerting:
50
- :interval: 1 # how often to check the readings
51
- :namespace: alerts # where the min/max settings, and active alerts are located
52
- :channel: alerts # publish alert messages to this channel
53
- :sources: # keys to obtain values from that need to be checked
54
- :ph: readings.ph
55
- :ec: readings.ec
56
- :flow: readings.flow
57
- # :name: redis.key.with.live.value
56
+ :interval: 1 # how often to check the readings
57
+ :namespace: alerts # the namespace to use for tracking active alerts/conditions
58
+ :separator: . # redis namespace separator
59
+ :channel: alerts # publish alert messages to this channel
60
+ :extrema: # details for where to find extrema information
61
+ :min: min # what you call your minimum
62
+ :max: max # what you call your maximum
63
+ :pattern: settings.$source_$extrema # the pattern to locate your extrema keys
64
+ :sources: # keys to obtain values from that need to be checked
65
+ :ph: readings.ph
66
+ :ec: readings.ec
67
+ :flow_rate: readings.flow_rate
68
+ # :name: redis.key.with.live.value
58
69
  ```
59
70
 
71
+ ### Extrema Patterns
72
+
73
+ So to find the min/max keys you will need to specify the pattern your extrema keys use (you use a pattern right?)
74
+
75
+ In the above case `settings.$source_$extrema` would be translated into:
76
+
77
+ * `settings.ph_min`
78
+ * `settings.ph_max`
79
+ * `settings.flow_rate_min`
80
+ * `settings.flow_rate_max`
81
+
82
+ If you stored your extrema a bit differently, a pattern like this might suffice: `alerts:$source:$extrema`:
83
+
84
+ * `alerts:ph:min`
85
+ * `alerts:ph:max`
86
+ * `alerts:ec:min`
87
+ * `alerts:ec:max`
88
+
89
+ Get it?
90
+
91
+ ### Sources
92
+
60
93
  With the example of `ph` above, the alerting system would check the redis key `readings.ph` and determine if it was outside the limits set in `alerts.ph.max` and `alerts.ph.min`.
61
94
 
62
95
  When it finds that the value in `readings.ph` is outside the range, it will add "ph" to the redis set `alerts.active`. When it comes back into range "ph" will be removed from the `alerts.active` set.
@@ -64,9 +97,12 @@ When it finds that the value in `readings.ph` is outside the range, it will add
64
97
  So to quickly summarize:
65
98
 
66
99
  * `readings.ph` - the reading value used to check against the min and max settings
67
- * `alerts.ph.min` - the minimum value for the reading (below which an alert is raised)
68
- * `alerts.ph.max` - the maximum value for the reading (above which an alert is raised)
69
- * `alerts.active` - the Redis SET that contains the names of the active alerts (e.g. "ph", "ec" or "flow")
100
+ * `settings.ph_min` - the minimum value for the reading (below which an alert is raised)
101
+ * `settings.ph_max` - the maximum value for the reading (above which an alert is raised)
102
+
103
+ ### Active Set
104
+
105
+ At anytime you can query the contents of the `alerts.active` SET to see which alert sources are currently active. It will contain the name specified under the sources section.
70
106
 
71
107
  ### Published messages
72
108
 
@@ -103,8 +139,8 @@ With the engine started try this (still sticking with the keys in the config fil
103
139
 
104
140
  ```sh
105
141
  $ redis-cli
106
- 127.0.0.1:6379> set alerts.ph.min 4000
107
- 127.0.0.1:6379> set alerts.ph.max 9000
142
+ 127.0.0.1:6379> set settings.ph_min 4000
143
+ 127.0.0.1:6379> set settings.ph_max 9000
108
144
  127.0.0.1:6379> set readings.ph 6000
109
145
  127.0.0.1:6379> smembers alerts.active
110
146
  (empty list or set)
data/bin/redis-alerting CHANGED
@@ -29,6 +29,7 @@ Daemons.run_proc("redis_alerting", daemon_opts ) do
29
29
  opts = Slop.parse slop_args do
30
30
  on :c, :config=, 'Configuration File'
31
31
  on :p, :pwd=, "Working directory"
32
+ on :l, :log=, "Log at the specified level to stdout"
32
33
  end
33
34
 
34
35
  begin
data/etc/config.yml CHANGED
@@ -1,9 +1,13 @@
1
1
  ---
2
- alerting:
3
- :interval: 1
4
- :namespace: alerts
5
- :channel: alerts
6
- :sources:
7
- :ph: readings.ph
8
- :ec: readings.ec
9
- :flow: readings.flow
2
+ :interval: 1
3
+ :namespace: alerts
4
+ :separator: .
5
+ :channel: alerts
6
+ :extrema:
7
+ :min: min
8
+ :max: max
9
+ :pattern: settings.$source_$extrema
10
+ :sources:
11
+ :ph: readings.ph
12
+ :ec: readings.ec
13
+ :flow_rate: readings.flow_rate
@@ -22,11 +22,26 @@ module RedisAlerting
22
22
  raise ArgumentError, "Invalid config file: #{@config[:config]}" unless File.exists? @config[:config]
23
23
 
24
24
  yaml = YAML.load_file(@config[:config])
25
- @config.merge!(yaml["alerting"])
25
+ @config.merge!(yaml)
26
+
27
+ @config[:log_level] = parse_log_level
26
28
 
27
29
  raise ArgumentError, "Incomplete configuration" unless valid_config?
28
30
  end
29
31
 
32
+ def parse_log_level
33
+ return Logger::UNKNOWN if @config[:log].nil? or @config[:log] == false
34
+
35
+ case @config[:log]
36
+ when "error"
37
+ Logger::ERROR
38
+ when "debug"
39
+ Logger::DEBUG
40
+ else
41
+ Logger::INFO
42
+ end
43
+ end
44
+
30
45
  # TODO: check we have all the needed options
31
46
  def valid_config?
32
47
  true
@@ -1,21 +1,43 @@
1
1
  module RedisAlerting
2
2
  class Engine
3
- def initialize(config, redis)
4
- @config = config
5
- @active_set = "#{@config[:namespace]}.active"
6
- @redis = redis
3
+ def initialize(config, redis, log)
4
+ @config = config
5
+ @active_set = "#{@config[:namespace]}#{@config[:separator]}active"
6
+ @redis = redis
7
+ @log = log
8
+ @extrema = {}
9
+
7
10
  check_redis
11
+ build_extrema
12
+
13
+ @log.info "Redis Alerting Engine Initialized"
14
+ @log.info "Publishing alert information on channel: #{@config[:channel]}"
15
+ @log.info "Currently active alerts are in the key: #{@active_set}"
16
+
17
+ @log.info "Working with sources:"
18
+ @config[:sources].each do |name, source|
19
+ @log.info " #{name}: #{source}"
20
+ end
21
+
22
+ @log.info "Working with extrema:"
23
+ @extrema.each do |name, ex|
24
+ @log.info " #{name}:"
25
+ @log.info " min: #{ex[:min]}"
26
+ @log.info " max: #{ex[:max]}"
27
+ end
28
+
8
29
  end
9
30
 
10
31
  def run
11
- ns = @config[:namespace]
12
32
  @config[:sources].each do |name, source|
13
33
 
14
34
  # get the readings and alert ranges
15
- min = @redis.get("#{ns}.#{name}.min").to_i
16
- max = @redis.get("#{ns}.#{name}.max").to_i
35
+ min = @redis.get(@extrema[name][:min]).to_i
36
+ max = @redis.get(@extrema[name][:max]).to_i
17
37
  value = @redis.get(source).to_i
18
38
 
39
+ @log.debug "Checking #{name} (min #{min}) (max #{max}): #{value}"
40
+
19
41
  # silently ignore
20
42
  next if max.nil? or min.nil? or value.nil?
21
43
 
@@ -40,8 +62,11 @@ module RedisAlerting
40
62
  end
41
63
 
42
64
  def add_alert_for(name, condition, value, min, max)
43
- return if @redis.sismember(@active_set, name)
65
+ return if @redis.sismember(@active_set, name) and @redis.get(condition_key(name)) == condition.to_s
44
66
  @redis.sadd @active_set, name
67
+ @redis.set condition_key(name), condition
68
+
69
+ @log.info "Added #{name} to active set"
45
70
 
46
71
  publish({
47
72
  action: :add,
@@ -56,7 +81,10 @@ module RedisAlerting
56
81
  def remove_if_alert_exists(name, value, min, max)
57
82
  return unless @redis.sismember(@active_set, name)
58
83
  @redis.srem @active_set, name
59
-
84
+ @redis.set condition_key(name), "OK"
85
+
86
+ @log.info "Removed #{name} from active set"
87
+
60
88
  publish({
61
89
  action: :remove,
62
90
  name: name,
@@ -68,12 +96,25 @@ module RedisAlerting
68
96
 
69
97
  def publish(message)
70
98
  @redis.publish @config[:channel], message.to_json
71
- puts "pushed message: #{message.inspect}"
99
+ @log.info "Pushed message: #{message.inspect}"
100
+ end
101
+
102
+ def condition_key(name)
103
+ "#{@config[:namespace]}#{@config[:separator]}#{name}#{@config[:separator]}condition"
72
104
  end
73
105
 
74
106
  def check_redis
75
107
  raise ArgumentError, "Invalid Redis instance given" unless @redis.is_a? Redis
76
108
  raise ArgumentError, "Could not connect to Redis" unless @redis.ping == "PONG"
77
109
  end
110
+
111
+ def build_extrema
112
+ @config[:sources].each do |source, redis_key|
113
+ @extrema[source] = {
114
+ min: @config[:extrema][:pattern].gsub("$source", source.to_s).gsub("$extrema", @config[:extrema][:min]),
115
+ max: @config[:extrema][:pattern].gsub("$source", source.to_s).gsub("$extrema", @config[:extrema][:max])
116
+ }
117
+ end
118
+ end
78
119
  end
79
120
  end
@@ -1,3 +1,3 @@
1
1
  module RedisAlerting
2
- VERSION = "1.1.1"
2
+ VERSION = "1.3.2"
3
3
  end
@@ -2,14 +2,17 @@ require "redis_alerting/version"
2
2
  require "redis_alerting/engine"
3
3
  require "redis_alerting/config"
4
4
  require 'redis'
5
+ require 'logger'
5
6
  require 'yaml'
6
7
  require 'json'
7
8
 
8
9
  module RedisAlerting
9
10
  class << self
10
11
  def run(opts)
11
- config = RedisAlerting::Config.new(opts).to_hash
12
- engine = RedisAlerting::Engine.new(config, ::Redis.new)
12
+ config = RedisAlerting::Config.new(opts).to_hash
13
+ log = Logger.new STDOUT
14
+ log.level = config[:log_level]
15
+ engine = RedisAlerting::Engine.new(config, ::Redis.new, log)
13
16
 
14
17
  loop do
15
18
  engine.run
metadata CHANGED
@@ -1,111 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_alerting
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert McLeod
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-17 00:00:00.000000000 Z
11
+ date: 2014-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: slop
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: daemons
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.7'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.7'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '10.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '10.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ! '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ! '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: pry
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ! '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ! '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  description: Checks redis for alert conditions and adds keys to a set when a value
@@ -117,7 +117,7 @@ executables:
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
- - .gitignore
120
+ - ".gitignore"
121
121
  - Gemfile
122
122
  - LICENSE.txt
123
123
  - README.md
@@ -141,12 +141,12 @@ require_paths:
141
141
  - lib
142
142
  required_ruby_version: !ruby/object:Gem::Requirement
143
143
  requirements:
144
- - - ! '>='
144
+ - - ">="
145
145
  - !ruby/object:Gem::Version
146
146
  version: '0'
147
147
  required_rubygems_version: !ruby/object:Gem::Requirement
148
148
  requirements:
149
- - - ! '>='
149
+ - - ">="
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0'
152
152
  requirements: []