scout_apm 1.4.3 → 1.4.4

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: e35b6c5c23a78e589b4756310047fb0bc7ac4adf
4
- data.tar.gz: 5489c84a0cd1a0f3df4ec85a54b9d6a8f34692b3
3
+ metadata.gz: 3f23c7ac5d4eb5fd3377ec8d9c4aa9f57a5fc356
4
+ data.tar.gz: 72c4e84ceeae582c401e30343c0f0594c79036cc
5
5
  SHA512:
6
- metadata.gz: 1786feaa5c35aa342e8d4e805d923754cb37de844f396cba10e66b56c341ea9facf9e8d8fec90c33ce23c3fda4fc062325c2adc7096ee7cf6a9a2bd3f0e31e33
7
- data.tar.gz: 85c19b4db97a36905e497db1c2e70bad95ab528d656db5f29378b55b53c5fdc256ce83bfa14f297bbdf47be21dacbbfcc999da7a55e6f78042d8707200c55b6d
6
+ metadata.gz: 7ae0882e14379a6a1d87923f20500fa9508cc8e63438788db0d9ee98ae773413a2f3a3d1aef9fee9977447cda1f10593f91de92837b8ee168e7a18c058b023ab
7
+ data.tar.gz: 93197ba1fdf634b6ccf399ba1e73363abc21d0604ae71f75537f5280e50480855c280b4f11690be2c32d8e780a85011d5f8ac3f49fe6e256a138c7b71c9e5ea6
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,8 @@
1
+ # 1.4.4
2
+
3
+ * Instrument Mongoid
4
+ * Instrument Redis
5
+
1
6
  # 1.4.3
2
7
 
3
8
  * Add a to_s call to have HTTPClient work with URI objects. Thanks to Nicolai for providing the change!
data/Rakefile CHANGED
@@ -8,3 +8,12 @@ task :test do
8
8
  Dir.glob('./test/**/*_test.rb').each { |file| require file }
9
9
  end
10
10
 
11
+
12
+ desc "IRB with this gem required"
13
+ task :console do
14
+ require 'irb'
15
+ require 'irb/completion'
16
+ require 'scout_apm'
17
+ ARGV.clear
18
+ IRB.start
19
+ end
data/lib/scout_apm.rb CHANGED
@@ -62,6 +62,7 @@ require 'scout_apm/instruments/net_http'
62
62
  require 'scout_apm/instruments/http_client'
63
63
  require 'scout_apm/instruments/moped'
64
64
  require 'scout_apm/instruments/mongoid'
65
+ require 'scout_apm/instruments/redis'
65
66
  require 'scout_apm/instruments/delayed_job'
66
67
  require 'scout_apm/instruments/active_record'
67
68
  require 'scout_apm/instruments/action_controller_rails_2'
@@ -253,6 +253,7 @@ module ScoutApm
253
253
  install_instrument(ScoutApm::Instruments::Mongoid)
254
254
  install_instrument(ScoutApm::Instruments::NetHttp)
255
255
  install_instrument(ScoutApm::Instruments::HttpClient)
256
+ install_instrument(ScoutApm::Instruments::Redis)
256
257
 
257
258
  if StackProf.respond_to?(:fake?) && StackProf.fake?
258
259
  logger.info 'StackProf not found - add `gem "stackprof"` to your Gemfile to enable advanced code profiling (only for Ruby 2.1+)'
@@ -266,6 +267,14 @@ module ScoutApm
266
267
  def install_instrument(instrument_klass)
267
268
  # Don't attempt to install the same instrument twice
268
269
  return if @installed_instruments.any? { |already_installed_instrument| instrument_klass === already_installed_instrument }
270
+
271
+ # Allow users to skip individual instruments via the config file
272
+ instrument_short_name = instrument_klass.name.split("::").last
273
+ if config.value("disabled_instruments").include?(instrument_short_name)
274
+ logger.info "Skipping Disabled Instrument: #{instrument_short_name} - To re-enable, change `disabled_instruments` key in scout_apm.yml"
275
+ return
276
+ end
277
+
269
278
  instance = instrument_klass.new
270
279
  @installed_instruments << instance
271
280
  instance.install
@@ -27,6 +27,7 @@ module ScoutApm
27
27
  'stackprof_interval' => 20000, # microseconds, 1000 = 1 millisecond, so 20k == 20 milliseconds
28
28
  'uri_reporting' => 'full_path',
29
29
  'report_format' => 'json',
30
+ 'disabled_instruments' => []
30
31
  }.freeze
31
32
 
32
33
  def initialize(config_path = nil)
@@ -22,11 +22,10 @@ module ScoutApm
22
22
  ::Mongoid::Collection.class_eval do
23
23
  include ScoutApm::Tracer
24
24
  (::Mongoid::Collections::Operations::ALL - [:<<, :[]]).each do |method|
25
- instrument_method method, :type => "MongoDB", :name => '#{@klass}/#{method}'
25
+ instrument_method method, :type => "MongoDB", :name => '#{@klass}/' + method.to_s
26
26
  end
27
27
  end
28
28
  end
29
-
30
29
  end
31
30
  end
32
31
  end
@@ -0,0 +1,39 @@
1
+ module ScoutApm
2
+ module Instruments
3
+ class Redis
4
+ attr_reader :logger
5
+
6
+ def initalize(logger=ScoutApm::Agent.instance.logger)
7
+ @logger = logger
8
+ @installed = false
9
+ end
10
+
11
+ def installed?
12
+ @installed
13
+ end
14
+
15
+ def install
16
+ @installed = true
17
+
18
+ if defined?(::Redis) && defined?(::Redis::Client)
19
+ ScoutApm::Agent.instance.logger.info "Instrumenting Redis"
20
+
21
+ ::Redis::Client.class_eval do
22
+ include ScoutApm::Tracer
23
+
24
+ def call_with_scout_instruments(*args, &block)
25
+ command = args.first.first rescue "Unknown"
26
+
27
+ self.class.instrument("Redis", command) do
28
+ call_without_scout_instruments(*args, &block)
29
+ end
30
+ end
31
+
32
+ alias_method :call_without_scout_instruments, :call
33
+ alias_method :call, :call_with_scout_instruments
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -44,33 +44,62 @@ module ScoutApm
44
44
  # Options:
45
45
  # type - "View" or "ActiveRecord" and similar
46
46
  # name - "users/show", "App#find"
47
- def instrument_method(method, options = {})
48
- ScoutApm::Agent.instance.logger.info "Instrumenting #{method}"
47
+ def instrument_method(method_name, options = {})
48
+ ScoutApm::Agent.instance.logger.info "Instrumenting #{method_name}"
49
49
  type = options[:type] || "Custom"
50
- name = options[:name] || "#{self.name}/#{method.to_s}"
50
+ name = options[:name] || "#{self.name}/#{method_name.to_s}"
51
51
 
52
- return if !instrumentable?(method) or instrumented?(method, type, name)
52
+ instrumented_name, uninstrumented_name = _determine_instrumented_name(method_name, type)
53
+
54
+ ScoutApm::Agent.instance.logger.info "Instrumenting #{instrumented_name}, #{uninstrumented_name}"
55
+
56
+ return if !_instrumentable?(method_name) or _instrumented?(instrumented_name, method_name)
53
57
 
54
58
  class_eval(
55
- instrumented_method_string(method, type, name, {:scope => options[:scope] }),
59
+ _instrumented_method_string(instrumented_name, uninstrumented_name, type, name, {:scope => options[:scope] }),
56
60
  __FILE__, __LINE__
57
61
  )
58
62
 
59
- alias_method _uninstrumented_method_name(method, type, name), method
60
- alias_method method, _instrumented_method_name(method, type, name)
63
+ alias_method uninstrumented_name, method_name
64
+ alias_method method_name, instrumented_name
61
65
  end
62
66
 
63
67
  private
64
68
 
65
- def instrumented_method_string(method, type, name, options={})
69
+ def _determine_instrumented_name(method_name, type)
70
+ inst = _find_unused_method_name { _instrumented_method_name(method_name, type) }
71
+ uninst = _find_unused_method_name { _uninstrumented_method_name(method_name, type) }
72
+
73
+ return inst, uninst
74
+ end
75
+
76
+ def _find_unused_method_name
77
+ raw_name = name = yield
78
+
79
+ i = 0
80
+ while method_defined?(name) && i < 100
81
+ i += 1
82
+ name = "#{raw_name}_#{i}"
83
+ end
84
+ name
85
+ end
86
+
87
+ def _instrumented_method_string(instrumented_name, uninstrumented_name, type, name, options={})
66
88
  klass = (self === Module) ? "self" : "self.class"
67
89
  method_str = <<-EOF
68
- def #{_instrumented_method_name(method, type, name)}(*args, &block)
90
+ def #{instrumented_name}(*args, &block)
91
+ name = begin
92
+ "#{name}"
93
+ rescue => e
94
+ ScoutApm::Agent.instance.logger.error("Error raised while interpreting instrumented name: %s, %s" % ['#{name}', e.message])
95
+ "Unknown"
96
+ end
97
+
69
98
  #{klass}.instrument( "#{type}",
70
- "#{name}",
99
+ name,
71
100
  {:scope => #{options[:scope] || false}}
72
101
  ) do
73
- #{_uninstrumented_method_name(method, type, name)}(*args, &block)
102
+ #{uninstrumented_name}(*args, &block)
74
103
  end
75
104
  end
76
105
  EOF
@@ -79,29 +108,29 @@ module ScoutApm
79
108
  end
80
109
 
81
110
  # The method must exist to be instrumented.
82
- def instrumentable?(method)
83
- exists = method_defined?(method) || private_method_defined?(method)
84
- ScoutApm::Agent.instance.logger.warn "The method [#{self.name}##{method}] does not exist and will not be instrumented" unless exists
111
+ def _instrumentable?(method_name)
112
+ exists = method_defined?(method_name) || private_method_defined?(method_name)
113
+ ScoutApm::Agent.instance.logger.warn "The method [#{self.name}##{method_name}] does not exist and will not be instrumented" unless exists
85
114
  exists
86
115
  end
87
116
 
88
117
  # +True+ if the method is already instrumented.
89
- def instrumented?(method, type, name)
90
- instrumented = method_defined?(_instrumented_method_name(method, type, name))
91
- ScoutApm::Agent.instance.logger.warn("The method [#{self.name}##{method}] has already been instrumented") if instrumented
118
+ def _instrumented?(instrumented_name, method_name)
119
+ instrumented = method_defined?(instrumented_name)
120
+ ScoutApm::Agent.instance.logger.warn("The method [#{self.name}##{method_name}] has already been instrumented") if instrumented
92
121
  instrumented
93
122
  end
94
123
 
95
124
  # given a method and a metric, this method returns the
96
125
  # untraced alias of the method name
97
- def _uninstrumented_method_name(method, type, name)
98
- "#{_sanitize_name(method)}_without_scout_instrument_#{_sanitize_name(name)}"
126
+ def _uninstrumented_method_name(method_name, type)
127
+ "#{_sanitize_name(method_name)}_without_scout_instrument"
99
128
  end
100
129
 
101
130
  # given a method and a metric, this method returns the traced
102
131
  # alias of the method name
103
- def _instrumented_method_name(method, type, name)
104
- "#{_sanitize_name(method)}_with_scout_instrument_#{_sanitize_name(name)}"
132
+ def _instrumented_method_name(method_name, type)
133
+ "#{_sanitize_name(method_name)}_with_scout_instrument"
105
134
  end
106
135
 
107
136
  # Method names like +any?+ or +replace!+ contain a trailing character that would break when
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "1.4.3"
2
+ VERSION = "1.4.4"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scout_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Haynes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-03-02 00:00:00.000000000 Z
12
+ date: 2016-03-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -101,6 +101,7 @@ files:
101
101
  - lib/scout_apm/instruments/process/process_cpu.rb
102
102
  - lib/scout_apm/instruments/process/process_memory.rb
103
103
  - lib/scout_apm/instruments/rails_router.rb
104
+ - lib/scout_apm/instruments/redis.rb
104
105
  - lib/scout_apm/instruments/sinatra.rb
105
106
  - lib/scout_apm/layaway.rb
106
107
  - lib/scout_apm/layaway_file.rb