redis_alerting 1.1.1 → 1.3.2

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.
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: []