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 +4 -4
- data/Readme.md +1 -0
- data/lib/kennel/importer.rb +18 -0
- data/lib/kennel/models/base.rb +7 -0
- data/lib/kennel/models/dashboard.rb +24 -11
- data/lib/kennel/models/monitor.rb +10 -0
- data/lib/kennel/syncer.rb +14 -3
- data/lib/kennel/tasks.rb +8 -0
- data/lib/kennel/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d34d639d4d27f3953211bc4f94f36d559b5ada87d3f289219bf611c8183805d
|
|
4
|
+
data.tar.gz: c531670c166981073648ae9e12f1ca6c47f27a5642a4b8abf0fc5890134bcead
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
data/lib/kennel/importer.rb
CHANGED
|
@@ -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
|
data/lib/kennel/models/base.rb
CHANGED
|
@@ -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
|
|
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:
|
|
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
|
|
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
|
data/lib/kennel/syncer.rb
CHANGED
|
@@ -72,11 +72,22 @@ module Kennel
|
|
|
72
72
|
filter_by_project! actual
|
|
73
73
|
|
|
74
74
|
details_cache do |cache|
|
|
75
|
-
actual.
|
|
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
|
-
|
|
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
|
data/lib/kennel/tasks.rb
CHANGED
|
@@ -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]
|
data/lib/kennel/version.rb
CHANGED
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.
|
|
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-
|
|
11
|
+
date: 2019-09-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|