dead_bro 0.2.10 → 0.2.13
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/FEATURES.md +1 -6
- data/README.md +19 -0
- data/lib/dead_bro/client.rb +11 -3
- data/lib/dead_bro/configuration.rb +59 -3
- data/lib/dead_bro/job_sql_tracking_middleware.rb +2 -0
- data/lib/dead_bro/job_subscriber.rb +11 -1
- data/lib/dead_bro/sql_tracking_middleware.rb +2 -0
- data/lib/dead_bro/subscriber.rb +6 -0
- data/lib/dead_bro/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: 2c308968cd84cfa8df47974178b741ab2847809754e86dc49cbe716d07a7a0bb
|
|
4
|
+
data.tar.gz: 6cdfb10f1ac9b2ecd9994bf6f35d8468022dc024e16e9ab31c1664fa91db7041
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a8f31655b9512739fa991ee94675c1f948c5ae2229dbb9de62a4e3c6ea0b5a8883ea880f986d911044e200d0c8ae6e696f6d8a58e5c338da6c8c3756c08e543
|
|
7
|
+
data.tar.gz: ddf1ed72e8310eb1f42db17f5124b704c5214447706ed68c1f9bae9f47f669fbf56006733f430a064af0fc8965be161dbb85bcaca2aee6b6c14a68b4865216f9
|
data/FEATURES.md
CHANGED
|
@@ -284,12 +284,7 @@ A comprehensive feature list for comparing ApmBro with other APM (Application Pe
|
|
|
284
284
|
## Deployment & Environment
|
|
285
285
|
|
|
286
286
|
### Deploy Tracking
|
|
287
|
-
- **Deploy ID Resolution**: Multiple sources for deploy identification
|
|
288
|
-
- Explicit configuration
|
|
289
|
-
- Rails settings/credentials
|
|
290
|
-
- Environment variables (APM_BRO_DEPLOY_ID, GIT_REV)
|
|
291
|
-
- Heroku (HEROKU_SLUG_COMMIT)
|
|
292
|
-
- Process-stable UUID fallback
|
|
287
|
+
- **Deploy ID Resolution**: Multiple sources for deploy identification (`Configuration#deploy_id=` wins when set, then ENV in `Configuration::DEPLOY_REVISION_ENV_KEYS` order—including `DEAD_BRO_DEPLOY_ID`, git/CI vars, `DD_VERSION`, etc.), otherwise a **per-process UUID** (fine for single dyno/process; unusable alone for fleets like ECS replicas)
|
|
293
288
|
- **Revision Tracking**: Includes deploy/revision ID in all metric payloads
|
|
294
289
|
|
|
295
290
|
### Environment Support
|
data/README.md
CHANGED
|
@@ -30,6 +30,25 @@ end
|
|
|
30
30
|
|
|
31
31
|
That is enough to start shipping metrics. Create or copy the key from your DeadBro account, then wire it into `DEAD_BRO_API_KEY` (or assign `config.api_key` directly).
|
|
32
32
|
|
|
33
|
+
### Deploy / release tracking (ECS, Kubernetes, autoscaling groups)
|
|
34
|
+
|
|
35
|
+
DeadBro sends a **`revision`** string on every payload so charts and deploys group metrics by release. If you do **not** configure a stable value, the gem generates a UUID **once per Ruby process**. With multiple containers or EC2 instances, each replica then looks like a separate deployment.
|
|
36
|
+
|
|
37
|
+
**Use one shared identifier for every task in the same rollout**, for example:
|
|
38
|
+
|
|
39
|
+
- Set `DEAD_BRO_DEPLOY_ID` (or `dead_bro_DEPLOY_ID`) in the task definition / pod spec to your **git SHA**, **image digest**, or CD **release id** injected at build or deploy time.
|
|
40
|
+
- Or set it in Ruby (this wins over environment variables when non-blank):
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
DeadBro.configure do |config|
|
|
44
|
+
config.deploy_id = ENV.fetch("GIT_SHA") { raise "Set GIT_SHA in the task definition" }
|
|
45
|
+
end
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The gem also checks these environment variables in order (first non-empty wins): `DEAD_BRO_DEPLOY_ID`, `dead_bro_DEPLOY_ID`, `GIT_REV`, `GIT_COMMIT`, `GIT_COMMIT_SHA`, `GIT_SHA`, `CODEBUILD_RESOLVED_SOURCE_REVISION`, `HEROKU_SLUG_COMMIT`, `RENDER_GIT_COMMIT`, `DD_VERSION`, `APP_REVISION`, `RELEASE_VERSION`, `SOURCE_VERSION`.
|
|
49
|
+
|
|
50
|
+
For **Amazon ECS**, add one of these variables in your task definition from CodeBuild, GitHub Actions, or your pipeline so all tasks in the service share the same value for that image version.
|
|
51
|
+
|
|
33
52
|
### Dashboard configuration
|
|
34
53
|
|
|
35
54
|
Use the DeadBro UI to turn features on or off, set sample rates, define controller/job inclusions and exclusions, tune slow-query EXPLAIN, enable queue and system metrics, and adjust related limits. After you deploy the initializer above, those choices take effect when the gem receives them from the API (typically on the next successful metric or heartbeat response).
|
data/lib/dead_bro/client.rb
CHANGED
|
@@ -15,11 +15,12 @@ module DeadBro
|
|
|
15
15
|
def post_metric(event_name:, payload:, force: false)
|
|
16
16
|
return if @configuration.api_key.nil?
|
|
17
17
|
return unless @configuration.enabled
|
|
18
|
+
return if @configuration.skip_tracking?
|
|
18
19
|
return if !force && !@configuration.should_sample?
|
|
19
20
|
return if circuit_open?
|
|
20
21
|
|
|
21
22
|
payload = truncate_payload_for_request(payload)
|
|
22
|
-
body = {event: event_name, payload: payload, sent_at: Time.now.utc.iso8601, revision: @configuration.resolve_deploy_id}
|
|
23
|
+
body = {event: event_name, payload: payload, sent_at: Time.now.utc.iso8601, revision: @configuration.resolve_deploy_id, gem_version: DeadBro::VERSION}
|
|
23
24
|
|
|
24
25
|
dispatch_request(
|
|
25
26
|
url: metrics_endpoint_url,
|
|
@@ -35,7 +36,7 @@ module DeadBro
|
|
|
35
36
|
return if @configuration.api_key.nil?
|
|
36
37
|
|
|
37
38
|
@configuration.last_heartbeat_attempt_at = Time.now.utc
|
|
38
|
-
body = {event: "heartbeat", payload: {}, sent_at: Time.now.utc.iso8601, revision: @configuration.resolve_deploy_id}
|
|
39
|
+
body = {event: "heartbeat", payload: {}, sent_at: Time.now.utc.iso8601, revision: @configuration.resolve_deploy_id, gem_version: DeadBro::VERSION}
|
|
39
40
|
|
|
40
41
|
dispatch_request(
|
|
41
42
|
url: metrics_endpoint_url,
|
|
@@ -50,10 +51,11 @@ module DeadBro
|
|
|
50
51
|
def post_monitor_stats(payload)
|
|
51
52
|
return if @configuration.api_key.nil?
|
|
52
53
|
return unless @configuration.enabled
|
|
54
|
+
return if @configuration.skip_tracking?
|
|
53
55
|
return unless @configuration.job_queue_monitoring_enabled
|
|
54
56
|
return if circuit_open?
|
|
55
57
|
|
|
56
|
-
body = {payload: payload, sent_at: Time.now.utc.iso8601, revision: @configuration.resolve_deploy_id}
|
|
58
|
+
body = {payload: payload, sent_at: Time.now.utc.iso8601, revision: @configuration.resolve_deploy_id, gem_version: DeadBro::VERSION}
|
|
57
59
|
|
|
58
60
|
dispatch_request(
|
|
59
61
|
url: monitor_endpoint_url,
|
|
@@ -140,6 +142,12 @@ module DeadBro
|
|
|
140
142
|
@configuration.last_heartbeat_at = Time.now.utc
|
|
141
143
|
end
|
|
142
144
|
end
|
|
145
|
+
|
|
146
|
+
if response.is_a?(Net::HTTPSuccess)
|
|
147
|
+
@configuration.skip_until = nil
|
|
148
|
+
elsif response.is_a?(Net::HTTPInsufficientStorage)
|
|
149
|
+
@configuration.skip_until = Time.now.utc + DeadBro::Configuration::METRICS_BACKEND_SKIP_AFTER_507_SECONDS
|
|
150
|
+
end
|
|
143
151
|
elsif @circuit_breaker && @configuration.circuit_breaker_enabled
|
|
144
152
|
@circuit_breaker.record_failure
|
|
145
153
|
end
|
|
@@ -7,7 +7,7 @@ module DeadBro
|
|
|
7
7
|
# returns it in a response; local configure() values apply until the next remote update.
|
|
8
8
|
attr_accessor :api_key, :open_timeout, :read_timeout, :enabled, :ruby_dev,
|
|
9
9
|
:circuit_breaker_enabled, :circuit_breaker_failure_threshold, :circuit_breaker_recovery_timeout,
|
|
10
|
-
:circuit_breaker_retry_timeout, :
|
|
10
|
+
:circuit_breaker_retry_timeout, :disk_paths, :interfaces_ignore
|
|
11
11
|
|
|
12
12
|
# Remote-managed settings (overwritten by backend JSON `settings` on successful API responses)
|
|
13
13
|
attr_accessor :memory_tracking_enabled, :allocation_tracking_enabled,
|
|
@@ -22,6 +22,10 @@ module DeadBro
|
|
|
22
22
|
# Tracks when we last received settings from the backend (in-memory only)
|
|
23
23
|
attr_accessor :settings_received_at
|
|
24
24
|
|
|
25
|
+
# After HTTP 507 Insufficient Storage from the API, skip all tracking until this
|
|
26
|
+
# UTC time (in-memory only). Cleared on the next successful API response.
|
|
27
|
+
attr_accessor :skip_until
|
|
28
|
+
|
|
25
29
|
# Last successful heartbeat HTTP response time while disabled (in-memory only)
|
|
26
30
|
attr_accessor :last_heartbeat_at
|
|
27
31
|
|
|
@@ -30,6 +34,26 @@ module DeadBro
|
|
|
30
34
|
|
|
31
35
|
HEARTBEAT_INTERVAL = 60 # seconds
|
|
32
36
|
|
|
37
|
+
METRICS_BACKEND_SKIP_AFTER_507_SECONDS = 600 # 10 minutes
|
|
38
|
+
|
|
39
|
+
# First non-empty ENV value wins for release/revision payloads and deploy grouping on the server.
|
|
40
|
+
# Order is roughly: DeadBro-native → common CI/hosting → observability tooling.
|
|
41
|
+
DEPLOY_REVISION_ENV_KEYS = %w[
|
|
42
|
+
DEAD_BRO_DEPLOY_ID
|
|
43
|
+
dead_bro_DEPLOY_ID
|
|
44
|
+
GIT_REV
|
|
45
|
+
GIT_COMMIT
|
|
46
|
+
GIT_COMMIT_SHA
|
|
47
|
+
GIT_SHA
|
|
48
|
+
CODEBUILD_RESOLVED_SOURCE_REVISION
|
|
49
|
+
HEROKU_SLUG_COMMIT
|
|
50
|
+
RENDER_GIT_COMMIT
|
|
51
|
+
DD_VERSION
|
|
52
|
+
APP_REVISION
|
|
53
|
+
RELEASE_VERSION
|
|
54
|
+
SOURCE_VERSION
|
|
55
|
+
].freeze
|
|
56
|
+
|
|
33
57
|
REMOTE_SETTING_KEYS = %w[
|
|
34
58
|
enabled sample_rate memory_tracking_enabled allocation_tracking_enabled
|
|
35
59
|
explain_analyze_enabled slow_query_threshold_ms max_sql_queries_to_send max_logs_to_send
|
|
@@ -47,7 +71,7 @@ module DeadBro
|
|
|
47
71
|
@circuit_breaker_failure_threshold = 3
|
|
48
72
|
@circuit_breaker_recovery_timeout = 60
|
|
49
73
|
@circuit_breaker_retry_timeout = 300
|
|
50
|
-
@
|
|
74
|
+
@explicit_deploy_revision = nil
|
|
51
75
|
@disk_paths = ["/"]
|
|
52
76
|
@interfaces_ignore = %w[lo lo0 docker0]
|
|
53
77
|
|
|
@@ -69,11 +93,23 @@ module DeadBro
|
|
|
69
93
|
@enable_system_stats = false
|
|
70
94
|
|
|
71
95
|
@settings_received_at = nil
|
|
96
|
+
@skip_until = nil
|
|
72
97
|
@last_heartbeat_at = nil
|
|
73
98
|
@last_heartbeat_attempt_at = nil
|
|
74
99
|
@settings_mutex = Mutex.new
|
|
75
100
|
end
|
|
76
101
|
|
|
102
|
+
# Current release revision sent as `revision` on all API payloads — same semantics as `#resolve_deploy_id`.
|
|
103
|
+
def deploy_id
|
|
104
|
+
resolve_deploy_id
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Overrides ENV-based resolution when set to a non-empty string (or clears override when nil/blank).
|
|
108
|
+
def deploy_id=(value)
|
|
109
|
+
s = value&.respond_to?(:to_s) ? value.to_s.strip : ""
|
|
110
|
+
@explicit_deploy_revision = s.empty? ? nil : s
|
|
111
|
+
end
|
|
112
|
+
|
|
77
113
|
def excluded_controllers=(value)
|
|
78
114
|
@excluded_controllers = Array(value).map(&:to_s)
|
|
79
115
|
@compiled_excluded_controllers = compile_patterns(@excluded_controllers)
|
|
@@ -123,8 +159,28 @@ module DeadBro
|
|
|
123
159
|
last_heartbeat_attempt_at.nil? || (Time.now.utc - last_heartbeat_attempt_at) >= HEARTBEAT_INTERVAL
|
|
124
160
|
end
|
|
125
161
|
|
|
162
|
+
def skip_tracking?
|
|
163
|
+
t = skip_until
|
|
164
|
+
return false unless t
|
|
165
|
+
|
|
166
|
+
Time.now.utc < t
|
|
167
|
+
end
|
|
168
|
+
|
|
126
169
|
def resolve_deploy_id
|
|
127
|
-
|
|
170
|
+
explicit = @explicit_deploy_revision&.to_s&.strip
|
|
171
|
+
return explicit unless explicit.nil? || explicit.empty?
|
|
172
|
+
|
|
173
|
+
DEPLOY_REVISION_ENV_KEYS.each do |key|
|
|
174
|
+
v = ENV[key]
|
|
175
|
+
next unless v.respond_to?(:to_s)
|
|
176
|
+
|
|
177
|
+
stripped = v.to_s.strip
|
|
178
|
+
next if stripped.empty?
|
|
179
|
+
|
|
180
|
+
return stripped
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
DeadBro.process_deploy_id
|
|
128
184
|
end
|
|
129
185
|
|
|
130
186
|
def excluded_controller?(controller_name, action_name = nil)
|
|
@@ -5,6 +5,8 @@ module DeadBro
|
|
|
5
5
|
def self.subscribe!
|
|
6
6
|
# Start SQL tracking when a job begins - use the start event, not the complete event
|
|
7
7
|
ActiveSupport::Notifications.subscribe("perform_start.active_job") do |name, started, finished, _unique_id, data|
|
|
8
|
+
next if DeadBro.configuration.skip_tracking?
|
|
9
|
+
|
|
8
10
|
# Clear logs for this job
|
|
9
11
|
DeadBro.logger.clear
|
|
10
12
|
|
|
@@ -15,6 +15,11 @@ module DeadBro
|
|
|
15
15
|
# Track job execution
|
|
16
16
|
ActiveSupport::Notifications.subscribe(JOB_EVENT_NAME) do |name, started, finished, _unique_id, data|
|
|
17
17
|
begin
|
|
18
|
+
if DeadBro.configuration.skip_tracking?
|
|
19
|
+
drain_job_tracking
|
|
20
|
+
next
|
|
21
|
+
end
|
|
22
|
+
|
|
18
23
|
job_class_name = data[:job].class.name
|
|
19
24
|
if DeadBro.configuration.excluded_job?(job_class_name)
|
|
20
25
|
drain_job_tracking
|
|
@@ -106,6 +111,11 @@ module DeadBro
|
|
|
106
111
|
# Track job exceptions
|
|
107
112
|
ActiveSupport::Notifications.subscribe(JOB_EXCEPTION_EVENT_NAME) do |name, started, finished, _unique_id, data|
|
|
108
113
|
begin
|
|
114
|
+
if DeadBro.configuration.skip_tracking?
|
|
115
|
+
drain_job_tracking
|
|
116
|
+
next
|
|
117
|
+
end
|
|
118
|
+
|
|
109
119
|
job_class_name = data[:job].class.name
|
|
110
120
|
if DeadBro.configuration.excluded_job?(job_class_name)
|
|
111
121
|
next
|
|
@@ -215,7 +225,7 @@ module DeadBro
|
|
|
215
225
|
(arg.length > 200) ? arg[0, 200] + "..." : arg
|
|
216
226
|
when Hash
|
|
217
227
|
# Filter sensitive keys and limit size
|
|
218
|
-
filtered = arg.
|
|
228
|
+
filtered = arg.reject { |k, _| %w[password token secret key].include?(k.to_s) }
|
|
219
229
|
(filtered.keys.size > 20) ? filtered.first(20).to_h : filtered
|
|
220
230
|
when Array
|
|
221
231
|
arg.first(5)
|
data/lib/dead_bro/subscriber.rb
CHANGED
|
@@ -16,6 +16,12 @@ module DeadBro
|
|
|
16
16
|
next
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
if DeadBro.configuration.skip_tracking?
|
|
20
|
+
client.post_heartbeat if DeadBro.configuration.heartbeat_due?
|
|
21
|
+
drain_request_tracking
|
|
22
|
+
next
|
|
23
|
+
end
|
|
24
|
+
|
|
19
25
|
# Skip excluded controllers or controller#action pairs
|
|
20
26
|
# Also check exclusive_controller_actions - if defined, only track those
|
|
21
27
|
notification = data.is_a?(Hash) ? data : {}
|
data/lib/dead_bro/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dead_bro
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Emanuel Comsa
|
|
@@ -65,7 +65,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
65
65
|
requirements:
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
68
|
+
version: 2.7.0
|
|
69
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
70
|
requirements:
|
|
71
71
|
- - ">="
|