debugbundle 0.1.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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +17 -0
  3. data/Makefile +43 -0
  4. data/README.md +168 -0
  5. data/debugbundle.gemspec +30 -0
  6. data/lib/debugbundle/client.rb +724 -0
  7. data/lib/debugbundle/config.rb +144 -0
  8. data/lib/debugbundle/logging.rb +77 -0
  9. data/lib/debugbundle/rack/middleware.rb +94 -0
  10. data/lib/debugbundle/rack/relay_middleware.rb +37 -0
  11. data/lib/debugbundle/rails/railtie.rb +35 -0
  12. data/lib/debugbundle/rails/relay_endpoint.rb +100 -0
  13. data/lib/debugbundle/rails.rb +10 -0
  14. data/lib/debugbundle/redaction.rb +151 -0
  15. data/lib/debugbundle/relay/handler.rb +231 -0
  16. data/lib/debugbundle/relay.rb +4 -0
  17. data/lib/debugbundle/remote_config.rb +153 -0
  18. data/lib/debugbundle/runtime.rb +22 -0
  19. data/lib/debugbundle/sidekiq/server_middleware.rb +34 -0
  20. data/lib/debugbundle/suppression.rb +121 -0
  21. data/lib/debugbundle/transport.rb +190 -0
  22. data/lib/debugbundle/trigger_token.rb +122 -0
  23. data/lib/debugbundle/version.rb +5 -0
  24. data/lib/debugbundle.rb +93 -0
  25. data/spec/client_spec.rb +236 -0
  26. data/spec/debugbundle_spec.rb +54 -0
  27. data/spec/file_transport_spec.rb +54 -0
  28. data/spec/logger_integration_spec.rb +118 -0
  29. data/spec/rack_integration_spec.rb +44 -0
  30. data/spec/rack_middleware_spec.rb +206 -0
  31. data/spec/rails_railtie_spec.rb +96 -0
  32. data/spec/rails_relay_spec.rb +121 -0
  33. data/spec/redaction_spec.rb +42 -0
  34. data/spec/relay_spec.rb +178 -0
  35. data/spec/remote_config_spec.rb +402 -0
  36. data/spec/sidekiq_integration_spec.rb +66 -0
  37. data/spec/sidekiq_middleware_spec.rb +50 -0
  38. data/spec/spec_helper.rb +20 -0
  39. data/spec/suppression_spec.rb +16 -0
  40. metadata +113 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 57ff4962fe1910ae27c974401d207da7c6a1afc1d22f9a5951b93d4c338f1f65
4
+ data.tar.gz: cb7d91a8088df973a7a4b344c79799e348fb0cbccc0544eac5f898c458bb931b
5
+ SHA512:
6
+ metadata.gz: 1eaccc22806e5bf4844d7a1820c52f67add73f63025f5023f664570ac64b4fb6ba46e62faeb2d6a8380c95bd7e1c7efd469cfbba4bb4de81613a4b4476305e40
7
+ data.tar.gz: 55ab0c5a6f38b356ad6a49d580fcf95ac68075f3d9633aabb136c70cd9c8d5f9908a0a38a83eb162cd1387d3ce4ca3edb979bb4b727430306facfda3dd50c145
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem 'json_schemer', '~> 2.4'
9
+ gem 'rack-test', '~> 2.1'
10
+ gem 'rails', '~> 7.1'
11
+ gem 'rake', '~> 13.2'
12
+ gem 'rspec', '~> 3.13'
13
+ gem 'rubocop', '~> 1.76', require: false
14
+ gem 'sidekiq', '~> 7.0', require: false
15
+ gem 'simplecov', '~> 0.22', require: false
16
+ gem 'webmock', '~> 3.25'
17
+ end
data/Makefile ADDED
@@ -0,0 +1,43 @@
1
+ SHELL := /bin/sh
2
+
3
+ RUBY_IMAGE ?= ruby:3.4.2
4
+ WORKDIR := /workspace
5
+ BUNDLE_GEMFILE ?= Gemfile
6
+
7
+ DOCKER_RUN = docker run --rm -t \
8
+ -v "$(PWD):$(WORKDIR)" \
9
+ -w "$(WORKDIR)" \
10
+ $(RUBY_IMAGE)
11
+
12
+ BUNDLE_ENV = BUNDLE_GEMFILE="$(BUNDLE_GEMFILE)"
13
+
14
+ .PHONY: bundle-install test lint build shell compat-rack compat-rails compat-sidekiq compat
15
+
16
+ bundle-install:
17
+ $(DOCKER_RUN) sh -lc "$(BUNDLE_ENV) bundle config set path vendor/bundle && $(BUNDLE_ENV) bundle install"
18
+
19
+ test:
20
+ $(DOCKER_RUN) sh -lc "$(BUNDLE_ENV) bundle config set path vendor/bundle && $(BUNDLE_ENV) bundle install && $(BUNDLE_ENV) bundle exec rspec"
21
+
22
+ lint:
23
+ $(DOCKER_RUN) sh -lc "$(BUNDLE_ENV) bundle config set path vendor/bundle && $(BUNDLE_ENV) bundle install && $(BUNDLE_ENV) bundle exec rubocop"
24
+
25
+ build:
26
+ $(DOCKER_RUN) sh -lc "$(BUNDLE_ENV) bundle config set path vendor/bundle && $(BUNDLE_ENV) bundle install && gem build debugbundle.gemspec"
27
+
28
+ compat-rack:
29
+ docker run --rm -t -v "$(PWD):$(WORKDIR)" -w "$(WORKDIR)" ruby:3.1.6 sh -lc 'SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rack_2_2.gemfile" bundle config set path vendor/bundle && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rack_2_2.gemfile" bundle install && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rack_2_2.gemfile" bundle exec rspec spec/rack_integration_spec.rb spec/rack_middleware_spec.rb spec/relay_spec.rb'
30
+ docker run --rm -t -v "$(PWD):$(WORKDIR)" -w "$(WORKDIR)" ruby:3.4.2 sh -lc 'SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rack_3.gemfile" bundle config set path vendor/bundle && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rack_3.gemfile" bundle install && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rack_3.gemfile" bundle exec rspec spec/rack_integration_spec.rb spec/rack_middleware_spec.rb spec/relay_spec.rb'
31
+
32
+ compat-rails:
33
+ docker run --rm -t -v "$(PWD):$(WORKDIR)" -w "$(WORKDIR)" ruby:3.1.6 sh -lc 'SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rails_7_0.gemfile" bundle config set path vendor/bundle && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rails_7_0.gemfile" bundle install && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rails_7_0.gemfile" bundle exec rspec spec/rails_relay_spec.rb spec/rails_railtie_spec.rb'
34
+ docker run --rm -t -v "$(PWD):$(WORKDIR)" -w "$(WORKDIR)" ruby:3.4.2 sh -lc 'SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rails_7_1.gemfile" bundle config set path vendor/bundle && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rails_7_1.gemfile" bundle install && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/rails_7_1.gemfile" bundle exec rspec spec/rails_relay_spec.rb spec/rails_railtie_spec.rb'
35
+
36
+ compat-sidekiq:
37
+ docker run --rm -t -v "$(PWD):$(WORKDIR)" -w "$(WORKDIR)" ruby:3.2 sh -lc 'SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/sidekiq_7.gemfile" bundle config set path vendor/bundle && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/sidekiq_7.gemfile" bundle install && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/sidekiq_7.gemfile" bundle exec rspec spec/sidekiq_middleware_spec.rb spec/sidekiq_integration_spec.rb'
38
+ docker run --rm -t -v "$(PWD):$(WORKDIR)" -w "$(WORKDIR)" ruby:3.4.2 sh -lc 'SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/sidekiq_8.gemfile" bundle config set path vendor/bundle && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/sidekiq_8.gemfile" bundle install && SIMPLECOV_MINIMUM_COVERAGE=0 BUNDLE_GEMFILE="gemfiles/sidekiq_8.gemfile" bundle exec rspec spec/sidekiq_middleware_spec.rb spec/sidekiq_integration_spec.rb'
39
+
40
+ compat: compat-rack compat-rails compat-sidekiq
41
+
42
+ shell:
43
+ $(DOCKER_RUN) sh
data/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # debugbundle
2
+
3
+ Ruby SDK for DebugBundle.
4
+
5
+ Use this gem to capture Ruby backend exceptions, request metadata, structured logs, runtime context, probe data, and browser relay traffic. It supports a singleton facade plus instance clients for Rack, Rails, Sidekiq, and explicit Ruby instrumentation.
6
+
7
+ ## Installation
8
+
9
+ ```ruby
10
+ gem "debugbundle"
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```ruby
16
+ require "debugbundle"
17
+
18
+ DebugBundle.init(
19
+ project_token: ENV.fetch("DEBUGBUNDLE_TOKEN"),
20
+ service: "checkout-api",
21
+ environment: ENV.fetch("APP_ENV", "production")
22
+ )
23
+
24
+ DebugBundle.capture_logger(Logger.new($stdout))
25
+ ```
26
+
27
+ `DebugBundle.init(...)` arms best-effort process exception capture automatically through `at_exit` and thread exception hooks.
28
+
29
+ Capture handled exceptions, messages, requests, and probes explicitly:
30
+
31
+ ```ruby
32
+ begin
33
+ perform_checkout
34
+ rescue => error
35
+ DebugBundle.capture_exception(error, context: { order_id: 123 })
36
+ end
37
+
38
+ DebugBundle.capture_log("payment retry failed", level: :warning, context: { order_id: 123 })
39
+ DebugBundle.capture_message("worker started", level: :info)
40
+ DebugBundle.probe("checkout.tax", { region: "us-east-1" })
41
+ DebugBundle.flush
42
+ ```
43
+
44
+ ## Framework integrations
45
+
46
+ | Surface | Integration |
47
+ | --- | --- |
48
+ | Rack | `DebugBundle::Rack::Middleware` |
49
+ | Rails | Railtie bootstrap, Rack middleware, and auto-mounted relay route |
50
+ | Sidekiq | `DebugBundle::Sidekiq::ServerMiddleware` |
51
+ | Ruby Logger | `DebugBundle.capture_logger(logger)` |
52
+ | Semantic Logger | `DebugBundle.capture_semantic_logger` |
53
+ | Browser relay | `DebugBundle::Relay::Handler` or `DebugBundle::Rack::RelayMiddleware` |
54
+
55
+ ## Browser relay
56
+
57
+ Ruby backends can receive browser events at `POST /debugbundle/browser` through the relay handler.
58
+
59
+ Rails applications can let the Railtie append that route automatically, or override it with:
60
+
61
+ - `config.debugbundle.relay_enabled = false` to disable automatic mounting
62
+ - `config.debugbundle.relay_path = "/debugbundle/browser"` to change the mounted path
63
+ - `config.debugbundle.relay_allowed_origins = ["https://app.example.com"]` to pin allowed origins
64
+ - `config.debugbundle.relay_rate_limit_per_minute = 120` to adjust per-IP relay throttling
65
+ - `config.debugbundle.relay_rate_limit_store = Rails.cache` to share relay throttling across processes
66
+ - `config.debugbundle.relay_handler = custom_handler` to supply a custom relay handler
67
+
68
+ The relay:
69
+
70
+ - validates same-origin requests by default
71
+ - enforces `Content-Type: application/json`
72
+ - caps request bodies at 256 KB
73
+ - strips browser-supplied credentials and trust-sensitive fields
74
+ - preserves browser correlation fields such as `trace_id`
75
+ - supports local-only event writes and connected durable forwarding
76
+
77
+ ## Remote probes
78
+
79
+ Probe buffers stay local and flush on captured exceptions by default. Paid-tier projects can also activate probes for immediate `probe_event` shipping through the polled remote config.
80
+
81
+ For one-off request diagnostics, the Ruby SDK also accepts signed trigger tokens:
82
+
83
+ - header: `X-DebugBundle-Probe-Trigger: dbundle_probe_...`
84
+ - query parameter: `?_debug_probe=dbundle_probe_...`
85
+
86
+ Matching probes still stay in the local ring buffer, but the triggered request also emits standalone `probe_event` records immediately when the token is valid.
87
+
88
+ ## Configuration
89
+
90
+ | Option | Default | Purpose |
91
+ | --- | --- | --- |
92
+ | `project_token` | required | Write-only DebugBundle project token. |
93
+ | `service` | `ruby-service` | Service name used in event envelopes. |
94
+ | `environment` | `development` | Runtime environment. |
95
+ | `endpoint` | `https://api.debugbundle.com/v1/events` | Connected ingestion endpoint. |
96
+ | `enabled` | `true` | Disable all capture without removing instrumentation. |
97
+ | `project_mode` | `connected` | `connected` or `local_only`. |
98
+ | `local_events_dir` | `.debugbundle/local/events` | Local event file destination. |
99
+ | `spool_dir` | `.debugbundle/local/browser-relay-spool` | Relay durable spool destination. |
100
+ | `redact_fields` | `[]` | Additional sensitive field names merged with built-in redaction defaults. Rails `filter_parameters` are added automatically. |
101
+ | `batch_size` | `25` | Max events per flush batch. |
102
+ | `flush_interval` | `5` | Flush interval in seconds. |
103
+ | `sample_rate` | `1.0` | Fraction of events kept before transport. |
104
+ | `log_level` | `warning` | Minimum captured log severity. |
105
+ | `relay_enabled` | `true` | Enable relay handling when using the Rails helper surface. |
106
+ | `relay_rate_limit_per_minute` | `60` | Per-IP rate limit for browser relay requests. |
107
+ | `relay_durable_write` | `true` | Write relay batches to the local spool before connected forwarding. |
108
+ | `max_probe_labels` | `50` | Max distinct probe labels kept in memory. |
109
+ | `max_probe_entries_per_label` | `10` | Max entries retained per probe label. |
110
+ | `probe_flush_on_error` | `true` | Attach probe buffers to captured exceptions. |
111
+ | `probes_poll_interval` | `60` | Remote config poll interval in seconds. |
112
+
113
+ ## Safety defaults
114
+
115
+ - SDK failures are isolated from host application failures.
116
+ - Sensitive values are redacted before buffering or transport.
117
+ - Rails `filter_parameters` are merged into redaction automatically.
118
+ - Duplicate event storms are suppressed locally.
119
+ - Request headers use an allowlist by default.
120
+ - Local file writes use owner-only permissions.
121
+ - `development`, `local`, and `test` environments write local event files by default.
122
+ - Browser relay requests cannot smuggle server-side credentials.
123
+
124
+ ## Examples
125
+
126
+ - Rack app: [examples/rack_app.rb](examples/rack_app.rb)
127
+ - Rails initializer: [examples/rails_initializer.rb](examples/rails_initializer.rb)
128
+ - Sidekiq server setup: [examples/sidekiq_initializer.rb](examples/sidekiq_initializer.rb)
129
+
130
+ ## Local development
131
+
132
+ The project defaults to Docker-backed commands:
133
+
134
+ ```sh
135
+ make bundle-install
136
+ make test
137
+ make compat
138
+ make lint
139
+ make build
140
+ ```
141
+
142
+ Compatibility lanes are also exercised in CI for Rails 7.0 and 7.1, Rack 2.2 and 3.x, and Sidekiq 7.x and 8.x.
143
+
144
+ ## Release
145
+
146
+ The repository ships a GitHub Actions release workflow at `.github/workflows/release.yml`.
147
+
148
+ - Push a `v*` tag or run the workflow manually with a `version` input.
149
+ - Configure the `RUBYGEMS_API_KEY` repository secret before enabling publish.
150
+ - The workflow runs lint, tests, gem build, local smoke install, GitHub release creation, RubyGems publish, and a published-gem smoke install.
151
+
152
+ ## Supported targets
153
+
154
+ - Ruby 3.1+
155
+ - Rails 7.0+
156
+ - Rack 2.2+
157
+ - Sidekiq 7.x+
158
+
159
+ ## Documentation
160
+
161
+ - Ruby SDK docs: https://debugbundle.com/docs/sdks/ruby
162
+ - SDK overview: https://debugbundle.com/docs/sdks
163
+ - Browser relay: https://debugbundle.com/docs/sdks/browser-relay
164
+ - Repository: https://github.com/debugbundle/debugbundle-ruby
165
+
166
+ ## License
167
+
168
+ AGPL-3.0-only. See LICENSE.
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/debugbundle/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'debugbundle'
7
+ spec.version = DebugBundle::VERSION
8
+ spec.authors = ['DebugBundle']
9
+ spec.email = ['support@debugbundle.com']
10
+
11
+ spec.summary = 'DebugBundle SDK for Ruby'
12
+ spec.description = 'Production-ready error, request, log, and probe capture for Ruby services.'
13
+ spec.homepage = 'https://debugbundle.com/docs/sdks/ruby'
14
+ spec.license = 'AGPL-3.0-only'
15
+ spec.required_ruby_version = '>= 3.1'
16
+
17
+ spec.metadata = {
18
+ 'homepage_uri' => spec.homepage,
19
+ 'source_code_uri' => 'https://github.com/debugbundle/debugbundle-ruby',
20
+ 'changelog_uri' => 'https://github.com/debugbundle/debugbundle-ruby/blob/main/CHANGELOG.md',
21
+ 'rubygems_mfa_required' => 'true'
22
+ }
23
+
24
+ spec.files = Dir.glob('{lib,spec}/**/*') + %w[Gemfile Makefile README.md debugbundle.gemspec]
25
+ spec.bindir = 'exe'
26
+ spec.require_paths = ['lib']
27
+
28
+ spec.add_dependency 'base64', '~> 0.2'
29
+ spec.add_dependency 'logger', '~> 1.6'
30
+ end