This is an experiment in making a threadsafe, low impact library to measure aspects of your ruby.
The library is very much a work-in-progress. It is being developed as I find needs while developing Papertrail.
The API is still in flux, but you can add this to your project by installing the gem.
To install, add this to your Gemfile
:
gem 'metriks'
and re-run bundle
.
Basic atomic counter. Used as an underlying metric for many of the other more advanced metrics.
Increment the counter. Without an argument it will increment by 1
.
counter = Metriks.counter('calls')
counter.increment
Decrement the counter. Without an argument it will decrement by 1
.
counter = Metriks.counter('calls')
counter.decrement
Return the current value of the counter.
counter = Metriks.counter('calls')
puts "counter: #{counter.count}"
A meter that measures the mean throughput and the one-, five-, and fifteen-minute exponentially-weighted moving average throughputs.
Record an event with the meter. Without an argument it will record one event.
meter = Metriks.meter('requests')
meter.mark
Returns the total number of events that have been recorded.
meter = Metriks.meter('requests')
puts "total: #{meter.count}"
Returns the one-minute average rate.
meter = Metriks.meter('requests')
puts "rate: #{meter.one_minute_rate}/sec"
Returns the five-minute average rate.
meter = Metriks.meter('requests')
puts "rate: #{meter.five_minute_rate}/sec"
Returns the fifteen-minute average rate.
meter = Metriks.meter('requests')
puts "rate: #{meter.fifteen_minute_rate}/sec"
Returns the mean (average) rate of the events since the start of the process.
meter = Metriks.meter('requests')
puts "rate: #{meter.mean_rate}/sec"
A timer that measures the average time as well as throughput metrics via a meter.
Records the duration of an operation. This normally wouldn't need to be
called — the #time
method is provided to simplify recording a duration.
timer = Metriks.timer('requests')
t0 = Time.now
work
timer.update(Time.now - t0)
Measure the amount of time a proc takes to execute. Takes either a block
or an object responding to #call
(normally a proc
or lambda
).
timer = Metriks.timer('requests')
timer.time do
work
end
If neither a block or an object is passed to the method, an object that
responds to #stop
will be returned. When #stop
is called, the time
will be recorded.
timer = Metriks.timer('requests')
t = timer.time
work
t.stop
Returns the number of measurements that have been made.
timer = Metriks.timer('requests')
puts "calls: #{timer.count}"
Returns the one-minute average rate.
meter = Metriks.timer('requests')
puts "rate: #{meter.one_minute_rate}/sec"
Returns the five-minute average rate.
meter = Metriks.timer('requests')
puts "rate: #{meter.five_minute_rate}/sec"
Returns the fifteen-minute average rate.
meter = Metriks.timer('requests')
puts "rate: #{meter.fifteen_minute_rate}/sec"
Returns the mean (average) rate of the events since the start of the process.
meter = Metriks.timer('requests')
puts "rate: #{meter.mean_rate}/sec"
Returns the minimum amount of time spent in the operation.
meter = Metriks.timer('requests')
puts "time: #{meter.min} seconds"
Returns the maximum time spent in the operation.
meter = Metriks.timer('requests')
puts "time: #{meter.max} seconds"
Returns the mean (average) time spent in the operation.
meter = Metriks.timer('requests')
puts "time: #{meter.mean} seconds"
Returns the standard deviation of the mean spent in the operation.
meter = Metriks.timer('requests')
puts "time: #{meter.stddev} seconds"
A specialized Timer
that calculates the percentage (between 0.0
and 1.0
) of
wall-clock time that was spent. It includes all of the methods of Timer
.
Returns the one-minute average utilization as a percentage between 0.0
and 1.0
.
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.one_minute_utilization * 100}%"
Returns the five-minute average utilization as a percentage between 0.0
and 1.0
.
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.five_minute_utilization * 100}%"
Returns the fifteen-minute average utilization as a percentage between 0.0
and 1.0
.
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.fifteen_minute_utilization * 100}%"
Returns the mean (average) utilization as a percentage between 0.0
and 1.0
since the process started.
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.mean_utilization * 100}%"
How to get metrics out of the process.
Sends metrics to Graphite every 60 seconds.
reporter = Metriks::Reporter::Graphite.new 'localhost', 3004
reporter.start
Send metrics to a logger every 60 seconds.
reporter = Metriks::Reporter::Logger.new(:logger => Logger.new('log/metrics.log'))
reporter.start
Send metrics to Librato Metrics every 60 seconds.
reporter = Metriks::Reporter::LibratoMetrics.new('email', 'token')
reporter.start
Provides a simple way to get up-to-date statistics from a process by updating the proctitle every 5 seconds (default).
reporter = Metriks::Reporter::ProcTitle.new :interval => 5
reporter.add 'reqs', 'sec' do
Metriks.meter('rack.requests').one_minute_rate
end
reporter.start
will display:
501 17015 26.0 1.9 416976 246956 ? Ss 18:54 11:43 thin reqs: 273.3/sec
Depending on how your application server operates, you may need to configure how reporters are created. Please look at Troubleshooting for more information.
An incomplete list of things I would like to see added:
- Rack middleware to measure utilization, throughput and worker time
- Basic reporters:
- Rack endpoint returning JSON
- Statsd reporter
- Metaprogramming instrumentation hooks like Shopify's statsd-instrument
Most of the inspiration for this project comes from Coda Hale's amazing Metrics, Metrics Everywhere talk at CodeConf and his sweet Metrics Java Library.
Copyright (c) 2012 Eric Lindvall
Published under the MIT License, see LICENSE