0.0
The project is in a healthy, maintained state
A fiber-native Prometheus client for modern Ruby.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

>= 2.38
~> 0.95
~> 1.37
 Project Readme

fast-prometheus

A fiber-native Prometheus client for modern Ruby, built on the socketry/async ecosystem: HTTP middleware for Protocol::HTTP (Falcon-native) and Rack, safe to share one Registry across OS threads and fibers by default, native histograms as a first-class metric type, protobuf scrape exposition, and OTLP export over gRPC (async-grpc) and HTTP.

Not a fork of prometheus/client_ruby — a new gem that uses it as the reference for supported surface.

Installation

gem install fast-prometheus

Or add to your Gemfile:

gem "fast-prometheus"

require "fast/prometheus" loads only the core, with no IO dependencies. Protobuf exposition and OTLP export are built on fast-protowire rather than google-protobuf, so no native protobuf runtime is loaded either. The opt-in surfaces and what each pulls in are listed in the require-path reference.

Quickstart

require "fast/prometheus"
require "fast/prometheus/formats/text"

registry = Fast::Prometheus::Registry.new

requests = registry.counter(:http_requests_total, docstring: "Total HTTP requests", labels: %i[method path])
duration = registry.histogram(:request_duration_seconds, docstring: "Request duration", labels: [:method])

requests.increment(labels: { method: "GET", path: "/" })
requests.increment(by: 5, labels: { method: "POST", path: "/api" })
duration.observe(0.042, labels: { method: "GET" })
duration.observe(0.018, labels: { method: "GET" })

puts Fast::Prometheus::Formats::Text.render(registry.collect)

Run with bundle exec ruby -I lib from the repo root. For running this under Falcon and scraping it with a real Prometheus, see the Falcon tutorial.

Documentation

Tutorials

How-to guides

Reference

Explanation

  • Concurrency model — the locking contract and what it guarantees under threads and fibers.
  • Native histograms — what a native histogram is and why it's protobuf-only.
  • Design: why a new gem — why fast-prometheus exists instead of a client_ruby fork.
  • Benchmarks — scrape and observe benchmarks against prometheus-client and google-protobuf, and how to reproduce them.

Concurrency

A Registry is safe to share across every OS thread of a process, and remains safe across fibers within a thread — correct under Falcon --threaded --count N, where the N OS threads share one module-level Fast::Prometheus.registry. Falcon --forked mode gives each process its own registry, so a single scrape only sees the metrics of the process that handled it; aggregating across processes is out of scope. See the concurrency model for the full guarantee.

Performance

Single process, locked, thread-safe by default (benchmark-ips and allocation comparisons against prometheus-client and google-protobuf; see the benchmarks page for the full runs and conditions):

  • A protobuf scrape of 36,000 series renders in 24 objects, where the google-protobuf encoder needed 3.5 million Ruby objects and 504k native arenas, and in a hundredth of the GC time; taking the snapshot it reads is 1 ms and one Hash per metric
  • The text renderer allocates 66x fewer objects than prometheus-client's formatter for the same body, and renders it 3.1x faster at 36,000 series
  • Bound counter and gauge writes allocate nothing and are 1.45x faster than prometheus-client's; histogram observe is 2.9x faster and summary observe 3.1x
  • Native histogram observe runs at 1.2M i/s with no prometheus-client equivalent

Development

bundle exec sus
bundle exec rubocop
E2E_REQUIRED=1 ./integration/run
BENCH_QUICK=1 bundle exec ruby benchmark/observe.rb      # every metric operation vs prometheus-client
BENCH_QUICK=1 bundle exec ruby benchmark/exposition.rb   # the scrape suite

See how to verify a release build for the pre-release rule.