multimeter 1.0.0.pre2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/multimeter/version.rb +5 -0
- data/lib/multimeter.rb +563 -0
- metadata +70 -0
data/lib/multimeter.rb
ADDED
@@ -0,0 +1,563 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$: << File.expand_path('../../../jar-gems/slf4j-jars/lib', __FILE__)
|
4
|
+
$: << File.expand_path('../../../jar-gems/metrics-core-jars/lib', __FILE__)
|
5
|
+
|
6
|
+
require 'metrics-core-jars'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
|
10
|
+
module Yammer
|
11
|
+
module Metrics
|
12
|
+
import 'com.yammer.metrics.core.MetricsRegistry'
|
13
|
+
import 'com.yammer.metrics.core.MetricName'
|
14
|
+
import 'com.yammer.metrics.core.Meter'
|
15
|
+
import 'com.yammer.metrics.core.Counter'
|
16
|
+
import 'com.yammer.metrics.core.Histogram'
|
17
|
+
import 'com.yammer.metrics.core.Gauge'
|
18
|
+
import 'com.yammer.metrics.core.Timer'
|
19
|
+
import 'com.yammer.metrics.reporting.JmxReporter'
|
20
|
+
|
21
|
+
class Meter
|
22
|
+
def type
|
23
|
+
:meter
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
{
|
28
|
+
:type => :meter,
|
29
|
+
:event_type => event_type,
|
30
|
+
:count => count,
|
31
|
+
:mean_rate => mean_rate,
|
32
|
+
:one_minute_rate => one_minute_rate,
|
33
|
+
:five_minute_rate => five_minute_rate,
|
34
|
+
:fifteen_minute_rate => fifteen_minute_rate
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Counter
|
40
|
+
def type
|
41
|
+
:counter
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_h
|
45
|
+
{
|
46
|
+
:type => :counter,
|
47
|
+
:count => count
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Histogram
|
53
|
+
def type
|
54
|
+
:histogram
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_h
|
58
|
+
{
|
59
|
+
:type => :histogram,
|
60
|
+
:count => count,
|
61
|
+
:max => max,
|
62
|
+
:min => min,
|
63
|
+
:mean => mean,
|
64
|
+
:std_dev => std_dev,
|
65
|
+
:sum => sum
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Gauge
|
71
|
+
def type
|
72
|
+
:gauge
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_h
|
76
|
+
{
|
77
|
+
:type => :gauge,
|
78
|
+
:value => value
|
79
|
+
}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Timer
|
84
|
+
def type
|
85
|
+
:timer
|
86
|
+
end
|
87
|
+
|
88
|
+
def to_h
|
89
|
+
{
|
90
|
+
:type => :timer,
|
91
|
+
:event_type => event_type,
|
92
|
+
:count => count,
|
93
|
+
:mean_rate => mean_rate,
|
94
|
+
:one_minute_rate => one_minute_rate,
|
95
|
+
:five_minute_rate => five_minute_rate,
|
96
|
+
:fifteen_minute_rate => fifteen_minute_rate,
|
97
|
+
:max => max,
|
98
|
+
:min => min,
|
99
|
+
:mean => mean,
|
100
|
+
:std_dev => std_dev,
|
101
|
+
:sum => sum
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def measure
|
106
|
+
ctx = self.time
|
107
|
+
begin
|
108
|
+
yield
|
109
|
+
ensure
|
110
|
+
ctx.stop
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
module JavaConcurrency
|
118
|
+
import 'java.util.concurrent.TimeUnit'
|
119
|
+
import 'java.util.concurrent.ConcurrentHashMap'
|
120
|
+
import 'java.util.concurrent.atomic.AtomicReference'
|
121
|
+
import 'java.lang.Thread'
|
122
|
+
end
|
123
|
+
|
124
|
+
module Multimeter
|
125
|
+
def self.global_registry
|
126
|
+
GLOBAL_REGISTRY
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.registry(group, scope, instance_id=nil)
|
130
|
+
Registry.new(group, scope, instance_id)
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.metrics(group, scope, &block)
|
134
|
+
Class.new do
|
135
|
+
include(Metrics)
|
136
|
+
group(group)
|
137
|
+
scope(scope)
|
138
|
+
instance_eval(&block)
|
139
|
+
end.new
|
140
|
+
end
|
141
|
+
|
142
|
+
module Metrics
|
143
|
+
def self.included(m)
|
144
|
+
m.extend(Dsl)
|
145
|
+
end
|
146
|
+
|
147
|
+
def initialize(*args)
|
148
|
+
super
|
149
|
+
self.class.instance_gauges.each do |name, block|
|
150
|
+
instance_block = proc { instance_exec(&block) }
|
151
|
+
multimeter_registry.gauge(name, &instance_block)
|
152
|
+
end
|
153
|
+
self.class.instance_metrics.each do |type, name, options|
|
154
|
+
multimeter_registry.send(type, name, options)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def multimeter_registry
|
159
|
+
registry_mode = self.class.send(:registry_mode)
|
160
|
+
case registry_mode
|
161
|
+
when :instance, :linked_instance
|
162
|
+
@multimeter_registry ||= begin
|
163
|
+
package, _, class_name = self.class.name.rpartition('::')
|
164
|
+
group = self.class.send(:group) || package
|
165
|
+
scope = self.class.send(:scope) || class_name
|
166
|
+
if (iid_proc = self.class.send(:instance_id))
|
167
|
+
instance_id = instance_exec(&iid_proc)
|
168
|
+
else
|
169
|
+
instance_id = self.object_id
|
170
|
+
end
|
171
|
+
if registry_mode == :linked_instance
|
172
|
+
::Multimeter.global_registry.sub_registry(scope, instance_id)
|
173
|
+
else
|
174
|
+
::Multimeter.registry(group, scope, instance_id)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
when :global
|
178
|
+
::Multimeter.global_registry
|
179
|
+
else
|
180
|
+
self.class.multimeter_registry
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
module Dsl
|
185
|
+
def multimeter_registry
|
186
|
+
@multimeter_registry ||= begin
|
187
|
+
package, _, class_name = self.name.rpartition('::')
|
188
|
+
g = group || package
|
189
|
+
s = scope || class_name
|
190
|
+
case registry_mode
|
191
|
+
when :linked
|
192
|
+
::Multimeter.global_registry.sub_registry(s)
|
193
|
+
when :global
|
194
|
+
::Multimeter.global_registry
|
195
|
+
else
|
196
|
+
::Multimeter.registry(g, s)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def instance_gauges
|
202
|
+
@instance_gauges || []
|
203
|
+
end
|
204
|
+
|
205
|
+
def instance_metrics
|
206
|
+
@instance_metrics || []
|
207
|
+
end
|
208
|
+
|
209
|
+
private
|
210
|
+
|
211
|
+
def group(g=nil)
|
212
|
+
@multimeter_registry_group = g.to_s if g
|
213
|
+
@multimeter_registry_group
|
214
|
+
end
|
215
|
+
|
216
|
+
def scope(t=nil)
|
217
|
+
@multimeter_registry_scope = t.to_s if t
|
218
|
+
@multimeter_registry_scope
|
219
|
+
end
|
220
|
+
|
221
|
+
def instance_id(pr=nil, &block_pr)
|
222
|
+
pr ||= block_pr
|
223
|
+
@multimeter_registry_iid = pr if pr
|
224
|
+
@multimeter_registry_iid
|
225
|
+
end
|
226
|
+
|
227
|
+
def registry_mode(m=nil)
|
228
|
+
@multimeter_registry_mode = m if m
|
229
|
+
@multimeter_registry_mode
|
230
|
+
end
|
231
|
+
|
232
|
+
def add_instance_gauge(name, block)
|
233
|
+
@instance_gauges ||= []
|
234
|
+
@instance_gauges << [name, block]
|
235
|
+
end
|
236
|
+
|
237
|
+
def add_instance_metric(type, name, options)
|
238
|
+
@instance_metrics ||= []
|
239
|
+
@instance_metrics << [type, name, options]
|
240
|
+
end
|
241
|
+
|
242
|
+
%w[counter meter histogram timer].each do |t|
|
243
|
+
type = t.to_sym
|
244
|
+
define_method(type) do |name, options={}|
|
245
|
+
case registry_mode
|
246
|
+
when :instance, :linked_instance
|
247
|
+
add_instance_metric(type, name, options)
|
248
|
+
else
|
249
|
+
multimeter_registry.send(type, name, options)
|
250
|
+
end
|
251
|
+
define_method(name) do
|
252
|
+
multimeter_registry.get(name)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def gauge(name, &block)
|
258
|
+
case registry_mode
|
259
|
+
when :instance, :linked_instance
|
260
|
+
add_instance_gauge(name, block)
|
261
|
+
else
|
262
|
+
multimeter_registry.gauge(name, &block)
|
263
|
+
end
|
264
|
+
define_method(name) do
|
265
|
+
multimeter_registry.gauge(name)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
module InstanceMetrics
|
272
|
+
def self.included(m)
|
273
|
+
m.send(:include, Metrics)
|
274
|
+
m.send(:registry_mode, :instance)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
module GlobalMetrics
|
279
|
+
def self.included(m)
|
280
|
+
m.send(:include, Metrics)
|
281
|
+
m.send(:registry_mode, :global)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
module LinkedMetrics
|
286
|
+
def self.included(m)
|
287
|
+
m.send(:include, Metrics)
|
288
|
+
m.send(:registry_mode, :linked)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
module LinkedInstanceMetrics
|
293
|
+
def self.included(m)
|
294
|
+
m.send(:include, Metrics)
|
295
|
+
m.send(:registry_mode, :linked_instance)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
module Jmx
|
300
|
+
def jmx!
|
301
|
+
::Yammer::Metrics::JmxReporter.start_default(@registry)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
module Http
|
306
|
+
def http!(rack_handler, options={})
|
307
|
+
server_thread = JavaConcurrency::Thread.new do
|
308
|
+
rack_handler.run(create_app(self), options)
|
309
|
+
end
|
310
|
+
server_thread.daemon = true
|
311
|
+
server_thread.name = 'multimeter-http-server'
|
312
|
+
server_thread.start
|
313
|
+
end
|
314
|
+
|
315
|
+
private
|
316
|
+
|
317
|
+
class BadRequest < StandardError; end
|
318
|
+
|
319
|
+
JSON_HEADERS = {'Content-Type' => 'application/json'}.freeze
|
320
|
+
JSONP_HEADERS = {'Content-Type' => 'application/javascript'}.freeze
|
321
|
+
ERROR_HEADERS = {'Content-Type' => 'text/plain'}.freeze
|
322
|
+
|
323
|
+
def create_app(registry)
|
324
|
+
proc do |env|
|
325
|
+
begin
|
326
|
+
body = registry.to_h.to_json
|
327
|
+
headers = JSON_HEADERS
|
328
|
+
if (callback_name = env['QUERY_STRING'][/callback=([^$&]+)/, 1])
|
329
|
+
if callback_name =~ /^[\w\d]+$/
|
330
|
+
body = "#{callback_name}(#{body});"
|
331
|
+
headers = JSONP_HEADERS
|
332
|
+
else
|
333
|
+
raise BadRequest
|
334
|
+
end
|
335
|
+
end
|
336
|
+
[200, headers, [body]]
|
337
|
+
rescue BadRequest => e
|
338
|
+
[400, ERROR_HEADERS, ['Bad Request']]
|
339
|
+
rescue => e
|
340
|
+
[500, ERROR_HEADERS, ['Internal Server Error']]
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
class Registry
|
347
|
+
include Enumerable
|
348
|
+
include Jmx
|
349
|
+
include Http
|
350
|
+
|
351
|
+
attr_reader :group, :scope, :instance_id
|
352
|
+
|
353
|
+
def initialize(*args)
|
354
|
+
@group, @scope, @instance_id = args
|
355
|
+
@registry = ::Yammer::Metrics::MetricsRegistry.new
|
356
|
+
@sub_registries = JavaConcurrency::ConcurrentHashMap.new
|
357
|
+
end
|
358
|
+
|
359
|
+
def instance_registry?
|
360
|
+
!!@instance_id
|
361
|
+
end
|
362
|
+
|
363
|
+
def sub_registry(scope, instance_id=nil)
|
364
|
+
full_id = scope.dup
|
365
|
+
full_id << "/#{instance_id}" if instance_id
|
366
|
+
r = @sub_registries.get(full_id)
|
367
|
+
unless r
|
368
|
+
r = self.class.new(@group, scope, instance_id)
|
369
|
+
@sub_registries.put_if_absent(full_id, r)
|
370
|
+
r = @sub_registries.get(full_id)
|
371
|
+
end
|
372
|
+
r
|
373
|
+
end
|
374
|
+
|
375
|
+
def sub_registries
|
376
|
+
@sub_registries.values.to_a
|
377
|
+
end
|
378
|
+
|
379
|
+
def each_metric
|
380
|
+
return self unless block_given?
|
381
|
+
@registry.all_metrics.each do |metric_name, metric|
|
382
|
+
yield metric_name.name, metric
|
383
|
+
end
|
384
|
+
end
|
385
|
+
alias_method :each, :each_metric
|
386
|
+
|
387
|
+
def get(name)
|
388
|
+
@registry.all_metrics[create_name(name)]
|
389
|
+
end
|
390
|
+
|
391
|
+
def find_metric(name)
|
392
|
+
m = get(name)
|
393
|
+
unless m
|
394
|
+
sub_registries.each do |registry|
|
395
|
+
m = registry.find_metric(name)
|
396
|
+
break if m
|
397
|
+
end
|
398
|
+
end
|
399
|
+
m
|
400
|
+
end
|
401
|
+
|
402
|
+
def gauge(name, options={}, &block)
|
403
|
+
if get(name) && block_given?
|
404
|
+
raise ArgumentError, %(Cannot redeclare gauge #{name})
|
405
|
+
end
|
406
|
+
@registry.new_gauge(create_name(name), ProcGauge.new(block))
|
407
|
+
end
|
408
|
+
|
409
|
+
def counter(name, options={})
|
410
|
+
error_translation do
|
411
|
+
@registry.new_counter(create_name(name))
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
def meter(name, options={})
|
416
|
+
error_translation do
|
417
|
+
event_type = (options[:event_type] || '').to_s
|
418
|
+
time_unit = TIME_UNITS[options[:time_unit] || :seconds]
|
419
|
+
@registry.new_meter(create_name(name), event_type, time_unit)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
def histogram(name, options={})
|
424
|
+
error_translation do
|
425
|
+
@registry.new_histogram(create_name(name), !!options[:biased])
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
def timer(name, options={})
|
430
|
+
error_translation do
|
431
|
+
duration_unit = TIME_UNITS[options[:duration_unit] || :milliseconds]
|
432
|
+
rate_unit = TIME_UNITS[options[:rate_unit] || :seconds]
|
433
|
+
@registry.new_timer(create_name(name), duration_unit, rate_unit)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
def to_h
|
438
|
+
h = {@scope => {}}
|
439
|
+
each_metric do |metric_name, metric|
|
440
|
+
h[@scope][metric_name.to_sym] = metric.to_h
|
441
|
+
end
|
442
|
+
registries_by_scope = sub_registries.group_by { |r| r.scope }
|
443
|
+
registries_by_scope.each do |scope, registries|
|
444
|
+
if registries.size == 1
|
445
|
+
h.merge!(registries.first.to_h)
|
446
|
+
else
|
447
|
+
h[scope] = {}
|
448
|
+
registries_by_metric = Hash.new { |h, k| h[k] = [] }
|
449
|
+
registries.each do |registry|
|
450
|
+
registry.each_metric do |metric_name, _|
|
451
|
+
registries_by_metric[metric_name] << registry
|
452
|
+
end
|
453
|
+
end
|
454
|
+
registries_by_metric.each do |metric_name, registries|
|
455
|
+
if registries.size == 1
|
456
|
+
h[scope][metric_name.to_sym] = registries.first.get(metric_name).to_h
|
457
|
+
else
|
458
|
+
metrics_by_instance_id = Hash[registries.map { |r| [r.instance_id, r.get(metric_name)] }]
|
459
|
+
h[scope][metric_name.to_sym] = Aggregate.new(metrics_by_instance_id).to_h
|
460
|
+
end
|
461
|
+
end
|
462
|
+
end
|
463
|
+
h
|
464
|
+
end
|
465
|
+
h.delete_if { |k, v| v.empty? }
|
466
|
+
h
|
467
|
+
end
|
468
|
+
|
469
|
+
private
|
470
|
+
|
471
|
+
TIME_UNITS = {
|
472
|
+
:seconds => JavaConcurrency::TimeUnit::SECONDS,
|
473
|
+
:milliseconds => JavaConcurrency::TimeUnit::MILLISECONDS
|
474
|
+
}.freeze
|
475
|
+
|
476
|
+
def create_name(name)
|
477
|
+
::Yammer::Metrics::MetricName.new(@group, @scope, name.to_s)
|
478
|
+
end
|
479
|
+
|
480
|
+
def error_translation
|
481
|
+
begin
|
482
|
+
yield
|
483
|
+
rescue java.lang.ClassCastException => cce
|
484
|
+
raise ArgumentError, %(Cannot redeclare a metric as another type)
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
class Aggregate
|
490
|
+
def initialize(metrics)
|
491
|
+
@metrics = metrics
|
492
|
+
@type = check_type!
|
493
|
+
end
|
494
|
+
|
495
|
+
def to_h
|
496
|
+
{
|
497
|
+
:type => :aggregate,
|
498
|
+
:total => compute_total,
|
499
|
+
:parts => Hash[@metrics.map { |k, v| [k.to_s, v.to_h] }]
|
500
|
+
}
|
501
|
+
end
|
502
|
+
|
503
|
+
private
|
504
|
+
|
505
|
+
def check_type!
|
506
|
+
types = @metrics.values.map(&:type).uniq
|
507
|
+
unless types.size == 1
|
508
|
+
raise ArgumentError, %[All metrics of an aggregate must be of the same type (they were: #{types.join(', ')})]
|
509
|
+
end
|
510
|
+
types.first
|
511
|
+
end
|
512
|
+
|
513
|
+
COMPUTATIONS = {
|
514
|
+
:max => :max,
|
515
|
+
:min => :min,
|
516
|
+
:type => :first,
|
517
|
+
:event_type => :first,
|
518
|
+
:count => :sum,
|
519
|
+
:sum => :sum,
|
520
|
+
:mean => :avg,
|
521
|
+
:mean_rate => :avg,
|
522
|
+
:one_minute_rate => :avg,
|
523
|
+
:five_minute_rate => :avg,
|
524
|
+
:fifteen_minute_rate => :avg,
|
525
|
+
:std_dev => :avg,
|
526
|
+
:value => :avg
|
527
|
+
}.freeze
|
528
|
+
|
529
|
+
def compute_total
|
530
|
+
h = {}
|
531
|
+
metric_hs = @metrics.values.map(&:to_h)
|
532
|
+
metric_hs.first.keys.each do |property|
|
533
|
+
values = metric_hs.map { |h| h[property] }
|
534
|
+
aggregate_value = begin
|
535
|
+
case COMPUTATIONS[property]
|
536
|
+
when :first then values.first
|
537
|
+
when :max then values.max
|
538
|
+
when :min then values.min
|
539
|
+
when :sum then values.reduce(:+)
|
540
|
+
when :avg then values.reduce(:+)/values.size.to_f
|
541
|
+
else
|
542
|
+
raise "Don't know how to aggregate #{property}"
|
543
|
+
end
|
544
|
+
end
|
545
|
+
h[property] = aggregate_value
|
546
|
+
end
|
547
|
+
h
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
class ProcGauge < ::Yammer::Metrics::Gauge
|
552
|
+
def initialize(proc)
|
553
|
+
super()
|
554
|
+
@proc = proc
|
555
|
+
end
|
556
|
+
|
557
|
+
def value
|
558
|
+
@proc.call
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
GLOBAL_REGISTRY = registry('global', 'global')
|
563
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multimeter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: 6
|
5
|
+
version: 1.0.0.pre2
|
6
|
+
platform: java
|
7
|
+
authors:
|
8
|
+
- Theo Hultberg
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-11 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: metrics-core-jars
|
16
|
+
version_requirements: &2058 !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ! '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
none: false
|
22
|
+
requirement: *2058
|
23
|
+
prerelease: false
|
24
|
+
type: :runtime
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: json
|
27
|
+
version_requirements: &2076 !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ! '>='
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '0'
|
32
|
+
none: false
|
33
|
+
requirement: *2076
|
34
|
+
prerelease: false
|
35
|
+
type: :runtime
|
36
|
+
description: Multimeter provides a JRuby DSL for instrumenting your application. It uses Yammer's Metrics library under the hood.
|
37
|
+
email:
|
38
|
+
- theo@iconara.net
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- lib/multimeter.rb
|
44
|
+
- lib/multimeter/version.rb
|
45
|
+
homepage: http://github.com/iconara/multimeter
|
46
|
+
licenses: []
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
none: false
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>'
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.1
|
62
|
+
none: false
|
63
|
+
requirements: []
|
64
|
+
rubyforge_project: multimeter
|
65
|
+
rubygems_version: 1.8.15
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: JRuby application metric instrumentation using Yammer's Metrics
|
69
|
+
test_files: []
|
70
|
+
...
|