kennel 1.49.0 → 1.53.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
  SHA256:
3
- metadata.gz: 7f0aabf5d65787da727c8f2fe6d4e42a3d88bca6cf31a426b2b29efbacc29316
4
- data.tar.gz: 8058d85578b7bf7247c26e50c8759fb4036977f22f321068283c1da77cf5e25e
3
+ metadata.gz: 95c82242166781e34d9132c511942a71c45c480951cb4b986702479cca60e271
4
+ data.tar.gz: 44ab3de5ad5709b6be941bfc8706ae4b712f94a3d1b9ae75a2f028a4e2c42926
5
5
  SHA512:
6
- metadata.gz: 80e9d102685107b747629f2df6045b30f588a1f9f9f7df2a668bfa7513fb96f47606c929d5276734282031328766210ae7c8dc260ef0e259a6cac4e36e915b22
7
- data.tar.gz: 762d5d95e419700fd9deb1b0c56fcaed33a460e3c65a4ed8d8f4ebd8c60875438d402423b48d62a086efe3b79019e72b64fd43bb59251ed20308039735f9f01a
6
+ metadata.gz: eb2bf40bccca3072b58c6eb7e7342de8ed51f6a716eba29eb5d717aeb013da18e082fdc0b4565fa666d6a7146d8dd77bc085f343b06d08fb81a285da7d64d520
7
+ data.tar.gz: be449f1b2c32d1f5996d16d17baa3e215c4446ae2ce4c865bd3cb160baece6bd8f56049cc7e29a56f025339a660ba474b6258fc042d808222a156cc2eb90f8e5
data/Readme.md CHANGED
@@ -154,12 +154,19 @@ end
154
154
  Some validations might be too strict for your usecase or just wrong, please [open an issue](https://github.com/grosser/kennel/issues) and
155
155
  to unblock use the `validate: -> { false }` option.
156
156
 
157
+ ### Monitor re-notification
158
+
159
+ Monitors inherit the re-notification setting from their `project.team`.
160
+ Set this to for example `renotify_interval: -> { 120 }` minutes,
161
+ to make alerts not get ignored by popping back up if they are still alerting.
162
+
157
163
  ### Linking with kennel_ids
158
164
 
159
165
  To link to existing monitors via their kennel_id
160
166
 
161
167
  - Screens `uptime` widgets can use `monitor: {id: "foo:bar"}`
162
168
  - Screens `alert_graph` widgets can use `alert_id: "foo:bar"`
169
+ - Monitors `composite` can use `query: -> { "%{foo:bar} || %{foo:baz}" }`
163
170
 
164
171
  ### Debugging changes locally
165
172
 
@@ -53,6 +53,9 @@ module Kennel
53
53
  if query && critical
54
54
  query.sub!(/([><=]) (#{Regexp.escape(critical.to_f.to_s)}|#{Regexp.escape(critical.to_i.to_s)})$/, "\\1 \#{critical}")
55
55
  end
56
+ elsif resource == "dashboard"
57
+ widgets = data[:widgets]&.flat_map { |widget| widget.dig(:definition, :widgets) || [widget] }
58
+ widgets&.each { |widget| dry_up_query!(widget) }
56
59
  end
57
60
 
58
61
  # simplify template_variables to array of string when possible
@@ -71,6 +74,20 @@ module Kennel
71
74
 
72
75
  private
73
76
 
77
+ # reduce duplication in imports by using dry `q: :metadata` when possible
78
+ def dry_up_query!(widget)
79
+ (widget.dig(:definition, :requests) || []).each do |request|
80
+ next unless request.is_a?(Hash)
81
+ next unless metadata = request[:metadata]
82
+ next unless query = request[:q]&.dup
83
+ metadata.each do |m|
84
+ next unless exp = m[:expression]
85
+ query.sub!(exp, "")
86
+ end
87
+ request[:q] = :metadata if query.delete(", ") == ""
88
+ end
89
+ end
90
+
74
91
  def pretty_print(hash)
75
92
  sort_widgets hash
76
93
 
@@ -84,6 +101,7 @@ module Kennel
84
101
  .gsub(/(^\s*)"([a-zA-Z][a-zA-Z\d_]*)":/, "\\1\\2:") # "foo": 1 -> foo: 1
85
102
  .gsub(/: \[\n\s+\]/, ": []") # empty arrays on a single line
86
103
  .gsub(/^/, " ") # indent
104
+ .gsub('q: "metadata"', "q: :metadata") # bring symbols back
87
105
 
88
106
  "\n#{pretty}\n "
89
107
  elsif k == :message
@@ -148,6 +148,13 @@ module Kennel
148
148
 
149
149
  private
150
150
 
151
+ def resolve_link(id, id_map, force:)
152
+ id_map[id] || begin
153
+ message = "Unable to find #{id} in existing monitors (they need to be created first to link them)"
154
+ force ? invalid!(message) : Kennel.err.puts(message)
155
+ end
156
+ end
157
+
151
158
  # let users know which project/resource failed when something happens during diffing where the backtrace is hidden
152
159
  def invalid!(message)
153
160
  raise ValidationError, "#{tracking_id} #{message}"
@@ -39,7 +39,7 @@ module Kennel
39
39
  pair.each do |b|
40
40
  b[:widgets]&.each do |w|
41
41
  if formats = w.dig(:definition, :conditional_formats)
42
- w[:definition][:conditional_formats] = formats.sort_by { |h| h[:value].to_f }
42
+ w[:definition][:conditional_formats] = formats.sort_by(&:hash)
43
43
  end
44
44
  end
45
45
  end
@@ -73,12 +73,15 @@ module Kennel
73
73
 
74
74
  def as_json
75
75
  return @json if @json
76
+ all_widgets = render_definitions + widgets
77
+ expand_q all_widgets
78
+
76
79
  @json = {
77
80
  layout_type: layout_type,
78
81
  title: "#{title}#{LOCK}",
79
82
  description: description,
80
83
  template_variables: render_template_variables,
81
- widgets: render_definitions + widgets
84
+ widgets: all_widgets
82
85
  }
83
86
 
84
87
  @json[:id] = id if id
@@ -98,11 +101,13 @@ module Kennel
98
101
  case definition[:type]
99
102
  when "uptime"
100
103
  if ids = definition[:monitor_ids]
101
- definition[:monitor_ids] = ids.map { |id| resolve_link(id, id_map) }
104
+ definition[:monitor_ids] = ids.map do |id|
105
+ tracking_id?(id) ? resolve_link(id, id_map, force: false) : id
106
+ end
102
107
  end
103
108
  when "alert_graph"
104
- if id = definition[:alert_id]
105
- definition[:alert_id] = resolve_link(id, id_map).to_s
109
+ if (id = definition[:alert_id]) && tracking_id?(id)
110
+ definition[:alert_id] = resolve_link(id, id_map, force: false).to_s
106
111
  end
107
112
  end
108
113
  end
@@ -110,16 +115,24 @@ module Kennel
110
115
 
111
116
  private
112
117
 
113
- def resolve_link(id, id_map)
114
- return id unless tracking_id?(id)
115
- id_map[id] ||
116
- Kennel.err.puts("Unable to find #{id} in existing monitors (they need to be created first to link them)")
117
- end
118
-
119
118
  def tracking_id?(id)
120
119
  id.is_a?(String) && !id.match?(/\A\d+\z/)
121
120
  end
122
121
 
122
+ # creates queries from metadata to avoid having to keep q and expression in sync
123
+ #
124
+ # {q: :metadata, metadata: [{expression: "sum:bar", alias_name: "foo"}, ...], }
125
+ # -> {q: "sum:bar, ...", metadata: ..., }
126
+ def expand_q(widgets)
127
+ widgets = widgets.flat_map { |w| w.dig(:definition, :widgets) || w } # expand groups
128
+ widgets.each do |w|
129
+ w.dig(:definition, :requests)&.each do |request|
130
+ next unless request.is_a?(Hash) && request[:q] == :metadata
131
+ request[:q] = request.fetch(:metadata).map { |m| m.fetch(:expression) }.join(", ")
132
+ end
133
+ end
134
+ end
135
+
123
136
  def validate_json(data)
124
137
  super
125
138
 
@@ -15,7 +15,7 @@ module Kennel
15
15
  evaluation_delay: nil,
16
16
  new_host_delay: 300,
17
17
  timeout_h: 0,
18
- renotify_interval: 120,
18
+ renotify_interval: 0,
19
19
  no_data_timeframe: nil # this works out ok since if notify_no_data is on, it would never be nil
20
20
  }.freeze
21
21
  DEFAULT_ESCALATION_MESSAGE = ["", nil].freeze
@@ -29,7 +29,7 @@ module Kennel
29
29
  defaults(
30
30
  message: -> { "\n\n@slack-#{project.slack}" },
31
31
  escalation_message: -> { DEFAULT_ESCALATION_MESSAGE.first },
32
- renotify_interval: -> { MONITOR_OPTION_DEFAULTS.fetch(:renotify_interval) },
32
+ renotify_interval: -> { project.team.renotify_interval },
33
33
  warning: -> { nil },
34
34
  ok: -> { nil },
35
35
  id: -> { nil },
@@ -108,6 +108,16 @@ module Kennel
108
108
  @as_json = data
109
109
  end
110
110
 
111
+ # resolve composite monitors ... only works when referenced monitors already exist
112
+ # since leaving names or bad ids in the query breaks the monitor update
113
+ def resolve_linked_tracking_ids(id_map)
114
+ if as_json[:type] == "composite"
115
+ as_json[:query] = as_json[:query].gsub(/%\{(.*?)\}/) do
116
+ resolve_link($1, id_map, force: true)
117
+ end
118
+ end
119
+ end
120
+
111
121
  def self.api_resource
112
122
  "monitor"
113
123
  end
@@ -2,9 +2,10 @@
2
2
  module Kennel
3
3
  module Models
4
4
  class Team < Base
5
- settings :slack, :email, :tags, :kennel_id
5
+ settings :slack, :email, :tags, :renotify_interval, :kennel_id
6
6
  defaults(
7
- tags: -> { ["team:#{kennel_id.sub(/^teams_/, "")}"] }
7
+ tags: -> { ["team:#{kennel_id.sub(/^teams_/, "")}"] },
8
+ renotify_interval: -> { 0 }
8
9
  )
9
10
 
10
11
  def initialize(*)
@@ -72,11 +72,22 @@ module Kennel
72
72
  filter_by_project! actual
73
73
 
74
74
  details_cache do |cache|
75
- actual.each do |a|
76
- id = a.fetch(:id)
75
+ items = actual.map do |a|
77
76
  e = matching_expected(a)
78
77
  if e && @expected.delete(e)
79
- fill_details(a, cache) if e.class::API_LIST_INCOMPLETE
78
+ [e, a]
79
+ else
80
+ [nil, a]
81
+ end
82
+ end
83
+
84
+ # fill details of things we need to compare (only do this part in parallel for safety & balancing)
85
+ Utils.parallel(items.select { |e, _| e && e.class::API_LIST_INCOMPLETE }) { |_, a| fill_details(a, cache) }
86
+
87
+ # pick out things to update or delete
88
+ items.each do |e, a|
89
+ id = a.fetch(:id)
90
+ if e
80
91
  diff = e.diff(a)
81
92
  @update << [id, e, a, diff] if diff.any?
82
93
  elsif tracking_id(a) # was previously managed
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "1.49.0"
3
+ VERSION = "1.53.0"
4
4
  end
@@ -136,12 +136,18 @@ end
136
136
  Some validations might be too strict for your usecase or just wrong, please [open an issue](https://github.com/grosser/kennel/issues) and
137
137
  to unblock use the `validate: -> { false }` option.
138
138
 
139
+ ### Monitor re-notification
140
+
141
+ Monitors inherit the re-notification setting from their projects team.
142
+ By default this is `renotify_interval: -> { 120 }` minutes, which will make alerts not get ignored by popping back up.
143
+
139
144
  ### Linking with kennel_ids
140
145
 
141
146
  To link to existing monitors via their kennel_id
142
147
 
143
148
  - Screens `uptime` widgets can use `monitor: {id: "foo:bar"}`
144
149
  - Screens `alert_graph` widgets can use `alert_id: "foo:bar"`
150
+ - Monitors `composite` can use `query: -> { "%{foo:bar} || %{foo:baz}" }`
145
151
 
146
152
  ### Debugging changes locally
147
153
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kennel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.49.0
4
+ version: 1.53.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-20 00:00:00.000000000 Z
11
+ date: 2019-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday