1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
|
# Metriks Client
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](https://papertrailapp.com/).
# Installing
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`:
``` ruby
gem 'metriks'
```
and re-run `bundle`.
# Metric API Overview
## Counters
Basic atomic counter. Used as an underlying metric for many of the other
more advanced metrics.
### increment(incr = 1)
Increment the counter. Without an argument it will increment by `1`.
``` ruby
counter = Metriks.counter('calls')
counter.increment
```
### decrement(decr = 1)
Decrement the counter. Without an argument it will decrement by `1`.
``` ruby
counter = Metriks.counter('calls')
counter.decrement
```
#### count()
Return the current value of the counter.
``` ruby
counter = Metriks.counter('calls')
puts "counter: #{counter.count}"
```
## Gauges
A gauge is an instantaneous measurement of a value.
It takes a callback to measure the value in form of a block or a callable
object.
**WARNING:** The code in the callback is executed every time the `#value`
method is called on the gauge. Most of the time this will be done by a
metriks reporter that is running in a separate thread.
``` ruby
# Callback as block
gauge = Metriks.gauge('queue.size') { queue.size }
# Callback as object responding to #call
callable = proc { queue.size }
gauge = Metriks.gauge('queue.size', callable)
```
### set(val)
Set the current value.
``` ruby
gauge = Metriks.gauge('queue_size')
gauge.set(queue.size)
```
### value()
Returns the value returned by the callback (if one is defined), returns the
value set via `#set` (or the default of 0) otherwise.
``` ruby
gauge = Metriks.gauge('queue_size')
puts "queue size: #{gauge.value}"
```
## Meters
A meter that measures the mean throughput and the one-, five-, and
fifteen-minute exponentially-weighted moving average throughputs.
### mark(val = 1)
Record an event with the meter. Without an argument it will record one event.
``` ruby
meter = Metriks.meter('requests')
meter.mark
```
### count()
Returns the total number of events that have been recorded.
``` ruby
meter = Metriks.meter('requests')
puts "total: #{meter.count}"
```
### one_minute_rate()
Returns the one-minute average rate.
``` ruby
meter = Metriks.meter('requests')
puts "rate: #{meter.one_minute_rate}/sec"
```
### five_minute_rate()
Returns the five-minute average rate.
``` ruby
meter = Metriks.meter('requests')
puts "rate: #{meter.five_minute_rate}/sec"
```
### fifteen_minute_rate()
Returns the fifteen-minute average rate.
``` ruby
meter = Metriks.meter('requests')
puts "rate: #{meter.fifteen_minute_rate}/sec"
```
### mean_rate()
Returns the mean (average) rate of the events since the start of the process.
``` ruby
meter = Metriks.meter('requests')
puts "rate: #{meter.mean_rate}/sec"
```
## Timers
A timer that measures the average time as well as throughput metrics via
a meter.
### update(duration)
Records the duration of an operation. This normally wouldn't need to be
called — the `#time` method is provided to simplify recording a duration.
``` ruby
timer = Metriks.timer('requests')
t0 = Time.now
work
timer.update(Time.now - t0)
```
### time(callable = nil, &block)
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`).
``` ruby
timer = Metriks.timer('requests')
work_result = 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.
``` ruby
timer = Metriks.timer('requests')
t = timer.time
work
t.stop
```
### count()
Returns the number of measurements that have been made.
``` ruby
timer = Metriks.timer('requests')
puts "calls: #{timer.count}"
```
### one_minute_rate()
Returns the one-minute average rate.
``` ruby
meter = Metriks.timer('requests')
puts "rate: #{meter.one_minute_rate}/sec"
```
### five_minute_rate()
Returns the five-minute average rate.
``` ruby
meter = Metriks.timer('requests')
puts "rate: #{meter.five_minute_rate}/sec"
```
### fifteen_minute_rate()
Returns the fifteen-minute average rate.
``` ruby
meter = Metriks.timer('requests')
puts "rate: #{meter.fifteen_minute_rate}/sec"
```
### mean_rate()
Returns the mean (average) rate of the events since the start of the process.
``` ruby
meter = Metriks.timer('requests')
puts "rate: #{meter.mean_rate}/sec"
```
### min()
Returns the minimum amount of time spent in the operation.
``` ruby
meter = Metriks.timer('requests')
puts "time: #{meter.min} seconds"
```
### max()
Returns the maximum time spent in the operation.
``` ruby
meter = Metriks.timer('requests')
puts "time: #{meter.max} seconds"
```
### mean()
Returns the mean (average) time spent in the operation.
``` ruby
meter = Metriks.timer('requests')
puts "time: #{meter.mean} seconds"
```
### stddev()
Returns the standard deviation of the mean spent in the operation.
``` ruby
meter = Metriks.timer('requests')
puts "time: #{meter.stddev} seconds"
```
## Utilization Timer
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`.
### one_minute_utilization()
Returns the one-minute average utilization as a percentage between `0.0` and `1.0`.
``` ruby
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.one_minute_utilization * 100}%"
```
### five_minute_utilization()
Returns the five-minute average utilization as a percentage between `0.0` and `1.0`.
``` ruby
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.five_minute_utilization * 100}%"
```
### fifteen_minute_utilization()
Returns the fifteen-minute average utilization as a percentage between `0.0` and `1.0`.
``` ruby
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.fifteen_minute_utilization * 100}%"
```
### mean_utilization()
Returns the mean (average) utilization as a percentage between `0.0` and `1.0`
since the process started.
``` ruby
meter = Metriks.utilization_timer('requests')
puts "utilization: #{meter.mean_utilization * 100}%"
```
# Reporter Overview
How to get metrics out of the process.
## Graphite Reporter
Sends metrics to Graphite every 60 seconds.
``` ruby
reporter = Metriks::Reporter::Graphite.new 'localhost', 3004
reporter.start
```
## Logger Reporter
Send metrics to a logger every 60 seconds.
``` ruby
reporter = Metriks::Reporter::Logger.new(:logger => Logger.new('log/metrics.log'))
reporter.start
```
## Librato Metrics Reporter
The Librato Metrics reporter has been moved to
[eric/metriks-librato_metrics](https://github.com/eric/metriks-librato_metrics).
## Proc Title Reporter
Provides a simple way to get up-to-date statistics from a process by
updating the proctitle every 5 seconds (default).
``` ruby
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
```
## Sematext Metrics Reporter
[metriks-sematext](https://github.com/sematext/metriks-sematext) gem provides reporter for sending metrics to [SPM](http://sematext.com/spm/index.html).
# Application Server Configuration
Depending on how your application server operates, you may need to configure how reporters are created. Please look at [Troubleshooting](https://github.com/eric/metriks/wiki/Troubleshooting) for more information.
# Plans
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](https://github.com/etsy/statsd) reporter
* Metaprogramming instrumentation hooks like [Shopify's statsd-instrument](https://github.com/Shopify/statsd-instrument)
# Credits
Most of the inspiration for this project comes from Coda Hale's amazing
[Metrics, Metrics Everywhere][metrics-talk] talk at CodeConf and his sweet
[Metrics][metrics] Java Library.
[metrics-talk]: http://pivotallabs.com/talks/139-metrics-metrics-everywhere
[metrics]: https://github.com/codahale/metrics
# License
Copyright (c) 2012 Eric Lindvall
Published under the MIT License, see LICENSE
|