instrument_all_the_things 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.drone.yml +14 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +95 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +7 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +74 -0
  10. data/README.md +397 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +11 -0
  13. data/bin/setup +8 -0
  14. data/instrument_all_the_things.gemspec +42 -0
  15. data/lib/instrument_all_the_things.rb +70 -0
  16. data/lib/instrument_all_the_things/clients/stat_reporter/datadog.rb +12 -0
  17. data/lib/instrument_all_the_things/clients/tracer/blackhole.rb +22 -0
  18. data/lib/instrument_all_the_things/context.rb +23 -0
  19. data/lib/instrument_all_the_things/helpers.rb +55 -0
  20. data/lib/instrument_all_the_things/instrumentors/all.rb +6 -0
  21. data/lib/instrument_all_the_things/instrumentors/error_logging.rb +48 -0
  22. data/lib/instrument_all_the_things/instrumentors/execution_count_and_timing.rb +21 -0
  23. data/lib/instrument_all_the_things/instrumentors/gc_stats.rb +49 -0
  24. data/lib/instrument_all_the_things/instrumentors/tracing.rb +30 -0
  25. data/lib/instrument_all_the_things/method_instrumentor.rb +57 -0
  26. data/lib/instrument_all_the_things/method_proxy.rb +77 -0
  27. data/lib/instrument_all_the_things/testing/rspec_matchers.rb +97 -0
  28. data/lib/instrument_all_the_things/testing/stat_tracker.rb +43 -0
  29. data/lib/instrument_all_the_things/testing/trace_tracker.rb +25 -0
  30. data/lib/instrument_all_the_things/version.rb +5 -0
  31. data/logo.jpg +0 -0
  32. data/vendor/cache/ast-2.4.0.gem +0 -0
  33. data/vendor/cache/benchmark-ips-2.7.2.gem +0 -0
  34. data/vendor/cache/coderay-1.1.2.gem +0 -0
  35. data/vendor/cache/ddtrace-0.34.0.gem +0 -0
  36. data/vendor/cache/diff-lcs-1.3.gem +0 -0
  37. data/vendor/cache/docile-1.3.2.gem +0 -0
  38. data/vendor/cache/dogstatsd-ruby-4.7.0.gem +0 -0
  39. data/vendor/cache/jaro_winkler-1.5.4.gem +0 -0
  40. data/vendor/cache/method_source-0.9.2.gem +0 -0
  41. data/vendor/cache/msgpack-1.3.3.gem +0 -0
  42. data/vendor/cache/parallel-1.19.1.gem +0 -0
  43. data/vendor/cache/parser-2.7.0.2.gem +0 -0
  44. data/vendor/cache/pry-0.12.2.gem +0 -0
  45. data/vendor/cache/rainbow-3.0.0.gem +0 -0
  46. data/vendor/cache/rake-10.5.0.gem +0 -0
  47. data/vendor/cache/rexml-3.2.4.gem +0 -0
  48. data/vendor/cache/rspec-3.9.0.gem +0 -0
  49. data/vendor/cache/rspec-core-3.9.1.gem +0 -0
  50. data/vendor/cache/rspec-expectations-3.9.0.gem +0 -0
  51. data/vendor/cache/rspec-mocks-3.9.1.gem +0 -0
  52. data/vendor/cache/rspec-support-3.9.2.gem +0 -0
  53. data/vendor/cache/rubocop-0.80.0.gem +0 -0
  54. data/vendor/cache/ruby-progressbar-1.10.1.gem +0 -0
  55. data/vendor/cache/simplecov-0.18.1.gem +0 -0
  56. data/vendor/cache/simplecov-html-0.11.0.gem +0 -0
  57. data/vendor/cache/unicode-display_width-1.6.1.gem +0 -0
  58. metadata +227 -0
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './method_instrumentor'
4
+
5
+ module InstrumentAllTheThings
6
+ module MethodProxy
7
+ def self.for_class(klass)
8
+ find_for_class(klass) || install_on_class(klass)
9
+ end
10
+
11
+ def self.find_for_class(klass)
12
+ klass.ancestors.detect do |a|
13
+ a.is_a?(Instrumentor) &&
14
+ a._iatt_built_for == klass
15
+ end
16
+ end
17
+
18
+ def self.install_on_class(klass)
19
+ construct_for_class(klass).tap do |m|
20
+ klass.prepend(m)
21
+ end
22
+ end
23
+
24
+ def self.construct_for_class(klass)
25
+ Module.new do
26
+ extend Instrumentor
27
+ end.tap { |m| m._iatt_built_for = klass }
28
+ end
29
+
30
+ module Instrumentor
31
+ def inspect
32
+ "InstrumentAllTheThings::#{@_iatt_built_for}Proxy"
33
+ end
34
+
35
+ def _iatt_built_for
36
+ @_iatt_built_for
37
+ end
38
+
39
+ def _iatt_built_for=(val)
40
+ @_iatt_built_for = val
41
+ end
42
+
43
+ def set_context_tags(klass, settings, args, kwargs)
44
+ return unless settings.is_a?(Hash) && settings[:trace].is_a?(Hash) && settings[:trace][:tags]
45
+
46
+ settings[:context][:tags] = settings[:trace][:tags].map do |tag|
47
+ if tag.is_a?(Proc)
48
+ case tag.arity
49
+ when 2
50
+ tag.call(args, kwargs)
51
+ when 1
52
+ tag.parameters[0][1].to_s == 'args' ? tag.call(args) : tag.call(kwargs)
53
+ else
54
+ klass.instance_exec(&tag)
55
+ end
56
+ else
57
+ tag
58
+ end
59
+ rescue StandardError
60
+ nil
61
+ end.compact
62
+ end
63
+
64
+ def wrap_implementation(method_name, settings)
65
+ wrap = MethodInstrumentor.new(**settings)
66
+ set_tags = method(:set_context_tags)
67
+
68
+ define_method(method_name) do |*args, **kwargs, &blk|
69
+ set_tags.call(self, settings, args, kwargs)
70
+ wrap.invoke(klass: is_a?(Class) ? self : self.class) do
71
+ super(*args, **kwargs, &blk)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InstrumentAllTheThings
4
+ module Testing
5
+ module RSpecMatchers
6
+ def histogram_value(counter_name)
7
+ stats = InstrumentAllTheThings.stat_reporter.emitted_values[:histogram][counter_name]
8
+ stats.inject(0){|l, n| l + n[:args][0] }
9
+ end
10
+
11
+ def distribution_values(distribution_name, with_tags: nil)
12
+ stats = InstrumentAllTheThings.stat_reporter.emitted_values[:distribution][distribution_name]
13
+
14
+ if with_tags && !stats.empty?
15
+ stats = stats.select do |s|
16
+ with_tags.all?{|t| s[:tags].include?(t) }
17
+ end
18
+ end
19
+
20
+ stats&.map{|i| i[:args] }&.map(&:first) || []
21
+ end
22
+
23
+ def histogram_values(histogram_name, with_tags: nil)
24
+ stats = InstrumentAllTheThings.stat_reporter.emitted_values[:histogram][histogram_name]
25
+
26
+ if with_tags && !stats.empty?
27
+ stats = stats.select do |s|
28
+ with_tags.all?{|t| s[:tags].include?(t) }
29
+ end
30
+ end
31
+
32
+ stats&.map{|i| i[:args] }&.map(&:first) || []
33
+ end
34
+
35
+ def timing_values(timing_name, with_tags: nil)
36
+ stats = InstrumentAllTheThings.stat_reporter.emitted_values[:timing][timing_name]
37
+
38
+ if with_tags && !stats.empty?
39
+ stats = stats.select do |s|
40
+ with_tags.all?{|t| s[:tags].include?(t) }
41
+ end
42
+ end
43
+
44
+ stats&.map{|i| i[:args] }&.map(&:first) || []
45
+ end
46
+
47
+ def set_value(counter_name, with_tags: nil)
48
+ stats = InstrumentAllTheThings.stat_reporter.emitted_values[:set][counter_name]
49
+
50
+ if with_tags && !stats.empty?
51
+ stats = stats.select do |s|
52
+ with_tags.all?{|t| s[:tags].include?(t) }
53
+ end
54
+ end
55
+
56
+ data = stats&.map{|i| i[:args] }&.map(&:first)
57
+ data ? data.uniq.length : 0
58
+ end
59
+
60
+ def gauge_value(counter_name, with_tags: nil)
61
+ stats = InstrumentAllTheThings.stat_reporter.emitted_values[:gauge][counter_name]
62
+
63
+ if with_tags && !stats.empty?
64
+ stats = stats.select do |s|
65
+ with_tags.all?{|t| s[:tags].include?(t) }
66
+ end
67
+ end
68
+ stats.last&.fetch(:args)&.first
69
+ end
70
+
71
+ def counter_value(counter_name, with_tags: nil)
72
+ stats = InstrumentAllTheThings.stat_reporter.emitted_values[:count][counter_name]
73
+ if with_tags && !stats.empty?
74
+ stats = stats.select do |s|
75
+ with_tags.all?{|t| s[:tags].include?(t) }
76
+ end
77
+ end
78
+ stats.inject(0){|l, n| l + n[:args][0] }
79
+ end
80
+
81
+ def flush_traces
82
+ Datadog.tracer&.writer&.worker&.flush_data
83
+ end
84
+
85
+ def emitted_spans(filtered_by: nil)
86
+ sleep 0.01
87
+ traces = InstrumentAllTheThings::Testing::TraceTracker.tracker.traces.map(&:dup)
88
+ if filtered_by
89
+ filtered_by.transform_keys!(&:to_s)
90
+ traces.select! { |t| filtered_by < t }
91
+ end
92
+
93
+ traces
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'datadog/statsd'
4
+
5
+ module InstrumentAllTheThings
6
+ module Testing
7
+ class StatTracker < Clients::StatReporter::DataDog
8
+ attr_reader :emitted_values
9
+ %i[
10
+ count
11
+ distribution
12
+ gauge
13
+ histogram
14
+ set
15
+ time
16
+ timing
17
+ ].each do |meth|
18
+ define_method(meth) do |*args, **kwargs, &blk|
19
+ @emitted_values[meth][args[0]] << {
20
+ args: args[1..-1],
21
+ tags: kwargs.fetch(:tags, []),
22
+ kwargs: kwargs,
23
+ }
24
+
25
+ super(*args, **kwargs, &blk)
26
+ end
27
+ end
28
+
29
+ def initialize(*args, **kwargs, &blk)
30
+ super
31
+ reset!
32
+ end
33
+
34
+ def reset!
35
+ @emitted_values = Hash.new do |h, k|
36
+ h[k] = Hash.new do |h2, k2|
37
+ h2[k2] = []
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InstrumentAllTheThings
4
+ module Testing
5
+ class TraceTracker
6
+ attr_reader :traces
7
+
8
+ def self.tracker
9
+ @tracker ||= new
10
+ end
11
+
12
+ def initialize
13
+ reset!
14
+ end
15
+
16
+ def reset!
17
+ @traces = []
18
+ end
19
+
20
+ def <<(val)
21
+ @traces = @traces.concat(MessagePack.load(val[:body]).flatten)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InstrumentAllTheThings
4
+ VERSION = '1.0.4'
5
+ end
Binary file
metadata ADDED
@@ -0,0 +1,227 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: instrument_all_the_things
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Brian Malinconico
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ddtrace
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dogstatsd-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: benchmark-ips
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Wrappers to make instrumentation of methods easy and pleasant to read
140
+ email:
141
+ - bmalinconico@terminus.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".drone.yml"
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - ".rubocop.yml"
150
+ - ".ruby-version"
151
+ - ".travis.yml"
152
+ - Gemfile
153
+ - Gemfile.lock
154
+ - README.md
155
+ - Rakefile
156
+ - bin/console
157
+ - bin/setup
158
+ - instrument_all_the_things.gemspec
159
+ - lib/instrument_all_the_things.rb
160
+ - lib/instrument_all_the_things/clients/stat_reporter/datadog.rb
161
+ - lib/instrument_all_the_things/clients/tracer/blackhole.rb
162
+ - lib/instrument_all_the_things/context.rb
163
+ - lib/instrument_all_the_things/helpers.rb
164
+ - lib/instrument_all_the_things/instrumentors/all.rb
165
+ - lib/instrument_all_the_things/instrumentors/error_logging.rb
166
+ - lib/instrument_all_the_things/instrumentors/execution_count_and_timing.rb
167
+ - lib/instrument_all_the_things/instrumentors/gc_stats.rb
168
+ - lib/instrument_all_the_things/instrumentors/tracing.rb
169
+ - lib/instrument_all_the_things/method_instrumentor.rb
170
+ - lib/instrument_all_the_things/method_proxy.rb
171
+ - lib/instrument_all_the_things/testing/rspec_matchers.rb
172
+ - lib/instrument_all_the_things/testing/stat_tracker.rb
173
+ - lib/instrument_all_the_things/testing/trace_tracker.rb
174
+ - lib/instrument_all_the_things/version.rb
175
+ - logo.jpg
176
+ - vendor/cache/ast-2.4.0.gem
177
+ - vendor/cache/benchmark-ips-2.7.2.gem
178
+ - vendor/cache/coderay-1.1.2.gem
179
+ - vendor/cache/ddtrace-0.34.0.gem
180
+ - vendor/cache/diff-lcs-1.3.gem
181
+ - vendor/cache/docile-1.3.2.gem
182
+ - vendor/cache/dogstatsd-ruby-4.7.0.gem
183
+ - vendor/cache/jaro_winkler-1.5.4.gem
184
+ - vendor/cache/method_source-0.9.2.gem
185
+ - vendor/cache/msgpack-1.3.3.gem
186
+ - vendor/cache/parallel-1.19.1.gem
187
+ - vendor/cache/parser-2.7.0.2.gem
188
+ - vendor/cache/pry-0.12.2.gem
189
+ - vendor/cache/rainbow-3.0.0.gem
190
+ - vendor/cache/rake-10.5.0.gem
191
+ - vendor/cache/rexml-3.2.4.gem
192
+ - vendor/cache/rspec-3.9.0.gem
193
+ - vendor/cache/rspec-core-3.9.1.gem
194
+ - vendor/cache/rspec-expectations-3.9.0.gem
195
+ - vendor/cache/rspec-mocks-3.9.1.gem
196
+ - vendor/cache/rspec-support-3.9.2.gem
197
+ - vendor/cache/rubocop-0.80.0.gem
198
+ - vendor/cache/ruby-progressbar-1.10.1.gem
199
+ - vendor/cache/simplecov-0.18.1.gem
200
+ - vendor/cache/simplecov-html-0.11.0.gem
201
+ - vendor/cache/unicode-display_width-1.6.1.gem
202
+ homepage: https://github.com/GetTerminus/instrument-all-the-things
203
+ licenses: []
204
+ metadata:
205
+ allowed_push_host: https://www.rubygems.org
206
+ homepage_uri: https://github.com/GetTerminus/instrument-all-the-things
207
+ source_code_uri: https://github.com/GetTerminus/instrument-all-the-things
208
+ post_install_message:
209
+ rdoc_options: []
210
+ require_paths:
211
+ - lib
212
+ required_ruby_version: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ version: '0'
217
+ required_rubygems_version: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ requirements: []
223
+ rubygems_version: 3.0.1
224
+ signing_key:
225
+ specification_version: 4
226
+ summary: Make instrumentation with DataDog easy peasy
227
+ test_files: []