process_metrics 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +142 -0
- data/lib/process_metrics/base.rb +57 -0
- data/lib/process_metrics/config.rb +18 -0
- data/lib/process_metrics/persistence/logger.rb +9 -0
- data/lib/process_metrics/persistence.rb +1 -0
- data/lib/process_metrics/timer.rb +71 -0
- data/lib/process_metrics/version.rb +3 -0
- data/lib/process_metrics.rb +18 -0
- data/test/test_simple.rb +151 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 60c71413069134039aeacc1348863efe45184b24
|
4
|
+
data.tar.gz: ec20a17b8047721208c0ac6b3135f424b3df31f5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 638f0704e0ba772963b5f72f36773a46d8661750d232ddbc979afa5facbb34e0f29982da40ab7759971398da4052ca17267ff1c088f85ab688459074340e97e9
|
7
|
+
data.tar.gz: b10606a34d866cca1abaa4d78c94c4e156ce824f4f5735d54ebd2a645a00885f5b68902e00e62e86ed85900d02f2c34821206585d837108d7e93d2d2aa58127a
|
data/README.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
[![Code Climate](https://codeclimate.com/github/lucasuyezu/metric.png)](https://codeclimate.com/github/lucasuyezu/metric)
|
2
|
+
|
3
|
+
Process Metrics
|
4
|
+
===============
|
5
|
+
|
6
|
+
This project aims to collect metrics for processes.
|
7
|
+
|
8
|
+
It differs from other metric gems by measuring **processes** instead of code execution.
|
9
|
+
|
10
|
+
A process can begin in one point in time and finish in another thread, or even another server.
|
11
|
+
|
12
|
+
Features
|
13
|
+
========
|
14
|
+
|
15
|
+
- Sub-process: Start a process, track each individual step and see the global metric. This is similar to how web browsers show you in the Network view how much time each asset takes to load. See where the holes are.
|
16
|
+
- Unobtrusive: Failure in saving a metric will not break your code unless you use `Metric.measure!`, `Metric#find!` and `Metric#finish!`
|
17
|
+
- Assyncronous: Persistence is made in parallel, so measurement itself will not affect the results.
|
18
|
+
- Multiple data stores: ActiveRecord for now. Leela2 in the near future. Implement your own if you want/need.
|
19
|
+
|
20
|
+
Usage
|
21
|
+
=====
|
22
|
+
|
23
|
+
Manual
|
24
|
+
------
|
25
|
+
|
26
|
+
### Single process
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
ProcessMetrics.measure('name') do |metric|
|
30
|
+
do_work
|
31
|
+
metric.data = { key: 'value' } # optional
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
### Sub Process in the same block
|
36
|
+
```ruby
|
37
|
+
ProcessMetrics.measure('name') do |metric|
|
38
|
+
metric.measure('first sub process') do |sub_metric|
|
39
|
+
do_work
|
40
|
+
sub_metric.data = { key: 'value' } # optional
|
41
|
+
end
|
42
|
+
|
43
|
+
do_more_work
|
44
|
+
|
45
|
+
metric.measure('second sub process') do |sub_metric|
|
46
|
+
do_even_more_work
|
47
|
+
sub_metric.data = { key: 'value' } # optional
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
### Sub Processes in different places
|
53
|
+
```ruby
|
54
|
+
# in app/controller/my_controller.rb
|
55
|
+
metric = ProcessMetrics.new 'name' # metric objects have an uuid
|
56
|
+
save_metric(metric.uuid)
|
57
|
+
schedule_worker
|
58
|
+
|
59
|
+
# in lib/workers/my_worker.rb
|
60
|
+
ProcessMetrics.find(metric_uuid).measure('sub process') do |sub_metric|
|
61
|
+
do_work
|
62
|
+
submetric.data = { key: 'value' } # optional
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
Automatic
|
67
|
+
---------
|
68
|
+
|
69
|
+
### Single process
|
70
|
+
```ruby
|
71
|
+
class MyModel
|
72
|
+
include ProcessMetrics::Timer
|
73
|
+
measure :perform,
|
74
|
+
name: -> { "metric name" } # Default would be "MyModel#perform"
|
75
|
+
|
76
|
+
def perform
|
77
|
+
do_some_work
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
### Sub processes
|
83
|
+
```ruby
|
84
|
+
class MyWorker
|
85
|
+
include ProcessMetrics::Timer
|
86
|
+
measure :perform,
|
87
|
+
parent_metric_uuid: -> { "2d931510-d99f-494a-8c67-87feb05e1594" }
|
88
|
+
|
89
|
+
belongs_to :my_model
|
90
|
+
|
91
|
+
def perform
|
92
|
+
do_some_work
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
Persistence
|
98
|
+
===========
|
99
|
+
|
100
|
+
Data collected will be serialized into a json and persisted.
|
101
|
+
You can put any data you like into the data field and it will be serialized as well.
|
102
|
+
|
103
|
+
|
104
|
+
```json
|
105
|
+
{
|
106
|
+
"metrics": [{
|
107
|
+
"uuid": "bad85eb9-0713-4da7-8d36-07a8e4b00eab",
|
108
|
+
"name": "virtual_machine_provisioning",
|
109
|
+
"started_at": "2014-03-13T11:34:53-03:00",
|
110
|
+
"finished_at": "2014-03-13T11:35:14-03:00",
|
111
|
+
"data": {
|
112
|
+
"customer_login": "anon",
|
113
|
+
"provisioning_id": 6000123456,
|
114
|
+
"object_type": "virtual_machine",
|
115
|
+
"object_id": "cpro123456"
|
116
|
+
},
|
117
|
+
"links": {
|
118
|
+
"metrics": [
|
119
|
+
"2d931510-d99f-494a-8c67-87feb05e1594",
|
120
|
+
"62936e70-1815-439b-bf89-8492855a7e6b"
|
121
|
+
]
|
122
|
+
}
|
123
|
+
}]
|
124
|
+
}
|
125
|
+
```
|
126
|
+
|
127
|
+
Configuration
|
128
|
+
=============
|
129
|
+
|
130
|
+
One time, in a migration
|
131
|
+
------------------------
|
132
|
+
```ruby
|
133
|
+
ProcessMetrics::Persistence::ActiveRecord.setup!
|
134
|
+
```
|
135
|
+
|
136
|
+
Then, in an initializer
|
137
|
+
-----------------------
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
ProcessMetrics.logger = Rails.logger
|
141
|
+
ProcessMetrics.persistence = Metric::Persistence::ActiveRecord # Default is Logger
|
142
|
+
```
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module ProcessMetrics
|
4
|
+
class Base
|
5
|
+
attr_accessor :data, :uuid
|
6
|
+
|
7
|
+
def initialize(name, parent=nil)
|
8
|
+
@uuid = SecureRandom.uuid
|
9
|
+
@parent_uuid = parent ? parent.uuid : nil
|
10
|
+
@data = nil
|
11
|
+
@name = name
|
12
|
+
@started_at = Time.now
|
13
|
+
@finished_at = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes
|
17
|
+
{
|
18
|
+
uuid: @uuid,
|
19
|
+
parent_uuid: @parent_uuid,
|
20
|
+
name: @name,
|
21
|
+
data: @data,
|
22
|
+
started_at: @started_at,
|
23
|
+
finished_at: @finished_at
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialized_attributes
|
28
|
+
{
|
29
|
+
uuid: @uuid,
|
30
|
+
parent_uuid: @parent_uuid,
|
31
|
+
name: @name,
|
32
|
+
data: @data,
|
33
|
+
started_at: @started_at.strftime("%Y-%m-%d %H:%M:%S.%N"),
|
34
|
+
finished_at: @finished_at.strftime("%Y-%m-%d %H:%M:%S.%N")
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def save
|
39
|
+
@finished_at = Time.now
|
40
|
+
ProcessMetrics.config.persistence.save(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
def measure(name, &block)
|
44
|
+
work(name, self, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.work(name, parent=nil, &block)
|
48
|
+
metric = ProcessMetrics::Base.new name, parent
|
49
|
+
block.call metric
|
50
|
+
metric.save
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
self.class.name + " " + serialized_attributes.to_s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require 'logger'
|
3
|
+
require 'process_metrics/persistence'
|
4
|
+
|
5
|
+
module ProcessMetrics
|
6
|
+
class Config < Hashie::Mash
|
7
|
+
def initialize
|
8
|
+
self.logger = Logger.new("metric.log")
|
9
|
+
self.persistence = ProcessMetrics::Persistence::Logger
|
10
|
+
self.active_record = Hashie::Mash.new
|
11
|
+
self.active_record.table_name = 'metrics'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.config
|
16
|
+
Config.new
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'process_metrics/persistence/logger'
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module ClassMethods
|
2
|
+
@@replacing = false
|
3
|
+
|
4
|
+
def measure(*methods_names)
|
5
|
+
options = extract_options(methods_names)
|
6
|
+
|
7
|
+
methods_names.each do |method_name|
|
8
|
+
measure_method_name = :"measure_#{method_name}"
|
9
|
+
raw_method_name = :"raw_#{method_name}"
|
10
|
+
self.send(:define_method, measure_method_name) do |*args, &block|
|
11
|
+
parent_uuid = parent_uuid(options)
|
12
|
+
process_name = "#{self.class.name}##{method_name}"
|
13
|
+
parent = ProcessMetrics::Base.new(process_name)
|
14
|
+
parent.uuid = parent_uuid
|
15
|
+
|
16
|
+
ProcessMetrics.measure(process_name, parent) do |metric|
|
17
|
+
ProcessMetrics.logger.debug "About to send #{raw_method_name} with args #{args.inspect} and block #{block.inspect} to #{self}"
|
18
|
+
metric.data = {args: args, block: block}
|
19
|
+
|
20
|
+
send(raw_method_name, *args, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_added(method_name)
|
27
|
+
return if @@replacing || method_name =~ /^measure_/ || method_name =~ /^raw_/
|
28
|
+
ProcessMetrics.logger.debug "Adding method #{method_name} in #{self}"
|
29
|
+
|
30
|
+
measure_method_name = :"measure_#{method_name}"
|
31
|
+
raw_method_name = :"raw_#{method_name}"
|
32
|
+
|
33
|
+
if self.instance_methods.include? measure_method_name
|
34
|
+
ProcessMetrics.logger.debug "#{self}##{measure_method_name} exists. Replacing..."
|
35
|
+
@@replacing = true
|
36
|
+
alias_method raw_method_name, method_name
|
37
|
+
alias_method method_name, measure_method_name
|
38
|
+
@@replacing = false
|
39
|
+
else
|
40
|
+
ProcessMetrics.logger.debug "#{self}##{measure_method_name} does not exist. Exiting..."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def extract_options(array)
|
46
|
+
array.last && array.last.is_a?(Hash) ? array.pop : nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module ProcessMetrics
|
51
|
+
module Timer
|
52
|
+
def self.included(base)
|
53
|
+
base.extend ClassMethods
|
54
|
+
end
|
55
|
+
|
56
|
+
def parent_uuid(options)
|
57
|
+
return unless options
|
58
|
+
|
59
|
+
if options[:parent_uuid].respond_to?(:call)
|
60
|
+
# It's a proc. parent_uuid is the return value
|
61
|
+
options[:parent_uuid].call
|
62
|
+
elsif options[:parent_uuid].is_a?(Symbol)
|
63
|
+
# It's a symbol. Call method on object and parent_uuid is its result.
|
64
|
+
send(options[:parent_uuid])
|
65
|
+
else
|
66
|
+
# It's something static. Just call #to_s
|
67
|
+
options[:parent_uuid].to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'process_metrics/base'
|
2
|
+
require 'process_metrics/config'
|
3
|
+
require 'process_metrics/version'
|
4
|
+
require 'process_metrics/timer'
|
5
|
+
|
6
|
+
module ProcessMetrics
|
7
|
+
def self.logger
|
8
|
+
config.logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.logger=(logger)
|
12
|
+
config.logger = logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.measure(name, parent=nil, &block)
|
16
|
+
ProcessMetrics::Base.work(name, parent, &block)
|
17
|
+
end
|
18
|
+
end
|
data/test/test_simple.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
require 'process_metrics'
|
4
|
+
|
5
|
+
class MyClass
|
6
|
+
include ProcessMetrics::Timer
|
7
|
+
measure :do_simple_work,
|
8
|
+
:do_work_with_params,
|
9
|
+
:do_work_with_block,
|
10
|
+
:do_work_with_params_and_block
|
11
|
+
|
12
|
+
attr_accessor :my_var
|
13
|
+
|
14
|
+
def initialize(my_var)
|
15
|
+
@my_var = my_var
|
16
|
+
end
|
17
|
+
|
18
|
+
def do_simple_work
|
19
|
+
@my_var += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
def do_work_with_block(&block)
|
23
|
+
block.call(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def do_work_with_params(user_id)
|
27
|
+
@my_var += user_id + 3
|
28
|
+
end
|
29
|
+
|
30
|
+
def do_work_with_params_and_block(user_id, &block)
|
31
|
+
@my_var += user_id + 5
|
32
|
+
block.call self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class MyChildSymbolClass
|
38
|
+
include ProcessMetrics::Timer
|
39
|
+
measure :do_simple_work,
|
40
|
+
parent_uuid: :parent_object_uuid
|
41
|
+
|
42
|
+
attr_accessor :my_var
|
43
|
+
|
44
|
+
def initialize(my_var)
|
45
|
+
@my_var = my_var
|
46
|
+
end
|
47
|
+
|
48
|
+
def do_simple_work
|
49
|
+
@my_var += 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def parent_object_uuid
|
53
|
+
"fe51cfe1-114f-4516-8c5f-e488e48c3778"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class MyChildProcClass
|
58
|
+
include ProcessMetrics::Timer
|
59
|
+
measure :do_simple_work,
|
60
|
+
parent_uuid: -> { "b0d50400-cae0-4cc4-b289-f487d3c9b397" }
|
61
|
+
|
62
|
+
attr_accessor :my_var
|
63
|
+
|
64
|
+
def initialize(my_var)
|
65
|
+
@my_var = my_var
|
66
|
+
end
|
67
|
+
|
68
|
+
def do_simple_work
|
69
|
+
@my_var += 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class MyChildStringClass
|
74
|
+
include ProcessMetrics::Timer
|
75
|
+
measure :do_simple_work,
|
76
|
+
parent_uuid: "c9b104fb-3389-4c21-b0e9-6c88fd905e4f"
|
77
|
+
|
78
|
+
attr_accessor :my_var
|
79
|
+
|
80
|
+
def initialize(my_var)
|
81
|
+
@my_var = my_var
|
82
|
+
end
|
83
|
+
|
84
|
+
def do_simple_work
|
85
|
+
@my_var += 1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class TestBlock < Minitest::Test
|
90
|
+
def test_simple_method
|
91
|
+
my_object = MyClass.new(1)
|
92
|
+
my_object.do_simple_work
|
93
|
+
|
94
|
+
assert_equal 2, my_object.my_var
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_method_with_params
|
98
|
+
my_object = MyClass.new(2)
|
99
|
+
my_object.do_work_with_params(3)
|
100
|
+
|
101
|
+
assert_equal 8, my_object.my_var
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_method_with_block
|
105
|
+
my_object = MyClass.new(5)
|
106
|
+
|
107
|
+
my_object.do_work_with_block do |that_object|
|
108
|
+
that_object.my_var += 7
|
109
|
+
end
|
110
|
+
|
111
|
+
assert_equal 12, my_object.my_var
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_method_with_params_and_block
|
115
|
+
my_object = MyClass.new(11)
|
116
|
+
|
117
|
+
my_object.do_work_with_params_and_block(13) do |that_object|
|
118
|
+
that_object.my_var += 17
|
119
|
+
end
|
120
|
+
|
121
|
+
assert_equal 46, my_object.my_var
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_child_symbol_simple_method
|
125
|
+
my_object = MyChildSymbolClass.new(1)
|
126
|
+
my_object.do_simple_work
|
127
|
+
|
128
|
+
assert_equal 2, my_object.my_var
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_child_proc_simple_method
|
132
|
+
my_object = MyChildProcClass.new(1)
|
133
|
+
my_object.do_simple_work
|
134
|
+
|
135
|
+
assert_equal 2, my_object.my_var
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_child_string_simple_method
|
139
|
+
my_object = MyChildStringClass.new(1)
|
140
|
+
my_object.do_simple_work
|
141
|
+
|
142
|
+
assert_equal 2, my_object.my_var
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_block
|
146
|
+
ProcessMetrics.measure('anon') do |metric|
|
147
|
+
sleep rand
|
148
|
+
metric.data = { my_key: 'my_value'}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: process_metrics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lucas Uyezu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hashie
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.5
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.5
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: pry-debugger
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.2'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.2.2
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.2'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.2.2
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: minitest
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '5.3'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 5.3.1
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '5.3'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 5.3.1
|
73
|
+
description: A gem that provides utilities to measure a process and its sub tasks.
|
74
|
+
email: lucas@uyezu.com
|
75
|
+
executables: []
|
76
|
+
extensions: []
|
77
|
+
extra_rdoc_files:
|
78
|
+
- README.md
|
79
|
+
files:
|
80
|
+
- README.md
|
81
|
+
- lib/process_metrics.rb
|
82
|
+
- lib/process_metrics/base.rb
|
83
|
+
- lib/process_metrics/config.rb
|
84
|
+
- lib/process_metrics/persistence.rb
|
85
|
+
- lib/process_metrics/persistence/logger.rb
|
86
|
+
- lib/process_metrics/timer.rb
|
87
|
+
- lib/process_metrics/version.rb
|
88
|
+
- test/test_simple.rb
|
89
|
+
homepage: https://github.com/lucasuyezu/process_metrics
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options:
|
95
|
+
- "--charset=UTF-8"
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.2.2
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Process metrics
|
114
|
+
test_files:
|
115
|
+
- test/test_simple.rb
|