kennel 1.48.0 → 1.52.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: 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