timeasure 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 284614263b2c5c4343831c8d79e391c869009490
4
+ data.tar.gz: 72aa7b99c6eaeef54890c1c12d66679be73895f1
5
+ SHA512:
6
+ metadata.gz: 175a8df40f6cf4a2ef58b11375b6b83da05499d960ed67055812fae8ebb9337b5d76834a432efc781d6ca8afc43f2fe816011538047755746bffb1ca448e853d
7
+ data.tar.gz: 20b2c718f96d7d0f8057cb086dc0cdab8fce80b1933fe9b7c0f68dddfa9606244b99cf57311b89976bac98250c8bd15652f832aba2ceb4317cd2e7d7c29dc5e5
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .idea/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4.2
3
+
4
+ Metrics/LineLength:
5
+ Max: 120
6
+
7
+ Documentation:
8
+ Enabled: false
9
+
10
+ Metrics/BlockLength:
11
+ ExcludedMethods: ['describe', 'context', 'before']
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in timeasure.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 Eliav Lavi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # Timeasure
2
+
3
+ **What Is It?**
4
+
5
+ Timeasure is a transparent method-level wrapper for profiling purposes developed by [Eliav Lavi](http://www.eliavlavi.com) & [Riskified](https://www.riskified.com/)).
6
+
7
+ Timeasure is a Ruby gem that allows measuring the runtime of methods in production environments
8
+ without having to alter the code of the methods themselves.
9
+
10
+ Timeasure allows you to declare tracked methods to be measured transparently upon each call.
11
+ Measured calls are then reported to Timeasure's Profiler, which aggregates the measurements on the method level.
12
+ This part is configurable and if you wish you can report measurements to another profiler of your choice.
13
+
14
+ **Why Use It?**
15
+
16
+ Timeasure was created in order to serve as an easy-to-use, self-contained framework for method-level profiling
17
+ that is safe to use in production. Testing runtime in non-production environments is helpful, but there is
18
+ great value to the knowledge gained by measuring what really goes on at real time.
19
+
20
+ **What To Do With the Data?**
21
+
22
+ The imagined usage of measured methods timing is to aggregate it along a certain transaction and report it to a live
23
+ BI service such as [NewRelic Insights](https://newrelic.com/insights) or [Keen.io](https://keen.io/);
24
+ however, different usages might prove helpful as well, such as writing the data to a database or a file.
25
+
26
+ **Disclaimers**
27
+
28
+ Timeasure uses minimal intervention in the Ruby Object Model for tracked modules and classes.
29
+ It integrates well within Rails and non-Rails apps.
30
+
31
+ Timeasure is inspired by [Metaprogramming Ruby 2](https://pragprog.com/book/ppmetr2/metaprogramming-ruby-2)
32
+ by [Paolo Perrotta](https://twitter.com/nusco)
33
+ and by [this](https://hashrocket.com/blog/posts/module-prepend-a-super-story) blog post by Hashrocket.
34
+
35
+ ## Requirements
36
+
37
+ Ruby 2.0 or a later version is mandatory. (Timeasure uses `Module#prepend` introduced in Ruby 2.0.)
38
+
39
+ ## Installation
40
+
41
+ Add this line to your application's Gemfile:
42
+
43
+ gem 'timeasure'
44
+
45
+ And then execute:
46
+
47
+ $ bundle
48
+
49
+ Or install it yourself as:
50
+
51
+ $ gem install timeasure
52
+
53
+ ## Usage
54
+ #### 1. Include Timeasure in Modules and Classes
55
+ Simply include the Timeasure module in any class or module and declare the desired methods to track:
56
+
57
+ ```ruby
58
+ class Foo
59
+ include Timeasure
60
+ tracked_class_methods :bar
61
+ tracked_instance_methods :baz, :qux
62
+
63
+ def self.bar
64
+ # some class-level stuff that can benefit from measuring runtime...
65
+ end
66
+
67
+ def baz
68
+ # some instance-level stuff that can benefit from measuring runtime...
69
+ end
70
+
71
+ def qux
72
+ # some other instance-level stuff that can benefit from measuring runtime...
73
+ end
74
+ end
75
+ ```
76
+
77
+ #### 2. Define the Boundaries of the Tracked Transaction
78
+ **Preparing for Method Tracking**
79
+
80
+ The user is responsible for managing the final reporting and the clean-up of the aggregated data after each transation.
81
+ It is recommended to prepare the profiler at the beginning of a transaction in which tracked methods exist with
82
+
83
+ ```ruby
84
+ Timeasure::Profiling::Manager.prepare
85
+ ```
86
+ and to re-prepare it again at the end of it in order to ensure a "clean slate" -
87
+ after you have handled the aggregated data in some way.
88
+
89
+ **Getting Hold of the Data**
90
+
91
+ In order to get hold of the reported methods data, use
92
+ ```ruby
93
+ Timeasure::Profiling::Manager.export
94
+ ````
95
+ This will return an array of `ReportedMethod`s. Each `ReportedMethod` object holds the aggregated timing data per
96
+ each tracked method call. This means that no matter how many times you call a tracked method, Timeasure's Profiler will
97
+ still hold a single `ReportedMethod` object to represent it.
98
+
99
+ `ReportedMethod` allows reading the following attributes:
100
+ * `klass_name`: Name of the class in which the tracked method resides.
101
+ * `method_name`: Name of the tracked method.
102
+ * `segment`: See [Segmented Method Tracking](#segmented-method-tracking) below.
103
+ * `metadata`: See [Carrying Metadata](#carrying-metadata) below.
104
+ * `method_path`: `klass_name` and `method_name` concatenated.
105
+ * `full_path`: Same as `method_path` unless segmentation is declared,
106
+ in which case the segment will be concatenated to the string as well. See [Segmented Method Tracking](#segmented-method-tracking) below.
107
+ * `runtime_sum`: The aggregated time it took the reported method in question to run across all calls.
108
+ * `call_count`: The times the reported method in question was called across all calls.
109
+
110
+
111
+ ## Advanced Usage
112
+
113
+ #### Segmented Method Tracking
114
+ Timeasure was designed to separate regular code from its time measurement declaration.
115
+ This is achieved by Timeasure's class macros `tracked_class_methods` and `tracked_instance_methods`.
116
+ Sometimes, however, the need for additional data might arise. Imagine this method:
117
+
118
+ ```ruby
119
+ class Foo
120
+ def bar(baz)
121
+ # some stuff that can benefit from measuring runtime
122
+ # yet its runtime is also highly affected by the value of baz...
123
+ end
124
+ end
125
+ ```
126
+
127
+ We've seen how Timeasure makes it easy to measure the `bar` method.
128
+ However, if we wish to segment each call by the value of `baz`,
129
+ we may use Timeasure's direct interface and send this value as a **segment**:
130
+
131
+ ```ruby
132
+ class Foo
133
+ def bar(baz)
134
+ Timeasure.measure(klass_name: 'Foo', method_name: 'bar', segment: { baz: baz }) do
135
+ # the code to be measured
136
+ end
137
+ end
138
+ end
139
+ ```
140
+
141
+ For such calls, Timeasure's Profiler will aggregate the data in `ReportedMethod` objects grouped by
142
+ class, method and segment.
143
+
144
+ This approach obviously violates Timeasure's idea of separating code and measurement-declaration,
145
+ but it allows for much more detailed investigations, if needed.
146
+ This will result in different `ReportedMethod` object in Timeasure's Profiler for
147
+ each combination of class, method and segment. Accordingly, such `ReportedMethod` object will include
148
+ these three elements, concatenated, as the value for `ReportedMethod#full_path`.
149
+
150
+ #### Carrying Metadata
151
+ This feature was developed in order to complement the segmented method tracking.
152
+
153
+ Sometimes carrying data with measurement that does not define a segment might be needed.
154
+ For example, assuming we save all our `ReportedMethod`s to some table called `reported_methods`,
155
+ we might want to supply a custom table name for specific measurements.
156
+ This might be achieved by using `metadata`:
157
+
158
+ ```ruby
159
+ class Foo
160
+ def bar
161
+ Timeasure.measure(klass_name: 'Foo', method_name: 'bar', metadata: { table_name: 'my_custom_table' }) do
162
+ # the code to be measured
163
+ end
164
+ end
165
+ end
166
+ ```
167
+
168
+ Unlike Segments, Timeasure only carries the Metadata onwards.
169
+ It is up to the user to make use of this data, probably after calling `Timeasure::Profiling::Manager.export`.
170
+
171
+ ## Notes
172
+
173
+ #### Compatibility with RSpec
174
+
175
+ If you run your test suite with Timeasure installed and modules, classes and methods tracked and all works fine - hurray!
176
+ However, due to the mechanics of Timeasure - namely, its usage of prepended modules - there exist a problem with
177
+ **stubbing** Timeasure-tracked method (RSpec does not support stubbing methods that appear in a prepended module).
178
+ To be accurate, that means that if you are tracking method `#foo`, you can not
179
+ declare something like `allow(bar).to receive(:foo).and_return(bar)`. Your specs will refuse to run in this case.
180
+ To solve that problem you can configure Timeasure's `enable_timeasure_proc` **not** to run under certain conditions.
181
+
182
+ If you are on Rails, add the following as a Rails initializer:
183
+
184
+ ```ruby
185
+ require 'timeasure'
186
+
187
+ Timeasure.configure do |configuration|
188
+ configuration.enable_timeasure_proc = lambda { !Rails.env.test? }
189
+ end
190
+ ```
191
+
192
+ Timeasure will not come into action if the expression in the block evaluates to `false`.
193
+ By default this block evaluates to `true`.
194
+
195
+
196
+ ## Feature Requests
197
+
198
+ Timeasure is open for changes and requests!
199
+ If you have an idea, a question or some need, feel free to contact me here or at eliavlavi@gmail.com.
200
+
201
+ ## Contributing
202
+
203
+ 1. Fork it ( https://github.com/riskified/timeasure/fork )
204
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
205
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
206
+ 4. Push to the branch (`git push origin my-new-feature`)
207
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/lib/timeasure.rb ADDED
@@ -0,0 +1,69 @@
1
+ require_relative 'timeasure/version'
2
+ require_relative 'timeasure/configuration'
3
+ require_relative 'timeasure/class_methods'
4
+ require_relative 'timeasure/measurement'
5
+ require_relative 'timeasure/profiling/manager'
6
+
7
+ module Timeasure
8
+ class << self
9
+ def configure
10
+ yield(configuration)
11
+ end
12
+
13
+ def configuration
14
+ @configuration ||= Configuration.new
15
+ end
16
+
17
+ def included(base_class)
18
+ base_class.extend ClassMethods
19
+
20
+ instance_interceptor = const_set(instance_interceptor_name_for(base_class), interceptor_module_for(base_class))
21
+ class_interceptor = const_set(class_interceptor_name_for(base_class), interceptor_module_for(base_class))
22
+
23
+ return unless timeasure_enabled?
24
+
25
+ base_class.prepend instance_interceptor
26
+ base_class.singleton_class.prepend class_interceptor
27
+ end
28
+
29
+ def measure(klass_name: nil, method_name: nil, segment: nil, metadata: nil)
30
+ t0 = Time.now.utc
31
+ block_return_value = yield if block_given?
32
+ t1 = Time.now.utc
33
+
34
+ begin
35
+ measurement = Timeasure::Measurement.new(klass_name: klass_name.to_s, method_name: method_name.to_s,
36
+ segment: segment, metadata: metadata, t0: t0, t1: t1)
37
+ Timeasure.configuration.post_measuring_proc.call(measurement)
38
+ rescue => e
39
+ Timeasure.configuration.rescue_proc.call(e, klass_name)
40
+ end
41
+
42
+ block_return_value
43
+ end
44
+
45
+ private
46
+
47
+ def instance_interceptor_name_for(base_class)
48
+ "#{base_class.timeasure_name}InstanceInterceptor"
49
+ end
50
+
51
+ def class_interceptor_name_for(base_class)
52
+ "#{base_class.timeasure_name}ClassInterceptor"
53
+ end
54
+
55
+ def interceptor_module_for(base_class)
56
+ Module.new do
57
+ @klass_name = base_class
58
+
59
+ def self.klass_name
60
+ @klass_name
61
+ end
62
+ end
63
+ end
64
+
65
+ def timeasure_enabled?
66
+ configuration.enable_timeasure_proc.call
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,33 @@
1
+ module Timeasure
2
+ module ClassMethods
3
+ def tracked_instance_methods(*method_names)
4
+ method_names.each do |method_name|
5
+ instance_interceptor = const_get("#{timeasure_name}InstanceInterceptor")
6
+ add_method_to_interceptor(instance_interceptor, method_name)
7
+ end
8
+ end
9
+
10
+ def tracked_class_methods(*method_names)
11
+ method_names.each do |method_name|
12
+ class_interceptor = const_get("#{timeasure_name}ClassInterceptor")
13
+ add_method_to_interceptor(class_interceptor, method_name)
14
+ end
15
+ end
16
+
17
+ def timeasure_name
18
+ name.gsub('::', '_')
19
+ end
20
+
21
+ private
22
+
23
+ def add_method_to_interceptor(interceptor, method_name)
24
+ interceptor.class_eval do
25
+ define_method method_name do |*args, &block|
26
+ Timeasure.measure(klass_name: interceptor.klass_name.to_s, method_name: method_name.to_s) do
27
+ super(*args, &block)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,42 @@
1
+ module Timeasure
2
+ class Configuration
3
+ attr_accessor :post_measuring_proc, :rescue_proc, :enable_timeasure_proc,
4
+ :reported_methods_handler_set_proc, :reported_methods_handler_get_proc
5
+
6
+ def initialize
7
+ @post_measuring_proc = lambda do |measurement|
8
+ # Enables the configuration of what to do with each method runtime measurement.
9
+ # By default it reports to Timeasure's Profiling Manager.
10
+
11
+ Timeasure::Profiling::Manager.report(measurement)
12
+ end
13
+
14
+ @rescue_proc = lambda do |e, klass|
15
+ # Enabled the configuration of post_measuring_proc rescue.
16
+ end
17
+
18
+ @enable_timeasure_proc = lambda do
19
+ # Enables toggling Timeasure's activation (e.g. for disabling Timeasure for RSpec).
20
+
21
+ true
22
+ end
23
+
24
+ @reported_methods_handler_set_proc = lambda do |reported_methods_handler|
25
+ # Enables configuring where to store the ReportedMethodsHandler instance.
26
+ # This proc will be called by Timeasure::Profiling::Manager.prepare.
27
+ # By default it stores the handler as a class instance variable (in Timeasure::Profiling::Manager)
28
+
29
+ @reported_methods_handler = reported_methods_handler
30
+ end
31
+
32
+ @reported_methods_handler_get_proc = lambda do
33
+ # Enables configuring where to fetch the ReportedMethodsHandler instance.
34
+ # This proc will be called by Timeasure::Profiling::Manager.report and Timeasure::Profiling::Manager.export.
35
+ # By default it fetches the handler from the class instance variable
36
+ # (see @reported_methods_handler_set_proc).
37
+
38
+ @reported_methods_handler
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module Timeasure
2
+ class Measurement
3
+ attr_reader :klass_name, :method_name, :segment, :metadata, :t0, :t1
4
+
5
+ def initialize(klass_name:, method_name:, t0:, t1:, segment: nil, metadata: nil)
6
+ @klass_name = klass_name
7
+ @method_name = method_name
8
+ @t0 = t0
9
+ @t1 = t1
10
+ @segment = segment
11
+ @metadata = metadata
12
+ end
13
+
14
+ def runtime_in_milliseconds
15
+ (@t1 - @t0) * 1000
16
+ end
17
+
18
+ def full_path
19
+ @segment.nil? ? method_path : "#{method_path}:#{@segment}"
20
+ end
21
+
22
+ def method_path
23
+ "#{@klass_name}##{@method_name}"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ require 'logger'
2
+ require_relative 'reported_methods_handler'
3
+ require_relative 'reported_method'
4
+
5
+ module Timeasure
6
+ module Profiling
7
+ class Manager
8
+ class << self
9
+ def prepare
10
+ Timeasure.configuration.reported_methods_handler_set_proc.call(ReportedMethodsHandler.new)
11
+ end
12
+
13
+ def report(measurement)
14
+ handler = reported_methods_handler
15
+ handler.nil? ? warn_unprepared_handler : handler.report(measurement)
16
+ end
17
+
18
+ def export
19
+ handler = reported_methods_handler
20
+ handler.nil? ? warn_unprepared_handler : handler.export
21
+ end
22
+
23
+ private
24
+
25
+ def reported_methods_handler
26
+ Timeasure.configuration.reported_methods_handler_get_proc.call
27
+ end
28
+
29
+ def warn_unprepared_handler
30
+ logger.warn("#{self} is not prepared. Call Timeasure::Profiling::Manager.prepare before trying to report measurements or export reported methods.")
31
+ end
32
+
33
+ def logger
34
+ @logger ||= Logger.new(STDOUT)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ module Timeasure
2
+ module Profiling
3
+ class ReportedMethod
4
+ attr_reader :klass_name, :method_name, :segment, :metadata, :full_path, :method_path, :runtime_sum, :call_count
5
+
6
+ def initialize(measurement)
7
+ @klass_name = measurement.klass_name
8
+ @method_name = measurement.method_name
9
+ @segment = measurement.segment
10
+ @metadata = measurement.metadata
11
+ @full_path = measurement.full_path
12
+ @method_path = measurement.method_path
13
+
14
+ @runtime_sum = 0
15
+ @call_count = 0
16
+ end
17
+
18
+ def increment_runtime_sum(runtime)
19
+ @runtime_sum += runtime
20
+ end
21
+
22
+ def increment_call_count
23
+ @call_count += 1
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ module Timeasure
2
+ module Profiling
3
+ class ReportedMethodsHandler
4
+ def initialize
5
+ @reported_methods = {}
6
+ end
7
+
8
+ def report(measurement)
9
+ initialize_path_for(measurement) if path_uninitialized_for(measurement)
10
+
11
+ @reported_methods[measurement.full_path].increment_runtime_sum(measurement.runtime_in_milliseconds)
12
+ @reported_methods[measurement.full_path].increment_call_count
13
+ end
14
+
15
+ def export
16
+ @reported_methods.values
17
+ end
18
+
19
+ private
20
+
21
+ def path_uninitialized_for(measurement)
22
+ @reported_methods[measurement.full_path].nil?
23
+ end
24
+
25
+ def initialize_path_for(measurement)
26
+ @reported_methods[measurement.full_path] = ReportedMethod.new(measurement)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module Timeasure
2
+ VERSION = '0.1.0'
3
+ end
data/timeasure.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'timeasure/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'timeasure'
7
+ spec.version = Timeasure::VERSION
8
+ spec.authors = ['Eliav Lavi']
9
+ spec.email = ['eliav@riskified.com', 'eliavlavi@gmail.com']
10
+ spec.summary = 'Transparent method-level wrapper for profiling purposes'
11
+ spec.description = <<-DESCRIPTION
12
+ Timeasure is a Ruby gem that allows measuring the runtime of methods
13
+ without having to alter the code of the methods themselves.
14
+ DESCRIPTION
15
+ spec.homepage = 'https://github.com/riskified/timeasure'
16
+ spec.license = 'MIT'
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.start_with? 'spec/' }
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^spec/})
20
+ spec.require_paths = ['lib', 'lib/timeasure', 'lib/timeasure/profiling']
21
+
22
+ spec.required_ruby_version = '>= 2.0'
23
+ spec.add_development_dependency 'bundler', '~> 1.6'
24
+ spec.add_development_dependency 'coveralls'
25
+ spec.add_development_dependency 'rake', '~> 12.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.6'
27
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timeasure
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eliav Lavi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: coveralls
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.6'
69
+ description: |2
70
+ Timeasure is a Ruby gem that allows measuring the runtime of methods
71
+ without having to alter the code of the methods themselves.
72
+ email:
73
+ - eliav@riskified.com
74
+ - eliavlavi@gmail.com
75
+ executables: []
76
+ extensions: []
77
+ extra_rdoc_files: []
78
+ files:
79
+ - ".gitignore"
80
+ - ".rspec"
81
+ - ".rubocop.yml"
82
+ - Gemfile
83
+ - LICENSE.txt
84
+ - README.md
85
+ - Rakefile
86
+ - lib/timeasure.rb
87
+ - lib/timeasure/class_methods.rb
88
+ - lib/timeasure/configuration.rb
89
+ - lib/timeasure/measurement.rb
90
+ - lib/timeasure/profiling/manager.rb
91
+ - lib/timeasure/profiling/reported_method.rb
92
+ - lib/timeasure/profiling/reported_methods_handler.rb
93
+ - lib/timeasure/version.rb
94
+ - timeasure.gemspec
95
+ homepage: https://github.com/riskified/timeasure
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ - lib/timeasure
104
+ - lib/timeasure/profiling
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '2.0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.6.14
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: Transparent method-level wrapper for profiling purposes
121
+ test_files: []