dogwatch 1.0.5 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3573cefa87a87733badaa188e4138bcf946598c1
4
- data.tar.gz: 7f160b2d047845120932ad57be4e9f851c94df49
3
+ metadata.gz: 224be9842797fe4c2fc9c0cf3d88a9972759d54f
4
+ data.tar.gz: 5b14f7af6a5a64146640832cf53aa16fe350d0bc
5
5
  SHA512:
6
- metadata.gz: 69453b6cbf2dc5dfc75be7d2a4e762a9d1d18a806a9b9a907e018bd01616602eb6a31dfb847c90f0dacb21ce70ce1db93b02a609e30a692ba6b727d1032bcd4e
7
- data.tar.gz: 7a9e862dc1736e0a0147b721851492332c1ada38428882b9c6c393c1f94e0f00a799bb0e2ac4e3a4cc0898cddcfc52fcd238d44946ad80bf49f88ee304a214e3
6
+ metadata.gz: f98c42c081bbf044495be9c26272e03699a74d581e9653cf5b6a21c8a3103c45d3d06b27b2c7faf8714b8033a928e5bdee2bffa8c95cb7b14e82ba452b6981d8
7
+ data.tar.gz: 026bf75a19af2a701511e8d7222dc176bf856fc4bac7ddee1cda6458eb09de0a46ea357836749a0cc015e054a0a3a84ef0438e03aeb7d12fdf069e6378c379ae
@@ -10,6 +10,7 @@ module DogWatch
10
10
  class_option :dogfile, :type => :string, :default => 'Dogfile'
11
11
  class_option :api_key, :type => :string, :default => nil
12
12
  class_option :app_key, :type => :string, :default => nil
13
+ class_option :timeout, :type => :numeric, :default => 5
13
14
  def initialize(*args)
14
15
  super
15
16
  @cwd = Dir.getwd
@@ -19,7 +20,8 @@ module DogWatch
19
20
  desc 'create', 'Create a monitor from a Dogfile'
20
21
  def create
21
22
  @dogfile.configure(File.absolute_path(options['dogfile'], @cwd),
22
- options['api_key'], options['app_key'])
23
+ options['api_key'], options['app_key'],
24
+ options['timeout'])
23
25
  @dogfile.create { |c| say_status(*c.to_thor) }
24
26
  end
25
27
  end
@@ -20,6 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = '>= 2.2'
22
22
 
23
- spec.add_runtime_dependency 'dogapi', '~> 1.21'
23
+ spec.add_runtime_dependency 'dogapi', '~> 1.27'
24
24
  spec.add_runtime_dependency 'thor', '~> 0.19'
25
25
  end
@@ -4,6 +4,26 @@
4
4
  #
5
5
  DogWatch.monitor do
6
6
  monitor 'test_alert' do
7
+ type :metric_alert
8
+ query 'avg(last_1dm):avg:system.cpu.user{region:us-east-1} > 20'
9
+ message 'A message to include with notifications for this monitor.'\
10
+ 'Email notifications can be sent to specific users by '\
11
+ 'using the same \'@username\' notation as events.'
12
+
13
+ tags %w(A list of tags to associate with your monitor)
14
+
15
+ options do
16
+ silenced '*': nil
17
+ notify_no_data false
18
+ no_data_timeframe 3
19
+ timeout_h 99
20
+ renotify_interval 60
21
+ escalation_message 'oh snap'
22
+ include_tags true
23
+ end
24
+ end
25
+
26
+ monitor 'test_alert2' do
7
27
  type :metric_alert
8
28
  query 'avg(last_1m):avg:system.cpu.user{region:us-east-1} > 20'
9
29
  message 'A message to include with notifications for this monitor.'\
@@ -3,6 +3,9 @@
3
3
  ##
4
4
  module DogWatch
5
5
  class << self
6
+ # @param [Hash] args
7
+ # @param [Proc] block
8
+ # @return [DogWatch::Monitor]
6
9
  def monitor(*args, &block)
7
10
  DogWatch::Monitor.new(*args, &block)
8
11
  end
@@ -9,9 +9,10 @@ module DogWatch
9
9
  # @param [String] dogfile
10
10
  # @param [String|Object] api_key
11
11
  # @param [String|Object] app_key
12
- def configure(dogfile, api_key = nil, app_key = nil)
12
+ # @param [Integer] timeout
13
+ def configure(dogfile, api_key, app_key, timeout)
13
14
  @dogfile = dogfile
14
- @config = DogWatch::Model::Config.new(api_key, app_key)
15
+ @config = DogWatch::Model::Config.new(api_key, app_key, timeout)
15
16
  end
16
17
 
17
18
  # @param [Proc] block
@@ -15,11 +15,13 @@ module DogWatch
15
15
  # @param [DogWatch::Model::Config] config
16
16
  def initialize(config)
17
17
  @config = config
18
- @client = Dogapi::Client.new(@config.api_key, @config.app_key)
18
+ @client = Dogapi::Client.new(@config.api_key, @config.app_key,
19
+ nil, nil, true, @config.timeout)
19
20
  @all_monitors = all_monitors
20
21
  end
21
22
 
22
23
  # @param [DogWatch::Model::Monitor] monitor
24
+ # @return [DogWatch::Model::Response]
23
25
  def execute(monitor)
24
26
  if monitor_exists?(monitor.name)
25
27
  update_monitor(monitor)
@@ -37,7 +39,7 @@ module DogWatch
37
39
  monitor.attributes.query,
38
40
  options)
39
41
  updated = %w(200 202).include?(response[0])
40
- @response = DogWatch::Model::Response.new(response, updated)
42
+ DogWatch::Model::Response.new(response, options[:name], updated)
41
43
  end
42
44
 
43
45
  # @param [DogWatch::Model::Monitor] monitor
@@ -47,7 +49,17 @@ module DogWatch
47
49
  response = @client.monitor(monitor.attributes.type,
48
50
  monitor.attributes.query,
49
51
  options)
50
- @response = DogWatch::Model::Response.new(response)
52
+ DogWatch::Model::Response.new(response, options[:name])
53
+ end
54
+
55
+ # @param [Dogwatch::Model::Monitor] monitor
56
+ # @return [Dogwatch::Model::Response]
57
+ def validate(monitor)
58
+ validation = monitor.validate
59
+ return validation if validation.status == :error
60
+
61
+ # If no validation errors return a valid Response
62
+ DogWatch::Model::Response.new(['200', {}], 'valid')
51
63
  end
52
64
 
53
65
  private
@@ -9,12 +9,15 @@ module DogWatch
9
9
  class Config
10
10
  attr_accessor :api_key
11
11
  attr_accessor :app_key
12
+ attr_accessor :timeout
12
13
 
13
14
  # @param [String] api_key
14
15
  # @param [String] app_key
15
- def initialize(api_key = nil, app_key = nil)
16
+ # @param [Integer] timeout
17
+ def initialize(api_key = nil, app_key = nil, timeout = 5)
16
18
  @api_key = api_key unless api_key.nil?
17
19
  @app_key = app_key unless app_key.nil?
20
+ @timeout = timeout
18
21
  return unless app_key.nil? || api_key.nil?
19
22
 
20
23
  from_file
@@ -5,6 +5,9 @@ module DogWatch
5
5
  # Provides a colorize() mixin that handles shell output coloring
6
6
  ##
7
7
  module Colorize
8
+ # @param [Symbol] param
9
+ # @param [Hash] options
10
+ # @return [Symbol]
8
11
  def colorize(param, options = {})
9
12
  define_method(:color) do
10
13
  case instance_variable_get("@#{ param }")
@@ -56,13 +56,44 @@ module DogWatch
56
56
  @attributes.options = opts.render
57
57
  end
58
58
 
59
- # @return [TrueClass|FalseClass]
59
+ # @return [DogWatch::Model::Response]
60
60
  def validate
61
- return false unless TYPE_MAP.value?(@attributes.type)
62
- return true unless @attributes.type.nil? || @attributes.type.empty? ||
63
- @attributes.query.nil? || @attributes.query.empty?
61
+ return DogWatch::Model::Response.new(invalid_type_response, 'invalid') \
62
+ unless TYPE_MAP.key?(@monitor_type)
64
63
 
65
- false
64
+ errors = []
65
+ errors.push('Missing monitor type') if missing_type?
66
+ errors.push('Missing monitor query') if missing_query?
67
+
68
+ if errors.empty?
69
+ DogWatch::Model::Response.new(['200', { :message => 'valid' }], 'valid')
70
+ else
71
+ DogWatch::Model::Response.new(['400', { 'errors' => errors }], 'invalid')
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def valid_types
78
+ TYPE_MAP.keys.map { |k| ":#{k}" }.join(', ')
79
+ end
80
+
81
+ def missing_type?
82
+ @attributes.type.nil? || @attributes.type.empty?
83
+ end
84
+
85
+ def missing_query?
86
+ @attributes.query.nil? || @attributes.query.empty?
87
+ end
88
+
89
+ def invalid_type_response
90
+ [
91
+ '400',
92
+ { 'errors' => [
93
+ "Monitor type '#{@monitor_type}' is not valid. " \
94
+ "Valid monitor types are: #{valid_types}"
95
+ ] }
96
+ ]
66
97
  end
67
98
  end
68
99
  end
@@ -21,6 +21,7 @@ module DogWatch
21
21
  @monitor_type = monitor_type
22
22
  end
23
23
 
24
+ # @return [Hash]
24
25
  def render
25
26
  @attributes.each_pair.to_h
26
27
  end
@@ -11,6 +11,7 @@ module DogWatch
11
11
  ERROR = '400'.freeze
12
12
  CREATED = '200'.freeze
13
13
  ACCEPTED = '202'.freeze
14
+
14
15
  colorize(:action,
15
16
  :green => [:created, :accepted, :updated],
16
17
  :yellow => [],
@@ -18,11 +19,21 @@ module DogWatch
18
19
 
19
20
  attr_accessor :response
20
21
 
21
- def initialize(response, updated = false)
22
+ # @param [Array] response
23
+ # @param [String] name
24
+ # @param [Boolean] updated
25
+ # @return [DogWatch::Model::Response]
26
+ def initialize(response, name, updated = false)
22
27
  @response = response
23
28
  @updated = updated
29
+ @name = if response[1]['name'].nil?
30
+ name
31
+ else
32
+ response[1]['name']
33
+ end
24
34
  end
25
35
 
36
+ # @return [Symbol]
26
37
  def status
27
38
  return :updated if @updated == true
28
39
  return :created if created?
@@ -30,13 +41,12 @@ module DogWatch
30
41
  return :accepted if accepted?
31
42
  end
32
43
 
44
+ # @return [String]
33
45
  def message
34
- attrs = @response[1]
35
- return attrs['errors'] if attrs.key?('errors')
36
- "#{status.to_s.capitalize} monitor #{attrs['name']}"\
37
- " with message #{attrs['message']}"
46
+ send(status, @response[1])
38
47
  end
39
48
 
49
+ # @return [Array]
40
50
  def to_thor
41
51
  action = status
42
52
  text = message
@@ -45,16 +55,35 @@ module DogWatch
45
55
 
46
56
  private
47
57
 
58
+ def error(attrs)
59
+ err = attrs['errors'].join(', ')
60
+ "The following errors occurred when creating monitor #{@name}: #{err}"
61
+ end
62
+
63
+ def created(attrs)
64
+ "Created monitor #{@name} with message #{attrs['message']}"
65
+ end
66
+
67
+ def updated(attrs)
68
+ # TODO: Use some kind of statefile to determine diffs between
69
+ # previously saved model and new version
70
+ "Updated monitor #{@name} with message #{attrs['message']}"
71
+ end
72
+
73
+ def accepted(attrs)
74
+ "Accepted monitor #{@name} with message #{attrs['message']}"
75
+ end
76
+
48
77
  def accepted?
49
- @response[0] == ACCEPTED ? true : false
78
+ @response[0] == ACCEPTED
50
79
  end
51
80
 
52
81
  def created?
53
- @response[0] == CREATED ? true : false
82
+ @response[0] == CREATED
54
83
  end
55
84
 
56
85
  def failed?
57
- @response[0] == ERROR ? true : false
86
+ @response[0] == ERROR
58
87
  end
59
88
  end
60
89
  end
@@ -32,20 +32,22 @@ module DogWatch
32
32
  # @return [Array]
33
33
  def get
34
34
  @responses = @monitors.map do |m|
35
- if m.validate
36
- @client.execute(m)
35
+ validate = @client.validate(m)
36
+ if validate.status == :error
37
+ validate
37
38
  else
38
- # Need somewhere to inject local errors such as if the request
39
- # was never sent because the type or query wasn't supplied.
40
- res = ['400', { 'errors' => ['The DogWatch monitor is invalid.'] }]
41
- DogWatch::Model::Response.new(res)
39
+ @client.execute(m)
42
40
  end
43
41
  end
44
42
  end
45
43
 
46
44
  # @return [DogWatch::Model::Client]
47
45
  def client(client = nil)
48
- @client = client.nil? ? DogWatch::Model::Client.new(@config) : client
46
+ @client = if client.nil?
47
+ DogWatch::Model::Client.new(@config)
48
+ else
49
+ client
50
+ end
49
51
  end
50
52
  end
51
53
  end
@@ -8,20 +8,20 @@ require 'json'
8
8
  class TestClient < Minitest::Test
9
9
  TEST_RESPONSE = [
10
10
  '200',
11
- [
11
+ {
12
12
  name: 'test monitor',
13
13
  type: 'metric alert',
14
14
  query: 'test query'
15
- ]
15
+ }
16
16
  ].freeze
17
17
 
18
18
  UPDATED_RESPONSE = [
19
19
  '200',
20
- [
20
+ {
21
21
  name: 'Monitor name',
22
22
  type: :metric_alert,
23
23
  query: 'scheduled maintenance query'
24
- ]
24
+ }
25
25
  ].freeze
26
26
 
27
27
  def setup
@@ -48,8 +48,8 @@ class TestClient < Minitest::Test
48
48
  new_monitor.query('test query')
49
49
 
50
50
  @client.client.stub :monitor, TEST_RESPONSE do
51
- @client.execute(new_monitor)
52
- assert_equal @client.response.status, :created
51
+ response = @client.execute(new_monitor)
52
+ assert_equal response.status, :created
53
53
  end
54
54
  end
55
55
 
@@ -59,8 +59,8 @@ class TestClient < Minitest::Test
59
59
  update_monitor.query('scheduled maintenance query')
60
60
 
61
61
  @client.client.stub :update_monitor, UPDATED_RESPONSE do
62
- @client.execute(update_monitor)
63
- assert_equal @client.response.status, :updated
62
+ response = @client.execute(update_monitor)
63
+ assert_equal response.status, :updated
64
64
  end
65
65
  end
66
66
  end
@@ -45,9 +45,16 @@ class TestMonitorModel < Minitest::Test
45
45
  end
46
46
 
47
47
  def test_validate
48
- assert_equal true, @monitor.validate
48
+ validation = @monitor.validate
49
+ assert_kind_of DogWatch::Model::Response, validation
50
+ assert_equal :created, validation.status
49
51
 
50
52
  @monitor.attributes.query = nil
51
- assert_equal false, @monitor.validate
53
+
54
+ failed_validation = @monitor.validate
55
+ assert_kind_of DogWatch::Model::Response, failed_validation
56
+ assert_equal :error, failed_validation.status
57
+ assert_equal 'The following errors occurred when creating monitor ' \
58
+ 'invalid: Missing monitor query', failed_validation.message
52
59
  end
53
60
  end
@@ -3,9 +3,9 @@ require_relative '../../lib/dogwatch/model/response'
3
3
 
4
4
  class TestResponse < MiniTest::Test
5
5
  def setup
6
- @error_res = DogWatch::Model::Response.new(ERROR_RES)
7
- @valid_res = DogWatch::Model::Response.new(VALID_RES)
8
- @accepted_res = DogWatch::Model::Response.new(ACCEPTED_RES)
6
+ @error_res = DogWatch::Model::Response.new(ERROR_RES, 'error')
7
+ @valid_res = DogWatch::Model::Response.new(VALID_RES, 'foobar')
8
+ @accepted_res = DogWatch::Model::Response.new(ACCEPTED_RES, 'foobar')
9
9
  end
10
10
 
11
11
  def test_status_is_error
@@ -17,7 +17,8 @@ class TestResponse < MiniTest::Test
17
17
  end
18
18
 
19
19
  def test_status_message
20
- assert_equal ["The value provided for parameter 'query' is invalid"], \
20
+ assert_equal 'The following errors occurred when creating monitor error: ' \
21
+ "The value provided for parameter 'query' is invalid", \
21
22
  @error_res.message
22
23
  end
23
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dogwatch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Greene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-13 00:00:00.000000000 Z
11
+ date: 2017-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dogapi
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.21'
19
+ version: '1.27'
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
- version: '1.21'
26
+ version: '1.27'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement