kennel 1.48.0 → 1.52.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9283bb5d1301a656e0c1ca896ad6fb8bc91ecfedd621722ce9e3b6a50055e34e
4
- data.tar.gz: fc1a556ee6e1a658da97b9a59792d6c7c789c834beae5cba39b8447a04818fe3
3
+ metadata.gz: 7d34d639d4d27f3953211bc4f94f36d559b5ada87d3f289219bf611c8183805d
4
+ data.tar.gz: c531670c166981073648ae9e12f1ca6c47f27a5642a4b8abf0fc5890134bcead
5
5
  SHA512:
6
- metadata.gz: ecc7e11d744f0a87941759927ef1e8d79b3b9ebccaf759c8c15c43ff7d7ef8524d38b4b488035d647a67b0841392f17c1c197cadf86d511ac72a2e118ba3d589
7
- data.tar.gz: df0c1b18c9f82a8bd50f717f84f63d80a33aec84668bcbde144ab944359b0bee65295bd712d2457da9453ff2fdb07d8d16721baed947afb88d088f575cb7ab4a
6
+ metadata.gz: 5e4f308f0076d4cc5f290c5041fc37a57a64986fb1d0ec586bf448b9293880fd42e67b6d6de60607369f2918efc7aeb87177fd7a27a1749ca272fdb2c5519d0f
7
+ data.tar.gz: e1852e1d4c0cceb841f73559ae248357ce5d1fdfe81e3d8a0a348374d2f1e6819befbc9fcdec0caae00cc72808430f91fd10d46b7dd88fe57b721faf55e1d882
data/Readme.md CHANGED
@@ -160,6 +160,7 @@ To link to existing monitors via their kennel_id
160
160
 
161
161
  - Screens `uptime` widgets can use `monitor: {id: "foo:bar"}`
162
162
  - Screens `alert_graph` widgets can use `alert_id: "foo:bar"`
163
+ - Monitors `composite` can use `query: -> { "%{foo:bar} || %{foo:baz}" }`
163
164
 
164
165
  ### Debugging changes locally
165
166
 
@@ -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
 
@@ -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
@@ -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
@@ -55,6 +55,14 @@ namespace :kennel do
55
55
  tag = ENV["TAG"] || abort("Call with TAG=foo:bar")
56
56
  monitors = Kennel.send(:api).list("monitor", monitor_tags: tag, group_states: "no data")
57
57
  monitors.select! { |m| m[:overall_state] == "No Data" }
58
+ monitors.reject! { |m| m[:tags].include? ["nodata:ignore"] }
59
+ if monitors.any?
60
+ Kennel.err.puts <<~TEXT
61
+ This is a useful task to find monitors that have mis-spelled metrics or never received data at any time.
62
+ To ignore monitors with nodata, tag the monitor with "nodata:ignore"
63
+
64
+ TEXT
65
+ end
58
66
 
59
67
  monitors.each do |m|
60
68
  Kennel.out.puts m[:name]
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "1.48.0"
3
+ VERSION = "1.52.0"
4
4
  end
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.48.0
4
+ version: 1.52.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-19 00:00:00.000000000 Z
11
+ date: 2019-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday