kennel 1.99.0 → 1.102.1

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: 0363ce2c85e194b4c6eca7e657a614d3eb0e27d7c0a5f4a55871bf39fc90f5f9
4
- data.tar.gz: 075f01f5fa4f153f1a8c07ec000b7abf246e3c0dd9082d5709661240191b07f1
3
+ metadata.gz: a2bb74d0c3edadadde342a244ba9978b571da0a2306b8c5aacaafd60a745f431
4
+ data.tar.gz: abbb833ba16df03e64e2fea46c4094b7ad2aa07780c13e0cebe981f9c77e4753
5
5
  SHA512:
6
- metadata.gz: 6834defb05ea8844a19fdaa80a8e3cb7154305bbf3dbc6a66c24d76cc4b050305020c14ca7712a105d1514c421cf4a1f4674b9dfccc93b694e17daba8d8abf8b
7
- data.tar.gz: 87f2c790faa21b2e63beaca026c565e6c940aa9dae0cc624b7060d81ed4b6cfce7894c77ccf56b60751a9fb3d1ed0b1dfc2c2c27a893ea88e0097b2d44138a05
6
+ metadata.gz: d0aea7c75a482f3a4a2d4996bca4c3b2990564f3720f027366749b5c287f50bc805e29782315e697a2711f5029f9aecbda05b4aae0b1f6204d371f6991e6e76b
7
+ data.tar.gz: 47037941ef3eedbefb74061545ea68c62d36367ec2b24a3acd3e6e2e08aaa9ef44f2735482012aa4af202aca5ee2cf2330af9df40ee717500d01c43940c9e436
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ module Kennel
3
+ class IdMap
4
+ NEW = :new # will be created during this run
5
+
6
+ def initialize
7
+ @map = Hash.new { |h, k| h[k] = {} }
8
+ end
9
+
10
+ def get(type, tracking_id)
11
+ @map[type][tracking_id]
12
+ end
13
+
14
+ def set(type, tracking_id, id)
15
+ @map[type][tracking_id] = id
16
+ end
17
+
18
+ def new?(type, tracking_id)
19
+ @map[type][tracking_id] == NEW
20
+ end
21
+ end
22
+ end
@@ -189,16 +189,17 @@ module Kennel
189
189
  when "uptime"
190
190
  if ids = definition[:monitor_ids]
191
191
  definition[:monitor_ids] = ids.map do |id|
192
- tracking_id?(id) ? (resolve_link(id, :monitor, id_map, **args) || id) : id
192
+ resolve(id, :monitor, id_map, **args) || id
193
193
  end
194
194
  end
195
195
  when "alert_graph"
196
- if (id = definition[:alert_id]) && tracking_id?(id)
197
- definition[:alert_id] = (resolve_link(id, :monitor, id_map, **args) || id).to_s
196
+ if id = definition[:alert_id]
197
+ resolved = resolve(id, :monitor, id_map, **args) || id
198
+ definition[:alert_id] = resolved.to_s # even though it's a monitor id
198
199
  end
199
200
  when "slo"
200
- if (id = definition[:slo_id]) && tracking_id?(id)
201
- definition[:slo_id] = (resolve_link(id, :slo, id_map, **args) || id).to_s
201
+ if id = definition[:slo_id]
202
+ definition[:slo_id] = resolve(id, :slo, id_map, **args) || id
202
203
  end
203
204
  end
204
205
  end
@@ -206,10 +207,6 @@ module Kennel
206
207
 
207
208
  private
208
209
 
209
- def tracking_id?(id)
210
- id.is_a?(String) && id.include?(":")
211
- end
212
-
213
210
  # creates queries from metadata to avoid having to keep q and expression in sync
214
211
  #
215
212
  # {q: :metadata, metadata: [{expression: "sum:bar", alias_name: "foo"}, ...], }
@@ -121,7 +121,7 @@ module Kennel
121
121
  when "composite", "slo alert"
122
122
  type = (as_json[:type] == "composite" ? :monitor : :slo)
123
123
  as_json[:query] = as_json[:query].gsub(/%{(.*?)}/) do
124
- resolve_link($1, type, id_map, **args) || $&
124
+ resolve($1, type, id_map, **args) || $&
125
125
  end
126
126
  end
127
127
  end
@@ -100,9 +100,20 @@ module Kennel
100
100
 
101
101
  private
102
102
 
103
+ def resolve(value, type, id_map, force:)
104
+ if tracking_id?(value)
105
+ return resolve_link(value, type, id_map, force: force)
106
+ end
107
+
108
+ value
109
+ end
110
+
111
+ def tracking_id?(id)
112
+ id.is_a?(String) && id.include?(":")
113
+ end
114
+
103
115
  def resolve_link(tracking_id, type, id_map, force:)
104
- id = id_map[tracking_id]
105
- if id == :new
116
+ if id_map.new?(type.to_s, tracking_id)
106
117
  if force
107
118
  invalid!(
108
119
  "#{type} #{tracking_id} was referenced but is also created by the current run.\n" \
@@ -111,7 +122,7 @@ module Kennel
111
122
  else
112
123
  nil # will be re-resolved after the linked object was created
113
124
  end
114
- elsif id
125
+ elsif id = id_map.get(type.to_s, tracking_id)
115
126
  id
116
127
  else
117
128
  invalid! "Unable to find #{type} #{tracking_id} (does not exist and is not being created by the current run)"
@@ -70,7 +70,7 @@ module Kennel
70
70
  def resolve_linked_tracking_ids!(id_map, **args)
71
71
  return unless as_json[:monitor_ids] # ignore_default can remove it
72
72
  as_json[:monitor_ids] = as_json[:monitor_ids].map do |id|
73
- id.is_a?(String) ? (resolve_link(id, :monitor, id_map, **args) || id) : id
73
+ resolve(id, :monitor, id_map, **args) || id
74
74
  end
75
75
  end
76
76
 
data/lib/kennel/syncer.rb CHANGED
@@ -122,7 +122,7 @@ module Kennel
122
122
  def calculate_diff
123
123
  @update = []
124
124
  @delete = []
125
- @id_map = {}
125
+ @id_map = IdMap.new
126
126
 
127
127
  actual = Progress.progress("Downloading definitions") { download_definitions }
128
128
 
@@ -254,11 +254,32 @@ module Kennel
254
254
  end
255
255
 
256
256
  def populate_id_map(expected, actual)
257
+ # mark everything as new
258
+ expected.each do |e|
259
+ @id_map.set(e.class.api_resource, e.tracking_id, IdMap::NEW)
260
+ if e.class.api_resource == "synthetics/tests"
261
+ @id_map.set(Kennel::Models::Monitor.api_resource, e.tracking_id, IdMap::NEW)
262
+ end
263
+ end
264
+
265
+ # override resources that exist with their id
266
+ project_prefix = @project_filter && "#{@project_filter}:"
257
267
  actual.each do |a|
268
+ # ignore when not managed by kennel
258
269
  next unless tracking_id = a.fetch(:tracking_id)
259
- @id_map[tracking_id] = a.fetch(:id)
270
+
271
+ # ignore when deleted from the codebase
272
+ # (when running with project filter we cannot see the other resources in the codebase)
273
+ api_resource = a.fetch(:klass).api_resource
274
+ next if
275
+ !@id_map.get(api_resource, tracking_id) &&
276
+ (!project_prefix || tracking_id.start_with?(project_prefix))
277
+
278
+ @id_map.set(api_resource, tracking_id, a.fetch(:id))
279
+ if a[:klass].api_resource == "synthetics/tests"
280
+ @id_map.set(Kennel::Models::Monitor.api_resource, tracking_id, a.fetch(:monitor_id))
281
+ end
260
282
  end
261
- expected.each { |e| @id_map[e.tracking_id] ||= :new }
262
283
  end
263
284
 
264
285
  def resolve_linked_tracking_ids!(list, force: false)
data/lib/kennel/tasks.rb CHANGED
@@ -3,6 +3,7 @@ require "English"
3
3
  require "kennel"
4
4
  require "kennel/unmuted_alerts"
5
5
  require "kennel/importer"
6
+ require "json"
6
7
 
7
8
  module Kennel
8
9
  module Tasks
@@ -89,7 +90,7 @@ namespace :kennel do
89
90
  Kennel::UnmutedAlerts.print(Kennel.send(:api), tag)
90
91
  end
91
92
 
92
- desc "show monitors with no data by TAG, for example TAG=team:foo"
93
+ desc "show monitors with no data by TAG, for example TAG=team:foo [THRESHOLD_DAYS=7] [FORMAT=json]"
93
94
  task nodata: :environment do
94
95
  tag = ENV["TAG"] || Kennel::Tasks.abort("Call with TAG=foo:bar")
95
96
  monitors = Kennel.send(:api).list("monitor", monitor_tags: tag, group_states: "no data")
@@ -97,16 +98,45 @@ namespace :kennel do
97
98
  monitors.reject! { |m| m[:tags].include? "nodata:ignore" }
98
99
  if monitors.any?
99
100
  Kennel.err.puts <<~TEXT
100
- This is a useful task to find monitors that have mis-spelled metrics or never received data at any time.
101
- To ignore monitors with nodata, tag the monitor with "nodata:ignore"
101
+ To ignore monitors with expected nodata, tag it with "nodata:ignore"
102
102
 
103
103
  TEXT
104
104
  end
105
105
 
106
+ now = Time.now
106
107
  monitors.each do |m|
107
- Kennel.out.puts m[:name]
108
- Kennel.out.puts Kennel::Utils.path_to_url("/monitors/#{m[:id]}")
109
- Kennel.out.puts
108
+ m[:days_in_no_data] =
109
+ if m[:overall_state_modified]
110
+ since = Date.parse(m[:overall_state_modified]).to_time
111
+ ((now - since) / (24 * 60 * 60)).to_i
112
+ else
113
+ 999
114
+ end
115
+ end
116
+
117
+ if threshold = ENV["THRESHOLD_DAYS"]
118
+ monitors.select! { |m| m[:days_in_no_data] > Integer(threshold) }
119
+ end
120
+
121
+ monitors.each { |m| m[:url] = Kennel::Utils.path_to_url("/monitors/#{m[:id]}") }
122
+
123
+ if ENV["FORMAT"] == "json"
124
+ report = monitors.map do |m|
125
+ match = m[:message].to_s.match(/-- Managed by kennel (\S+:\S+) in (\S+), /) || []
126
+ m.slice(:url, :name, :tags, :days_in_no_data).merge(
127
+ kennel_tracking_id: match[1],
128
+ kennel_source: match[2]
129
+ )
130
+ end
131
+
132
+ Kennel.out.puts JSON.pretty_generate(report)
133
+ else
134
+ monitors.each do |m|
135
+ Kennel.out.puts m[:name]
136
+ Kennel.out.puts Kennel::Utils.path_to_url("/monitors/#{m[:id]}")
137
+ Kennel.out.puts "No data since #{m[:days_in_no_data]}d"
138
+ Kennel.out.puts
139
+ end
110
140
  end
111
141
  end
112
142
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "1.99.0"
3
+ VERSION = "1.102.1"
4
4
  end
data/lib/kennel.rb CHANGED
@@ -9,6 +9,7 @@ require "kennel/version"
9
9
  require "kennel/utils"
10
10
  require "kennel/progress"
11
11
  require "kennel/syncer"
12
+ require "kennel/id_map"
12
13
  require "kennel/api"
13
14
  require "kennel/github_reporter"
14
15
  require "kennel/subclass_tracking"
@@ -69,7 +70,8 @@ module Kennel
69
70
  path = "generated/#{part.tracking_id.tr("/", ":").sub(":", "/")}.json"
70
71
  used << File.dirname(path) # only 1 level of sub folders, so this is safe
71
72
  used << path
72
- write_file_if_necessary(path, JSON.pretty_generate(part.as_json) << "\n")
73
+ payload = part.as_json.merge(api_resource: part.class.api_resource)
74
+ write_file_if_necessary(path, JSON.pretty_generate(payload) << "\n")
73
75
  end
74
76
 
75
77
  # deleting all is slow, so only delete the extras
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.99.0
4
+ version: 1.102.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-05 00:00:00.000000000 Z
11
+ date: 2021-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -77,6 +77,7 @@ files:
77
77
  - lib/kennel/api.rb
78
78
  - lib/kennel/file_cache.rb
79
79
  - lib/kennel/github_reporter.rb
80
+ - lib/kennel/id_map.rb
80
81
  - lib/kennel/importer.rb
81
82
  - lib/kennel/models/base.rb
82
83
  - lib/kennel/models/dashboard.rb