Vitals is your one stop shop for metrics in Ruby and Ruby Web and API frameworks. It currently support Rails, Rack (Sinatra and any Rack-supported frameworks), and Grape.
Add this line to your application's Gemfile:
gem'vitals'And then execute:
$ bundle
Or install it yourself as:
$ gem install vitals
Make an initializers/vitals.rb initializer, and configure Vitals as you'd like:
require'vitals'Vitals.configure!do |c|
c.facility='my_service'c.reporter=Vitals::Reporters::StatsdReporter.new(host: 'statsd-host',port: 8125)end## Rails#require'vitals/integrations/notifications/action_controller'Vitals::Integrations::Notifications::ActionController.subscribe!# if you also want ActiveJob metricsrequire'vitals/integrations/notifications/action_job'Vitals::Integrations::Notifications::ActiveJob.subscribe!## Grape#require'vitals/integrations/notifications/grape'Vitals::Integrations::Notifications::Grape.subscribe!You can shortcircuit the notifications configuration by using subscribe! right after configuring:
require'vitals'Vitals.configure!do |c|
c.facility='my_service'c.reporter=Vitals::Reporters::StatsdReporter.new(host: 'statsd-host',port: 8125)end# Subscribe to Rails' controllers, background jobs, and grape's API controllersVitals.subscribe!(:action_controller,:active_job,:grape)You can use the Requests middleware for pure Rack apps or Sinatra, Rails, and Grape instead of, or
in addition to, using the notification based instrumentation. Here is a sample Sinatra app:
require'vitals'require'vitals/integrations/rack/requests'classSinatraTestAPI < Sinatra::BaseuseVitals::Integrations::Rack::Requestsget'/foo/bar/baz'dosleep0.1"hello get"endpost'/foo/bar/:name'dosleep0.1"hello post"endendYou can emit metrics from anywhere:
Vitals.inc('my_metric')Vitals.count('my_metric',17)Vitals.gauge('my_metric',42)Vitals.timing('my_metric',500)# millisecondsVitals.time('my_metric'){# so something slow}# Use a dot to logically separate segmentsVitals.timing('category.my_metric',500)# millisecondsThe Vitals API is extensible. It should resemble the standard Logger look and feel,
and it revolves around 3 concepts:
Reporter- the thing that takes your metrics and flushes them to a metrics agent. UseStatsdReporterin production andConsoleReporterin development.ConsoleReporterwill spit out metrics tostdoutas they come. You can also wire them both withMultiReporter. Check the specs for how to do that.Format- takes the contextual information (host, service, environment) and your metric, and formats them in an order that makes sense for working with Graphite. You have theProductionFormat,HostLastFormatandNoHostFormat.Integrations- integrations hook things that we're able to instrument with Vitals. Check integrations for more.
Here's what's available to you at configuration time:
Vitals.configure!do |c|
# Set your service name (default: 'default')c.facility='my_service'# Set environment (default: taken from RACK_ENV)# c.environment = 'env'# Set a host (default: taken from hostname)# c.host = 'foohost'# Use a specific reporter (default: InmemReporter)# c.reporter = Vitals::Reporters::ConsoleReporter.new# Use a different format perhaps? (default: ProductionFormat)# c.format = Vitals::Formats::HostLastFormat# Use a different metric path separator, control how hierarcies are generated (default: '.')# c.path_sep = '__'endIf you leave the default metric path separator, it will be a dot. This means Graphite will parse this and generate a branch in the tree when ever it sees a new segment, so:
requests.api.status.registration.get.200.host-123
Will be created from a GET /api/status/registration
On the other hand, if you choose a non-dot separator, like underscore, then:
requests.api_status_registration.get.200.host-123
Will be generated from a GET /api/status/registration.
You can pick either of those and the trade-offs are:
Nested hierarchy (using a dot): fine-grained control over grouping your metrics efficiently. If you want to pick and choose a metric, and be able to group based on topics efficiently. You cannot group cross-segments of a path in graphite.
Flat hierarchy (using anything other than a dot, like an underscore): grouping over segments can be glob-like, so quick wins like "graph all errors" can be had like this:
api.*.500.*. However, every time you want to group metrics, you will need to find the appropriate glob pattern, which will taxi Graphite for a huge amounts of metrics.
The default separator is a dot, which makes everything hierarchical.
Tests and benchmarks should be run with at least Ruby 2.1 (because of memory profiling API)
$ bundle install && rake spec && rake bench
You can use the following to test various web frameworks using their own integration testing stacks:
$ rake multiverse
Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :).
Copyright (c) 2011-2016 Dotan Nahum@jondot. See LICENSE for further details.