activerabbit-ai 0.6.2 → 0.6.3

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: c71eb72533f7d6588444722f3ca8502230006f75bd12cee11b7f585e0a00aa1a
4
- data.tar.gz: e187bb60976eda2eccd743589737240f40930897f6063c9ff6b061e517786135
3
+ metadata.gz: d02e83fd5992873b3b7aabb322ab9e3c914b91e7e64b4a80be335007561bc404
4
+ data.tar.gz: d60e55a0fcab7c981d7b7a214cff142825c613e7d32ddf15533bccd451cb6657
5
5
  SHA512:
6
- metadata.gz: 97ffc354514d50a73b8f32dd086e6d2a095bea00e0ce095464c7ea0a389fc8b1304359125a798abfabf4f456095aec51f3a086a2f6cb1d4c0d3eb5367d1744f0
7
- data.tar.gz: dafed4a9c5c2de391bdc1527de3092340a093afdde7cc336a04c533c7d4898d5fad4987992fa3861dbbf806dd792eaa8e2a1037cc0a00133e235cd86747a4e3e
6
+ metadata.gz: 32a57acfde857e55a97932f56ae1a449f04a7e51e7ad8903d2cf63380ddd338cf0930d18785559f2bf358250470ce1890f503dde670aaebddf1756f6b5675c2f
7
+ data.tar.gz: dad613e6edf130e26c185b2b17670366400c4a40a36ebf0d8017a77189f01c1647c0cbd3ef7f810727a47beccf46b5f482394b681424982ad64a020eb1bcd768
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.6.3] - 2026-03-30
6
+
7
+ ### Added
8
+ - **HTTP client request id**: `make_request` sends a stable `X-Request-Id` header (same value across retries) so APIs can correlate or deduplicate requests after timeouts and transient failures.
9
+ - **Explicit `securerandom` load**: `HttpClient` requires `securerandom` so `SecureRandom` is always available regardless of load order.
10
+
5
11
  ## [0.6.2] - 2026-01-26
6
12
 
7
13
  ### Fixed
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRabbit
4
+ module Client
5
+ # Sentry-style cron check-ins for Active Job: in_progress at start, ok on success, error on failure.
6
+ #
7
+ # class BackupJob < ApplicationJob
8
+ # include ActiveRabbit::Client::CronMonitor
9
+ # active_rabbit_cron slug: "nightly_backup"
10
+ #
11
+ # def perform
12
+ # # ...
13
+ # end
14
+ # end
15
+ module CronMonitor
16
+ def self.included(base)
17
+ base.extend(ClassMethods)
18
+ base.class_eval do
19
+ around_perform :_active_rabbit_cron_monitor_around
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ # @param value [String, Symbol, Hash] string/symbol slug, or { slug: "..." }
25
+ def active_rabbit_cron(value = nil)
26
+ case value
27
+ when String, Symbol
28
+ @active_rabbit_cron_slug = value.to_s.strip
29
+ when Hash
30
+ s = value[:slug].to_s.strip
31
+ @active_rabbit_cron_slug = s.empty? ? nil : s
32
+ when nil
33
+ @active_rabbit_cron_slug = nil
34
+ end
35
+ end
36
+
37
+ def active_rabbit_cron_monitor_slug
38
+ slug = instance_variable_defined?(:@active_rabbit_cron_slug) ? @active_rabbit_cron_slug : nil
39
+ return slug if slug.is_a?(String) && !slug.strip.empty?
40
+
41
+ name.to_s.underscore.tr("/", "_")
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def _active_rabbit_cron_monitor_around(&block)
48
+ slug = self.class.active_rabbit_cron_monitor_slug
49
+ if slug.to_s.strip.empty? || !ActiveRabbit::Client.configured?
50
+ block.call
51
+ return
52
+ end
53
+
54
+ ActiveRabbit::Client.capture_cron_check_in(slug, :in_progress)
55
+ begin
56
+ block.call
57
+ rescue StandardError => e
58
+ ActiveRabbit::Client.capture_cron_check_in(slug, :error)
59
+ raise e
60
+ end
61
+ ActiveRabbit::Client.capture_cron_check_in(slug, :ok)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -131,6 +131,9 @@ module ActiveRabbit
131
131
  structured_stack_trace: structured_frames,
132
132
  culprit_frame: culprit_frame,
133
133
 
134
+ # Error source: backend (Ruby gem) vs frontend (JS SDK)
135
+ source: "backend",
136
+
134
137
  # Timing and environment
135
138
  occurred_at: Time.now.iso8601(3),
136
139
  environment: configuration.environment || 'development',
@@ -6,6 +6,7 @@ require "json"
6
6
  require "concurrent"
7
7
  require "time"
8
8
  require "uri"
9
+ require "securerandom"
9
10
 
10
11
  module ActiveRabbit
11
12
  module Client
@@ -140,6 +141,12 @@ module ActiveRabbit
140
141
  { success: false, error: e.message }
141
142
  end
142
143
 
144
+ # Cron / heartbeat check-in (project token + monitor slug). Synchronous, not batched.
145
+ def post_cron_check_in(slug:, status: :ok)
146
+ payload = stringify_and_sanitize({ slug: slug.to_s, status: status.to_s })
147
+ make_request(:post, "/api/v1/cron/check_ins", payload)
148
+ end
149
+
143
150
  def flush
144
151
  return if @request_queue.empty?
145
152
 
@@ -225,12 +232,16 @@ module ActiveRabbit
225
232
  log(:debug, "[ActiveRabbit] Request headers: X-Project-Token=#{configuration.api_key}, X-Project-ID=#{configuration.project_id}")
226
233
  log(:debug, "[ActiveRabbit] Request body: #{safe_preview(data)}")
227
234
 
235
+ # Generate a stable request ID for dedup — same ID is reused across retries
236
+ # so the server can reject duplicates when we retry after a timeout.
237
+ request_id = SecureRandom.uuid
238
+
228
239
  # Retry logic with exponential backoff
229
240
  retries = 0
230
241
  max_retries = configuration.retry_count
231
242
 
232
243
  begin
233
- response = perform_request(uri, method, data)
244
+ response = perform_request(uri, method, data, request_id: request_id)
234
245
  log(:info, "[ActiveRabbit] Response status: #{response.code}")
235
246
  log(:debug, "[ActiveRabbit] Response headers: #{response.to_hash.inspect}")
236
247
  log(:debug, "[ActiveRabbit] Response body: #{response.body}")
@@ -273,7 +284,7 @@ module ActiveRabbit
273
284
  end
274
285
  end
275
286
 
276
- def perform_request(uri, method, data)
287
+ def perform_request(uri, method, data, request_id: nil)
277
288
  log(:debug, "[ActiveRabbit] Making HTTP request: #{method.upcase} #{uri}")
278
289
  http = Net::HTTP.new(uri.host, uri.port)
279
290
 
@@ -308,6 +319,7 @@ module ActiveRabbit
308
319
  request['Accept'] = 'application/json'
309
320
  request['User-Agent'] = "ActiveRabbit-Client/#{ActiveRabbit::Client::VERSION}"
310
321
  request['X-Project-Token'] = configuration.api_key
322
+ request['X-Request-Id'] = request_id if request_id
311
323
 
312
324
  if configuration.project_id
313
325
  request['X-Project-ID'] = configuration.project_id
@@ -1,5 +1,5 @@
1
1
  module ActiveRabbit
2
2
  module Client
3
- VERSION = "0.6.2"
3
+ VERSION = "0.6.3"
4
4
  end
5
5
  end
@@ -24,6 +24,12 @@ rescue LoadError
24
24
  # Sidekiq not available, skip integration
25
25
  end
26
26
 
27
+ # Active Job cron monitors (optional)
28
+ begin
29
+ require_relative "client/cron_monitor" if defined?(ActiveJob)
30
+ rescue LoadError
31
+ end
32
+
27
33
  module ActiveRabbit
28
34
  module Client
29
35
  class Error < StandardError; end
@@ -144,6 +150,19 @@ module ActiveRabbit
144
150
  http_client.post_release(payload)
145
151
  end
146
152
 
153
+ # Cron / heartbeat monitor (uses project API token + slug). Status: :ok, :success, :in_progress, :error.
154
+ def capture_cron_check_in(slug, status = :ok)
155
+ return unless configured?
156
+
157
+ s = slug.to_s.strip
158
+ return nil if s.empty?
159
+
160
+ http_client.post_cron_check_in(slug: s, status: status)
161
+ rescue => e
162
+ log(:error, "[ActiveRabbit] capture_cron_check_in failed: #{e.class}: #{e.message}")
163
+ nil
164
+ end
165
+
147
166
  def log(level, message)
148
167
  cfg = configuration
149
168
  return if cfg.nil? || cfg.disable_console_logs
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerabbit-ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Shapalov
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2026-01-27 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: concurrent-ruby
@@ -90,6 +89,7 @@ files:
90
89
  - lib/active_rabbit/client/action_mailer_patch.rb
91
90
  - lib/active_rabbit/client/active_job_extensions.rb
92
91
  - lib/active_rabbit/client/configuration.rb
92
+ - lib/active_rabbit/client/cron_monitor.rb
93
93
  - lib/active_rabbit/client/dedupe.rb
94
94
  - lib/active_rabbit/client/error_reporter.rb
95
95
  - lib/active_rabbit/client/event_processor.rb
@@ -120,7 +120,6 @@ metadata:
120
120
  allowed_push_host: https://rubygems.org
121
121
  source_code_uri: https://github.com/bugrabbit/active_rabbit-client
122
122
  changelog_uri: https://github.com/bugrabbit/active_rabbit-client/blob/main/CHANGELOG.md
123
- post_install_message:
124
123
  rdoc_options: []
125
124
  require_paths:
126
125
  - lib
@@ -135,8 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
134
  - !ruby/object:Gem::Version
136
135
  version: '0'
137
136
  requirements: []
138
- rubygems_version: 3.5.15
139
- signing_key:
137
+ rubygems_version: 4.0.7
140
138
  specification_version: 4
141
139
  summary: Ruby client for ActiveRabbit.ai application monitoring and error tracking
142
140
  test_files: []