kennel 2.9.0 → 2.10.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: d9635f7b742f83290e0feaa0f3eb1a55ba4ad78ca7d95c38aaba6e0adfebc1f4
4
- data.tar.gz: 984fd58f8cabb3303e5f9084eb90405d6cf39c23b9c42b304d1aa6a07afca24b
3
+ metadata.gz: 9213ac86e78dd85ff280d2048bd20fe3d074c3d6218cc45021b8c11eee7c720c
4
+ data.tar.gz: b2506ab43bb450a0496db0985ffa990b378ad591fa7be2a1c8db32223863680e
5
5
  SHA512:
6
- metadata.gz: ef77dd9a72a9577b0bf8eb78b300c41e098543422d7313a800693fbdc3e5a9ba5db82687cd0551eb362bb9cd8990e9cb943987ea442a3b99cdd52d02b30de3eb
7
- data.tar.gz: 4d4e036cc03aec4619c6e407255189f263d9cd167406cd1bf7f0c131047417a65a777c8c449701622fed38e908d8c3f6aab7f9cd6f7514668371fc33bf0eabb4
6
+ metadata.gz: 73331755a7074cd0eeb95c92901cb8bf477380672a553cd7ef4722ec4cb6ea6f2fd56634eef442fb4a59de961d102c7b8b0f5b39788d006c24d960573eb27500
7
+ data.tar.gz: fa9ee34a57cce815f63eba43208daac2232cd04456f1200adc4181e6a381407b93962d52cbc5f9b27398caa863c8ab371758f5c216613b0218f8b9e958de6bc5
data/lib/kennel/api.rb CHANGED
@@ -5,8 +5,6 @@ module Kennel
5
5
  class Api
6
6
  CACHE_FILE = ENV.fetch("KENNEL_API_CACHE_FILE", "tmp/cache/details")
7
7
 
8
- RateLimitParams = Data.define(:limit, :period, :remaining, :reset, :name)
9
-
10
8
  def self.with_tracking(api_resource, reply)
11
9
  klass = Models::Record.api_resource_map[api_resource]
12
10
  return reply unless klass # do not blow up on unknown models
@@ -125,20 +123,8 @@ module Kennel
125
123
  end
126
124
  end
127
125
 
128
- rate_limit = RateLimitParams.new(
129
- limit: response.headers["x-ratelimit-limit"],
130
- period: response.headers["x-ratelimit-period"],
131
- remaining: response.headers["x-ratelimit-remaining"],
132
- reset: response.headers["x-ratelimit-reset"],
133
- name: response.headers["x-ratelimit-name"]
134
- )
135
-
136
126
  if response.status == 429
137
- message = "Datadog rate limit #{rate_limit.name.inspect} hit"
138
- message += " (#{rate_limit.limit} requests per #{rate_limit.period} seconds)"
139
- message += "; sleeping #{rate_limit.reset} seconds before trying again"
140
- Kennel.err.puts message
141
- sleep rate_limit.reset.to_f
127
+ sleep_until_rate_limit_resets(response)
142
128
  redo
143
129
  end
144
130
 
@@ -161,6 +147,20 @@ module Kennel
161
147
  end
162
148
  end
163
149
 
150
+ def sleep_until_rate_limit_resets(response)
151
+ limit = response.headers["x-ratelimit-limit"]
152
+ period = response.headers["x-ratelimit-period"]
153
+ reset = response.headers["x-ratelimit-reset"]
154
+ name = response.headers["x-ratelimit-name"]
155
+
156
+ message = "Datadog rate limit #{name.inspect} hit"
157
+ message += " (#{limit} requests per #{period} seconds)"
158
+ message += "; sleeping #{reset} seconds before trying again"
159
+
160
+ Kennel.err.puts message
161
+ sleep reset.to_f
162
+ end
163
+
164
164
  # allow caching all requests to speedup/benchmark logic that includes repeated requests
165
165
  def with_cache(enabled, key)
166
166
  return yield unless enabled
@@ -32,6 +32,12 @@ module Kennel
32
32
  DEFAULT_ESCALATION_MESSAGE = ["", nil].freeze
33
33
  ALLOWED_PRIORITY_CLASSES = [NilClass, Integer].freeze
34
34
  SKIP_NOTIFY_NO_DATA_TYPES = ["event alert", "event-v2 alert", "log alert"].freeze
35
+ MINUTES_PER_UNIT = {
36
+ "m" => 1,
37
+ "h" => 60,
38
+ "d" => 60 * 24,
39
+ "w" => 60 * 24 * 7
40
+ }.freeze
35
41
 
36
42
  settings(
37
43
  :query, :name, :message, :escalation_message, :critical, :type, :renotify_interval, :warning, :timeout_h, :evaluation_delay,
@@ -49,13 +55,11 @@ module Kennel
49
55
  # datadog UI sets this to false by default, but true is safer
50
56
  # except for log alerts which will always have "no error" gaps and should default to false
51
57
  notify_no_data: -> { !SKIP_NOTIFY_NO_DATA_TYPES.include?(type) },
52
- no_data_timeframe: -> { 60 },
53
58
  notify_audit: -> { MONITOR_OPTION_DEFAULTS.fetch(:notify_audit) },
54
59
  new_host_delay: -> { MONITOR_OPTION_DEFAULTS.fetch(:new_host_delay) },
55
60
  new_group_delay: -> { nil },
56
61
  group_retention_duration: -> { MONITOR_OPTION_DEFAULTS.fetch(:group_retention_duration) },
57
62
  tags: -> { @project.tags },
58
- timeout_h: -> { MONITOR_OPTION_DEFAULTS.fetch(:timeout_h) },
59
63
  evaluation_delay: -> { MONITOR_OPTION_DEFAULTS.fetch(:evaluation_delay) },
60
64
  critical_recovery: -> { nil },
61
65
  warning_recovery: -> { nil },
@@ -187,6 +191,24 @@ module Kennel
187
191
  "cannot update type from #{actual_type} to #{type}"
188
192
  end
189
193
 
194
+ # deprecated this setting is no longer returned by dd for new monitors
195
+ # datadog UI warns when setting no data timeframe to less than 2x the query window
196
+ # limited to 24h because `no_data_timeframe must not exceed group retention` and max group retention is 24h
197
+ def no_data_timeframe
198
+ default = 60
199
+ if type == "query alert" && (minutes = query_window_minutes)
200
+ (minutes * 2).clamp(default, 24 * 60)
201
+ else
202
+ default
203
+ end
204
+ end
205
+
206
+ # validate that monitors that alert on no data resolve in external services by using timeout_h, so it sends a
207
+ # notification when the no data group is removed from the monitor, which datadog does automatically after 24h
208
+ def timeout_h
209
+ notify_no_data && on_missing_data != "resolve" ? 24 : MONITOR_OPTION_DEFAULTS.fetch(:timeout_h)
210
+ end
211
+
190
212
  def self.api_resource
191
213
  "monitor"
192
214
  end
@@ -372,6 +394,11 @@ module Kennel
372
394
  else # do nothing
373
395
  end
374
396
  end
397
+
398
+ def query_window_minutes
399
+ return unless (match = query.match(/^\s*\w+\(last_(?<count>\d+)(?<unit>[mhdw])\):/))
400
+ Integer(match["count"]) * MINUTES_PER_UNIT.fetch(match["unit"])
401
+ end
375
402
  end
376
403
  end
377
404
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "2.9.0"
3
+ VERSION = "2.10.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: 2.9.0
4
+ version: 2.10.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: 2025-12-20 00:00:00.000000000 Z
11
+ date: 2026-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diff-lcs