Project

metrixwire

0.0
The project is in a healthy, maintained state
Zero-config application performance monitoring for Ruby. Add the gem, set METRIXWIRE_KEY, and every request, database query, outbound HTTP call and cache op is instrumented automatically — no manual spans, no middleware to wire up. Detects N+1 queries, slow endpoints, slow queries and more. Non-blocking: traces are batched off the request path.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

metrixwire

Zero-config APM SDK for Ruby — Rails, Sinatra & bare Rack. In Rails it's fully automatic: add the gem and set METRIXWIRE_KEY. Elsewhere, call MetrixWire.init once. Every request, database query, outbound HTTP call and cache op is instrumented automatically. There is no manual span API and no middleware to wire up. Non-blocking: if the MetrixWire endpoint is down, your app keeps running normally.

Installation

# Gemfile
gem 'metrixwire', require: 'metrixwire'
bundle install

Usage

Rails — fully automatic

Add the gem, set the key, done. A Railtie auto-initializes from ENV, inserts the Rack middleware (one trace per request), and subscribes to ActiveSupport::Notifications — no code changes:

export METRIXWIRE_KEY=mw_...

Sinatra & bare Rack — automatic

Just require the gem and call init once, as early as possible:

require 'metrixwire'
MetrixWire.init(api_key: ENV['METRIXWIRE_KEY'])

The SDK patches Rack::Builder#to_app, so the tracing middleware is inserted for you — you never write use MetrixWire::Rack. Every HTTP request becomes a trace, and every query / HTTP call / cache op within it becomes a span.

How the automatic tracing works

Framework Traced automatically Notes
Rails Route refined to controller#action via ActiveSupport::Notifications. 5xx & exceptions captured.
Sinatra Route pattern (GET /users/:id) detected from sinatra.route. Zero wiring.
bare Rack Middleware auto-inserted via Rack::Builder#to_app.

The Rails path uses ActiveSupport::Notifications (the idiomatic, reliable route): sql.active_record for DB spans, process_action.action_controller for the route + errors, cache_*.active_support for cache spans, and transaction.active_record for transaction spans. Outside Rails, DB and HTTP are captured by patching the underlying drivers directly.

Automatically instrumented libraries

Library How
ActiveRecord (Rails) sql.active_record notifications (db_query + rowCount)
pg patches PG::Connection#exec/#exec_params/#async_exec (rowCount from the result; transaction spans from BEGIN…COMMIT)
mysql2 patches Mysql2::Client#query
sqlite3 patches SQLite3::Database#execute
Net::HTTP (and libs built on it) patches Net::HTTP#request (http_call span + statusCode)
redis / redis-client cache spans (hit/miss where known) for the slow-cache detector

Each patch is guarded: if the library or constant isn't present, it's skipped silently. The core has zero runtime gem dependencies (stdlib only).

init options

MetrixWire.init(
  api_key: 'mw_...',                        # required (falls back to METRIXWIRE_KEY)
  endpoint: 'http://localhost:3000/ingest',  # default (a base URL is accepted; /ingest is appended)
  flush_interval_ms: 5000,                   # how often batches are sent
  enabled: true,                             # set to false to disable entirely (or METRIXWIRE_ENABLED=false)
  timeout_ms: 3000,                          # send timeout (short, non-blocking)
  max_batch: 20,                             # flush immediately once this many are queued
  capture_source: true                       # capture the file:line a span originated from
)

All options fall back to environment variables when omitted: METRIXWIRE_KEY, METRIXWIRE_ENDPOINT, METRIXWIRE_ENABLED. With no API key the SDK runs in disabled mode instead of raising.

Non-blocking behavior

  • Traces are batched on a background daemon thread and sent off the request path with a short timeout.
  • All transport errors are swallowed — instrumentation never throws into or blocks your app.
  • A final flush runs on at_exit; you can also call MetrixWire.flush before a short-lived process exits.

Error boundary (escape hatch)

For frameworks the SDK can't hook automatically, attach an exception to the active trace — this is not a manual span API; requests/queries are still captured automatically:

begin
  do_work
rescue => e
  MetrixWire.capture_exception(e)
  raise
end