Time-series metrics for Ruby. Track anything (signups, revenue, job durations) using the database you already have. No InfluxDB. No TimescaleDB. Just one call and your existing Postgres, Redis, MongoDB, MySQL, or SQLite.
Part of the Trifle ecosystem. Also available in Elixir and Go.
- No new infrastructure. Uses your existing database. No dedicated time-series DB to deploy, maintain, or pay for.
- One call, many dimensions. Track nested breakdowns (revenue by country by channel) in a single
trackcall. Automatic rollup across dynamic time granularities (1m,6h,1d, etc.). - Library-first. Start with the gem. Add Trifle App dashboards, Trifle CLI terminal access, or AI agent integration via MCP when you need them.
gem 'trifle-stats'Trifle::Stats.configure do |config|
config.driver = Trifle::Stats::Driver::Postgres.new(ActiveRecord::Base.connection)
config.granularities = ['1h', '1d', '1w', '1mo']
endTrifle::Stats.track(
key: 'orders',
at: Time.now,
values: {
count: 1,
revenue: 49_90,
revenue_by_country: { us: 49_90 },
revenue_by_channel: { organic: 49_90 }
}
)Trifle::Stats.values(
key: 'orders',
from: 1.week.ago,
to: Time.now,
granularity: :day
)
#=> { at: [Mon, Tue, Wed, ...], values: [{ "count" => 12, "revenue" => 598_80, ... }, ...] }| Driver | Backend | Best for |
|---|---|---|
| Postgres | JSONB upsert | Most production apps |
| Redis | Hash increment | High-throughput counters |
| MongoDB | Document upsert | Document-oriented stacks |
| MySQL | JSON column | MySQL shops |
| SQLite | JSON1 extension | Single-server apps, dev/test |
| Process | In-memory | Testing |
| Dummy | No-op | Disabled analytics |
- Dynamic time granularities. Use any interval like
1m,10m,1h,6h,1d,1w,1mo,1q,1y. - Nested value hierarchies. Track dimensional breakdowns in a single call.
- Series operations. Aggregators (sum, avg, min, max), transponders, formatters.
- Buffered writes. Queue metrics in-memory before flushing to reduce write load.
- Driver flexibility. Switch backends without changing application code.
Every track/assert/assort call is buffered by default. The buffer flushes on an interval, when the queue reaches a configurable size, and on shutdown (SIGTERM/at_exit).
Trifle::Stats.configure do |config|
config.driver = Trifle::Stats::Driver::Redis.new(Redis.new)
config.buffer_duration = 5 # flush every ~5 seconds
config.buffer_size = 100 # ...or sooner when 100 actions are enqueued
config.buffer_aggregate = true
endSet buffer_enabled = false for synchronous write-through.
Full guides, API reference, and examples at docs.trifle.io/trifle-stats-rb
Trifle::Stats is the tracking layer. The ecosystem grows with you:
| Component | What it does |
|---|---|
| Trifle App | Dashboards, alerts, scheduled reports, AI-powered chat. Cloud or self-hosted. |
| Trifle CLI | Query and push metrics from the terminal. MCP server mode for AI agents. |
| Trifle::Stats (Elixir) | Elixir implementation with the same API and storage format. |
| Trifle Stats (Go) | Go implementation with the same API and storage format. |
| Trifle::Traces | Structured execution tracing for background jobs. |
| Trifle::Logs | File-based log storage with ripgrep-powered search. |
| Trifle::Docs | Map a folder of Markdown files to documentation URLs. |
Bug reports and pull requests are welcome on GitHub at https://github.com/trifle-io/trifle-stats.
The gem is available as open source under the terms of the MIT License.