Chronos Ruby
Chronos Ruby is the framework-independent client for sending Ruby application errors to Chronos. Version 0.3 adds bounded resilience to the privacy-focused legacy foundation: manual exceptions are sanitized before queueing, retried under a finite policy, retained in a fixed-size memory backlog during outages, and controlled by a restricted remote policy.
What the gem collects
For each exception, version 0.3 can collect:
- exception class, message, structured backtrace, and chained causes;
- timestamp, severity, tags, and an optional fingerprint;
- application-supplied context, parameters, session, and user fields;
- Ruby version, engine, platform, process ID, opaque thread ID, and hostname;
- application version, environment, and service name.
See Data collected for the complete field table.
What is not collected by default
Chronos Ruby does not inspect environment variables, request bodies, cookies, HTTP headers, source code, database contents, or installed gems. Application-supplied fields are recursively sanitized, but applications should still avoid sending unnecessary personal, health, financial, or authentication data.
Supported Ruby and Rails versions
Version 0.x targets Ruby 2.2.10 through Ruby 2.6. Version 0.3 is independent of Rails and does not yet declare support for any Rails integration. All supported combinations must pass dedicated CI before being listed as supported.
See Compatibility.
Plain Ruby installation
The current public build is a pre-release. Add its exact version to the application's Gemfile:
gem "chronos-ruby", "0.3.0.pre.1"
Install with a Bundler version compatible with the application. For the oldest supported runtime:
gem install bundler -v 1.17.3
bundle _1.17.3_ install
Without Bundler:
gem install chronos-ruby --pre
Rails installation
Rails automatic integration is not part of version 0.3. A Rails application may use the plain Ruby API, but this does not constitute declared Rails support. Rack and Rails adapters are planned for later legacy releases.
Minimum configuration
project_id, project_key, and an HTTPS host are required while the agent is enabled:
require "chronos"
Chronos.configure do |config|
config.project_id = ENV["CHRONOS_PROJECT_ID"]
config.project_key = ENV["CHRONOS_PROJECT_KEY"]
config.host = "https://chronos.example.com"
config.environment = ENV["APP_ENV"] || "production"
config.service_name = "billing"
config.app_version = ENV["APP_VERSION"]
end
HTTPS verification is enabled by default. HTTP requires explicitly setting ssl_verify = false and should only be used with a local test server.
Automatic capture
Automatic exception capture is not implemented in version 0.3. Applications must call Chronos.notify or Chronos.notify_sync. Rack, Rails, and worker hooks will be introduced only after their compatibility suites exist.
Manual capture
Asynchronous capture is recommended for application code:
begin
perform_payment
rescue StandardError => error
Chronos.notify(error, :tags => ["payment"])
raise
end
Synchronous capture waits for the HTTP result and is useful in scripts or controlled shutdown paths:
delivered = Chronos.notify_sync(RuntimeError.new("import failed"))
Both methods return false instead of allowing an internal agent error to escape.
User context
User data is opt-in and must contain only values your application is allowed to send:
Chronos.notify(error, :user => {"id" => "customer-42", "role" => "operator"})
Version 0.3 sanitizes this context before delivery and before it can enter retry storage. Data minimization remains the application's responsibility.
Breadcrumbs
Breadcrumbs are not implemented in version 0.3.
Filters and LGPD
Version 0.3 recursively redacts sensitive keys and detects Bearer tokens, JWTs, e-mail addresses, CPF, CNPJ, and valid payment-card candidates in free text. IPv4 addresses are anonymized by default. Applications can add blocklist matchers, hash selected identifiers, or install custom filters:
Chronos.configure do |config|
# required options omitted
config.blocklist_keys += [:medical_record, /bank_account/i]
config.hash_keys += [:customer_id]
config.filters << proc { |key, value| key.to_s == "internal_reference" ? "[REMOVED]" : value }
end
Sanitization runs before queueing and transport. See Privacy and LGPD for behavior, limitations, health and financial examples, and a payload audit procedure.
Ignore rules
Entire environments can be ignored:
Chronos.configure do |config|
# required options omitted
config.ignored_environments = ["development", "test"]
end
Local exception-specific ignore callbacks are not available in version 0.3. The server may provide a bounded list of exact fingerprints to ignore; it cannot provide regular expressions or executable rules.
Performance monitoring
Request, SQL, cache, job, and external HTTP monitoring are not implemented in version 0.3. The local capture pipeline is bounded and HTTP delivery runs outside the caller thread when Chronos.notify is used.
Sidekiq and Active Job
Sidekiq and Active Job integrations are not implemented in version 0.3. Calling the manual API from a job is possible, but automatic capture and deduplication are not yet guaranteed.
Deploy tracking
Deploy notifications are not implemented in version 0.3. app_version may be included in exception events for release correlation.
Asynchronous queue
The queue has a fixed capacity and drops the newest event when full. Worker threads are created lazily after the first accepted event. The default capacity is 100 events with one worker.
flowchart LR
E[Exception] --> N[Notice builder]
N --> P[Privacy sanitizer]
P --> S[Safe bounded serializer]
S --> D[Delivery pipeline]
D --> Q[Bounded queue]
Q --> W[Fixed worker pool]
W --> R[Retry and circuit breaker]
R --> H[Net::HTTP transport]
R --> B[Bounded memory backlog]
Use Chronos.flush(timeout) to wait for accepted events and Chronos.close(timeout) during shutdown. Workers are recreated after a process fork.
Retry and backlog
Version 0.3 retries network errors, HTTP 408, 429, and 5xx responses with exponential backoff, bounded jitter, and a finite attempt count. Other 4xx responses are permanent and are not retried. A circuit breaker pauses requests after repeated failures, preventing retry storms.
After retries are exhausted, the already sanitized SerializedEvent may enter a fixed-capacity memory backlog. The backlog drops new items when full, is lost when the process exits, and never writes to disk. A later successful half-open probe drains backlog items as new events arrive.
The SaaS may return a JSON policy in the bounded X-Chronos-Remote-Configuration response header. Only sampling rate, enabled event types, a lower payload limit, exact ignored fingerprints, send interval, and kill switch are accepted. Remote values cannot change the host, project credentials, TLS, local maximums, code, or regular expressions. See Retry and backlog and Remote configuration.
How it works internally
The code follows hexagonal boundaries:
Chronos::Corecontains immutable notices, sanitization, and safe normalization;Chronos::Applicationcoordinates capture;Chronos::Application::DeliveryPipelineowns bounded retry and remote policy;Chronos::Portsdefines delivery behavior;Chronos::Adaptersimplements Net::HTTP delivery;Chronos::Internalowns bounded queueing, workers, and defensive logging.
The core has no dependency on Rails, Rack, Sidekiq, or ActiveSupport. See Architecture.
Environment-specific configuration
Configuration values are explicit; the gem never scans the process environment. Read only the variables your application chooses:
Chronos.configure do |config|
config.project_id = ENV["CHRONOS_PROJECT_ID"]
config.project_key = ENV["CHRONOS_PROJECT_KEY"]
config.host = ENV["CHRONOS_HOST"]
config.environment = ENV["APP_ENV"] || "production"
config.enabled = ENV["CHRONOS_ENABLED"] != "false"
config.queue_size = 100
config.workers = 1
config.timeout = 5.0
config.open_timeout = 2.0
config.max_retries = 3
config.retry_base_interval = 0.5
config.retry_max_interval = 30.0
config.retry_jitter = 0.25
config.backlog_size = 100
config.circuit_failure_threshold = 5
config.circuit_reset_timeout = 30.0
config.remote_configuration = true
end
All options are documented in Configuration.
Troubleshooting
Configuration errors are raised during Chronos.configure. Capture and delivery errors are contained and optionally reported to the configured logger. Verify credentials, HTTPS certificates, timeouts, and Chronos.flush results. See Troubleshooting.
Benchmark
Run the version 0.3 benchmarks with:
bundle _1.17.3_ exec ruby benchmarks/capture_exception.rb
bundle _1.17.3_ exec ruby benchmarks/serialization.rb
bundle _1.17.3_ exec ruby benchmarks/filtering.rb
bundle _1.17.3_ exec ruby benchmarks/queue.rb
bundle _1.17.3_ exec ruby benchmarks/retry_backlog.rb
Results depend on runtime, hardware, and payload. No performance comparison is claimed until repeatable measurements are published.
Migration from Airbrake
An Airbrake migration guide will be added before the legacy 1.0 release. Version 0.3 does not claim API compatibility or automatic replacement.
Local development
Clone the repository, install Bundler 1.17.3, and run setup:
gem install bundler -v 1.17.3
bin/setup
Open an interactive console:
bin/console
Install the current source locally:
bundle _1.17.3_ exec rake install
Tests
Run the complete suite on the current Ruby:
bundle _1.17.3_ exec rake
The legacy CI matrix covers Ruby 2.2.10, 2.3.8, 2.4.10, 2.5.9, and 2.6.10. Network integration tests use a local fake HTTP server.
Contributing
Open an issue before introducing a new public API or dependency. Every public class requires YARD documentation, tests, module documentation, and compatibility evidence. See CONTRIBUTING.md.
Security
Never include credentials in event context or logs. Report vulnerabilities privately according to SECURITY.md. Ruby 2.2 through 2.6 are end-of-life; Chronos provides technical compatibility, not runtime security maintenance.
License
Chronos Ruby is distributed under the terms of the MIT License. See LICENSE.txt.