allstak
AllStak SDK for Ruby, Rails, Rack, and Sidekiq. Captures exceptions, logs, inbound and outbound HTTP requests, ActiveRecord queries, Sidekiq job failures, spans, and cron heartbeats. Rails apps are auto-instrumented via a Railtie; Sidekiq via a server middleware.
Install
gem install allstak
Or add it to your Gemfile:
gem "allstak"
Setup
require "allstak"
AllStak.configure do |config|
config.api_key = ENV["ALLSTAK_API_KEY"]
config.environment = ENV.fetch("APP_ENV", "production")
config.release = ENV["ALLSTAK_RELEASE"]
config.service_name = "checkout-api"
end
AllStak.capture_exception(StandardError.new("checkout failed"))
AllStak.log.info("payment retry", metadata: { order_id: "ord_123" })
Rails
For Rails apps there is no manual wiring. Requiring the gem loads a
Railtie that auto-inserts the AllStak Rack middleware into your application's
middleware stack during boot. Just configure the SDK during app initialization
(e.g. in config/initializers/allstak.rb):
require "allstak"
AllStak.configure do |config|
config.api_key = ENV["ALLSTAK_API_KEY"]
config.environment = Rails.env
config.service_name = "checkout-api"
end
You then get inbound request telemetry, trace propagation, unhandled-exception
capture, ActiveRecord query instrumentation, and outbound Net::HTTP capture
automatically. The middleware insertion is idempotent.
Rack (non-Rails)
For plain Rack apps (Sinatra, Roda, etc.), add the middleware yourself:
use AllStak::Integrations::Rack::Middleware
Sidekiq
When Sidekiq is present, AllStak.configure registers a Sidekiq server
middleware automatically — no manual setup. It wraps each job in a span and
breadcrumb, and captures job failures with worker class, jid, queue, and
(PII-sanitized) args as context, then re-raises so Sidekiq's retry machinery
still runs. Jobs that exhaust their retries are also captured via a death
handler. When Sidekiq is not installed, this is a graceful no-op.
Spans
AllStak.tracing.in_span("checkout.authorize") do
end
Breadcrumbs
Breadcrumbs are collected automatically — no per-call code. After
AllStak.configure, the SDK records a trail of recent events on a 50-entry
per-thread ring buffer and attaches it to the next captured exception on
that thread. Auto breadcrumbs come from:
- inbound Rack requests (method, path, status, duration),
- outbound
Net::HTTPcalls (method, host, path, status, duration), - ActiveRecord queries (truncated SQL, duration, status),
- Sidekiq job processing,
- and every
AllStak.log.*call.
Because the buffer is per-thread, one request's trail never bleeds into a concurrent request's exception. You can also add your own:
AllStak.(type: "auth", message: "password reset requested",
data: { "userId" => current_user.id })
Disable automatic collection (manual add_breadcrumb still works) with
enable_auto_breadcrumbs = false or ALLSTAK_AUTO_BREADCRUMBS=0.
Structured logs (optional)
Ship your application logs to AllStak by composing the optional log adapter with your existing logger — existing log destinations are preserved:
# Rails 7.1+ (broadcast alongside the current logger):
AllStak::Integrations::Logger.attach_to_rails!
# Any Ruby logger:
logger = AllStak::Integrations::Logger.broadcast(logger)
Once attached, logger.info / .warn / .error ship to /ingest/v1/logs
automatically. Records at ERROR/FATAL are additionally promoted to error
entries so they surface in the Errors list. Disable promotion with
AllStak::Integrations::Logger.new(error_promotion: false), or change the
threshold with error_promotion_level:. The adapter is opt-in and fail-open —
it never raises into your logging path.
Configuration
| Option | Description |
|---|---|
api_key |
Project API key. |
environment |
Deployment environment. |
release |
App version or commit SHA. |
service_name |
Logical service name. |
flush_interval_ms |
Background flush interval. |
buffer_size |
Max buffered events. |
enable_auto_breadcrumbs |
Collect breadcrumbs automatically from the Rack/Net::HTTP/ActiveRecord/Sidekiq instrumentation and the AllStak.log.* bridge (default true; env ALLSTAK_AUTO_BREADCRUMBS=0 to disable). Manual AllStak.add_breadcrumb is unaffected. |
install_at_exit_handler |
Install a process-wide at_exit hook that captures the exception terminating the process as an unhandled event (default true). |
before_send |
Callable invoked with the event hash just before transport. Return a modified hash, or nil to drop the event. Fails open (sends the original) if it raises. |
sample_rate |
Float in [0.0, 1.0] head-sampling rate for error/message events (default 1.0 = keep all). |
traces_sample_rate |
Float in [0.0, 1.0] span sampling rate. nil (default) keeps every span and the traceparent sampled flag; when set, span creation is sampled and the propagated traceparent flag reflects the decision. |
For top-level uncaught exceptions outside Rack (workers, threads, rake tasks), the at_exit handler catches genuine unhandled terminations automatically. You can also report manually at a boundary:
begin
run_worker
rescue => e
AllStak.capture_unhandled(e) # mechanism=at_exit, handled=false
raise
end
Privacy
The SDK redacts common sensitive headers and fields. Avoid putting secrets in custom metadata.
Troubleshooting
- No events: confirm
ALLSTAK_API_KEYis available before configuration. - Missing request telemetry (Rails): confirm
require "allstak"runs at boot so the Railtie can auto-insert the middleware. - Missing request telemetry (plain Rack): confirm
use AllStak::Integrations::Rack::Middlewareis in your Rack stack. - Short-lived job: call
AllStak.flushbefore exit when possible.
Contributing and Support
- Report bugs with the GitHub bug report template: https://github.com/AllStak/allstak-ruby/issues/new/choose
- Open pull requests using the checklist in CONTRIBUTING.md.
- Report security vulnerabilities privately through SECURITY.md.
License
MIT