|
| 1 | +# sentry-yabeda |
| 2 | + |
| 3 | +A [Yabeda](https://github.com/yabeda-rb/yabeda) adapter that forwards Ruby application metrics to [Sentry](https://sentry.io). |
| 4 | + |
| 5 | +## Installation |
| 6 | + |
| 7 | +Add this line to your application's Gemfile: |
| 8 | + |
| 9 | +```ruby |
| 10 | +gem "sentry-yabeda" |
| 11 | +``` |
| 12 | + |
| 13 | +## Usage |
| 14 | + |
| 15 | +Require `sentry-yabeda` in your application. If you're using Bundler (most cases), simply adding it to your Gemfile is enough. |
| 16 | + |
| 17 | +```ruby |
| 18 | +# config/initializers/sentry.rb |
| 19 | +Sentry.init do |config| |
| 20 | + config.dsn = ENV["SENTRY_DSN"] |
| 21 | + config.enable_metrics = true |
| 22 | +end |
| 23 | + |
| 24 | +# config/initializers/yabeda.rb (or wherever Yabeda is configured) |
| 25 | +require "sentry-yabeda" |
| 26 | +``` |
| 27 | + |
| 28 | +That's it! All Yabeda metrics will automatically flow to Sentry. |
| 29 | + |
| 30 | +### Periodic Gauge Collection |
| 31 | + |
| 32 | +Many Yabeda plugins (puma, gc, gvl\_metrics) measure process-level state using **gauge metrics** with `collect` blocks. These blocks are designed for Prometheus's pull model. A scrape request triggers `Yabeda.collect!`, which reads the current state and sets gauge values. |
| 33 | + |
| 34 | +In a push-based system like Sentry, there's no scrape request. `sentry-yabeda` solves this with a built-in **periodic collector** that calls `Yabeda.collect!` on a background thread: |
| 35 | + |
| 36 | +```ruby |
| 37 | +require "sentry-yabeda" |
| 38 | + |
| 39 | +# Start the collector (default: every 15 seconds) |
| 40 | +Sentry::Yabeda.start_collector! |
| 41 | + |
| 42 | +# Or with a custom interval |
| 43 | +Sentry::Yabeda.start_collector!(interval: 30) |
| 44 | + |
| 45 | +# Stop the collector |
| 46 | +Sentry::Yabeda.stop_collector! |
| 47 | +``` |
| 48 | + |
| 49 | +Without starting the collector, only **event-driven metrics** (counters incremented on each request, histograms measured per-operation) will flow to Sentry. Gauges that depend on periodic collection (e.g. GC stats, GVL contention, and Puma thread pool utilization) require the collector. |
| 50 | + |
| 51 | +** How it works ** |
| 52 | + |
| 53 | +Every 15s (or set interval) |
| 54 | +1. Collector calls Yabeda.collect! |
| 55 | +2. Plugin collect blocks fire (read GC.stat, fetch Puma /stats, etc.) |
| 56 | +3. gauge.set(value) calls flow through the adapter |
| 57 | +4. Sentry.metrics.gauge(name, value, attributes: tags) |
| 58 | +5. Sentry buffers and sends in the next envelope flush |
| 59 | + |
| 60 | +### Metric Type Mapping |
| 61 | + |
| 62 | +| Yabeda Type | Sentry Type | |
| 63 | +|-------------|-------------| |
| 64 | +| Counter | `Sentry.metrics.count` | |
| 65 | +| Gauge | `Sentry.metrics.gauge` | |
| 66 | +| Histogram | `Sentry.metrics.distribution` | |
| 67 | +| Summary | `Sentry.metrics.distribution` | |
| 68 | + |
| 69 | +### Tags |
| 70 | + |
| 71 | +Yabeda tags are passed directly as Sentry metric attributes, enabling filtering and grouping in the Sentry UI. |
| 72 | + |
| 73 | +### Metric Naming |
| 74 | + |
| 75 | +Metrics are named using the pattern `{group}.{name}` (e.g., `rails.request_duration`). Metrics without a group use just the name. |
| 76 | + |
| 77 | +### Trace Integration |
| 78 | + |
| 79 | +Since Sentry metrics carry trace context automatically, metrics emitted via the adapter are connected to active traces when `sentry-rails` or other Sentry integrations are active. This enables pivoting from metric spikes to relevant traces in the Sentry UI. |
0 commit comments