timeasure 0.1.1 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 98176f0d699b3c9ca5cd0e101021edafe375e77d
4
- data.tar.gz: 7be9aa110d461fd15ebe5b449e307c5159df778d
3
+ metadata.gz: 646792d500a9a61b929dd067f9c1b48b9bf30b2d
4
+ data.tar.gz: 1c0b5af7065eb1a950e201521ca7ec2f5c644964
5
5
  SHA512:
6
- metadata.gz: '03826e4210bf05d86005e3245f35c90e02aa75e4771195b850a3ba9744535404d799474e56e7db7312bb48ae89ef70a2c455bc661a9c48e3156fa2932dc8ec55'
7
- data.tar.gz: 50bdd345a80bfc306eb3138f46c7a3f20493d8193d53ee73d0c538da92da86ffeca7eff5a3dc8d52e0890e8cfc014cd998e8f0efe3792947ad9829bb43c43762
6
+ metadata.gz: 81af656e98f415dddf152dbec13530c84d4506c64eac0fd13b6f217aad76598dd10251c18239de1c9b69eb8fabc18d732531ce45fe188a73a144453580be486a
7
+ data.tar.gz: b2062fb31932f6087a6ec43b7f8f7991a868f8b8ff4081e7579358fa9798a1438e377144a257cedc2d36aec0a6570ba772b3c07d8d2fc0bbc9d366b289cc7919
data/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.2.0] - 2018-03-12
10
+ ### Added
11
+ - New class macros for tracking private methods in both inline and scoped visibility declaration.
12
+
13
+ ### Changed
14
+ - Start using `Process.clock_gettime(Process::CLOCK_MONOTONIC)` instead of `Time.now` for time tracking
15
+ - Bumped up required Ruby version from 2.0 to 2.1
16
+
17
+ ## [0.1.1] - 2018-02-24
18
+ ### Added
19
+ - Specs for describing the proper way to track private methods.
20
+
21
+ ### Fixed
22
+ - Minor performance issue in class macros
23
+
24
+ ## [0.1.0] - 2018-02-24
25
+ ### Added
26
+ - Timeasure main code
27
+ - Timeasure profiler
28
+
29
+ [0.2.0]: https://github.com/Riskified/timeasure/compare/v0.1.1...v0.2.0
30
+ [0.1.1]: https://github.com/Riskified/timeasure/compare/v0.1.0...v0.1.1
data/README.md CHANGED
@@ -39,7 +39,7 @@ Timeasure is developed and maintained by [Eliav Lavi](http://www.eliavlavi.com)
39
39
 
40
40
  ## Requirements
41
41
 
42
- Ruby 2.0 or a later version is mandatory. (Timeasure uses `Module#prepend` introduced in Ruby 2.0.)
42
+ Ruby 2.1 or a later version is mandatory. (Timeasure uses `Module#prepend` introduced in Ruby 2.0 and `Process::CLOCK_MONOTONIC` introduced in Ruby 2.1.)
43
43
 
44
44
  ## Installation
45
45
 
@@ -78,6 +78,70 @@ class Foo
78
78
  end
79
79
  end
80
80
  ```
81
+ **An Important Note Regarding Private Methods**
82
+
83
+ If you need to track any private methods - either class methods or instance methods - use the designated class macros for that:
84
+
85
+ ```ruby
86
+ class Foo
87
+ include Timeasure
88
+ tracked_class_methods :a_class_method_that_calls_private_methods
89
+ tracked_private_class_methods :a_scoped_private_class_method, :an_inline_private_class_method
90
+
91
+ class << self
92
+ def a_class_method_that_calls_private_methods
93
+ a_scoped_private_class_method
94
+ an_inline_private_class_method
95
+ end
96
+
97
+ def a_scoped_private_class_method
98
+ # some private class-level stuff that can benefit from measuring runtime...
99
+ end
100
+ end
101
+
102
+ def self.an_inline_private_class_method
103
+ # some other private class-level stuff that can benefit from measuring runtime...
104
+ end
105
+ end
106
+ ```
107
+
108
+ And the instance-level equivalent:
109
+
110
+ ```ruby
111
+ class Foo
112
+ include Timeasure
113
+ tracked_instance_methods :a_instance_method_that_calls_private_methods
114
+ tracked_private_instance_methods :a_scoped_private_instance_method, :an_inline_private_instance_method
115
+
116
+ class << self
117
+ def a_instance_method_that_calls_private_methods
118
+ a_scoped_private_instance_method
119
+ an_inline_private_instance_method
120
+ end
121
+
122
+ def a_scoped_private_instance_method
123
+ # some private instance-level stuff that can benefit from measuring runtime...
124
+ end
125
+ end
126
+
127
+ def self.an_inline_private_instance_method
128
+ # some other private instance-level stuff that can benefit from measuring runtime...
129
+ end
130
+ end
131
+ ```
132
+
133
+ **ATTENTION!**
134
+
135
+ **Declaring the tracking of private methods with `tracked_class_methods` or `tracked_instance_methods` will end up in `NoMethodError` upon calling their triggering method!**
136
+
137
+ Also, tracking your public methods with `tracked_private_class_methods` or `tracked_private_instance_methods` will make your class' interface inaccessible.
138
+ The reason for these two is that since Timeasure is declared at the top of the class,
139
+ it cannot know in advance which methods will be declared as private, so you need to specify this explicitly.
140
+
141
+ As a side note, it could be claimed that as a rule of thumb, if you find yourself measuring private methods,
142
+ this might be a good idea to invest in refactoring this area of code and [Extract Class](https://refactoring.guru/extract-class).
143
+ However, this is not always possible, of course, especially when working on legacy code.
144
+ Hence, this feature of Timeasure should be considered as somewhat of a last resort and be handled with care.
81
145
 
82
146
  #### 2. Define the Boundaries of the Tracked Transaction
83
147
  **Preparing for Method Tracking**
data/lib/timeasure.rb CHANGED
@@ -27,9 +27,9 @@ module Timeasure
27
27
  end
28
28
 
29
29
  def measure(klass_name: nil, method_name: nil, segment: nil, metadata: nil)
30
- t0 = Time.now.utc
30
+ t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
31
31
  block_return_value = yield if block_given?
32
- t1 = Time.now.utc
32
+ t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
33
33
 
34
34
  begin
35
35
  measurement = Timeasure::Measurement.new(klass_name: klass_name.to_s, method_name: method_name.to_s,
@@ -1,19 +1,27 @@
1
1
  module Timeasure
2
2
  module ClassMethods
3
3
  def tracked_instance_methods(*method_names)
4
- instance_interceptor = const_get("#{timeasure_name}InstanceInterceptor")
5
4
  method_names.each do |method_name|
6
5
  add_method_to_interceptor(instance_interceptor, method_name)
7
6
  end
8
7
  end
9
8
 
10
9
  def tracked_class_methods(*method_names)
11
- class_interceptor = const_get("#{timeasure_name}ClassInterceptor")
12
10
  method_names.each do |method_name|
13
11
  add_method_to_interceptor(class_interceptor, method_name)
14
12
  end
15
13
  end
16
14
 
15
+ def tracked_private_instance_methods(*method_names)
16
+ tracked_instance_methods(*method_names)
17
+ method_names.each { |method_name| privatize_interceptor_method(instance_interceptor, method_name) }
18
+ end
19
+
20
+ def tracked_private_class_methods(*method_names)
21
+ tracked_class_methods(*method_names)
22
+ method_names.each { |method_name| privatize_interceptor_method(class_interceptor, method_name) }
23
+ end
24
+
17
25
  def timeasure_name
18
26
  name.gsub('::', '_')
19
27
  end
@@ -29,5 +37,17 @@ module Timeasure
29
37
  end
30
38
  end
31
39
  end
40
+
41
+ def privatize_interceptor_method(interceptor, method_name)
42
+ interceptor.class_eval { private method_name }
43
+ end
44
+
45
+ def instance_interceptor
46
+ const_get("#{timeasure_name}InstanceInterceptor")
47
+ end
48
+
49
+ def class_interceptor
50
+ const_get("#{timeasure_name}ClassInterceptor")
51
+ end
32
52
  end
33
53
  end
@@ -1,3 +1,3 @@
1
1
  module Timeasure
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/timeasure.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^spec/})
20
20
  spec.require_paths = ['lib', 'lib/timeasure', 'lib/timeasure/profiling']
21
21
 
22
- spec.required_ruby_version = '>= 2.0'
22
+ spec.required_ruby_version = '>= 2.1'
23
23
  spec.add_development_dependency 'bundler', '~> 1.6'
24
24
  spec.add_development_dependency 'coveralls'
25
25
  spec.add_development_dependency 'rake', '~> 12.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeasure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eliav Lavi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-24 00:00:00.000000000 Z
11
+ date: 2018-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -79,6 +79,7 @@ files:
79
79
  - ".gitignore"
80
80
  - ".rspec"
81
81
  - ".rubocop.yml"
82
+ - CHANGELOG.md
82
83
  - Gemfile
83
84
  - LICENSE.txt
84
85
  - README.md
@@ -106,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
107
  requirements:
107
108
  - - ">="
108
109
  - !ruby/object:Gem::Version
109
- version: '2.0'
110
+ version: '2.1'
110
111
  required_rubygems_version: !ruby/object:Gem::Requirement
111
112
  requirements:
112
113
  - - ">="