scout_apm 3.0.0.pre13 → 3.0.0.pre14

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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/scout_apm.rb +20 -10
  3. data/lib/scout_apm/agent.rb +114 -319
  4. data/lib/scout_apm/agent/exit_handler.rb +66 -0
  5. data/lib/scout_apm/agent/preconditions.rb +69 -0
  6. data/lib/scout_apm/agent_context.rb +234 -0
  7. data/lib/scout_apm/app_server_load.rb +24 -14
  8. data/lib/scout_apm/background_job_integrations/resque.rb +7 -8
  9. data/lib/scout_apm/background_job_integrations/sidekiq.rb +2 -2
  10. data/lib/scout_apm/background_recorder.rb +8 -3
  11. data/lib/scout_apm/background_worker.rb +14 -7
  12. data/lib/scout_apm/config.rb +35 -26
  13. data/lib/scout_apm/context.rb +11 -4
  14. data/lib/scout_apm/db_query_metric_set.rb +17 -5
  15. data/lib/scout_apm/debug.rb +1 -1
  16. data/lib/scout_apm/environment.rb +10 -14
  17. data/lib/scout_apm/framework_integrations/sinatra.rb +1 -1
  18. data/lib/scout_apm/git_revision.rb +13 -8
  19. data/lib/scout_apm/histogram.rb +1 -1
  20. data/lib/scout_apm/instant/middleware.rb +7 -7
  21. data/lib/scout_apm/instant_reporting.rb +7 -7
  22. data/lib/scout_apm/instrument_manager.rb +87 -0
  23. data/lib/scout_apm/instruments/action_controller_rails_2.rb +12 -7
  24. data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +17 -12
  25. data/lib/scout_apm/instruments/action_view.rb +11 -7
  26. data/lib/scout_apm/instruments/active_record.rb +25 -11
  27. data/lib/scout_apm/instruments/elasticsearch.rb +10 -6
  28. data/lib/scout_apm/instruments/grape.rb +12 -8
  29. data/lib/scout_apm/instruments/http_client.rb +10 -6
  30. data/lib/scout_apm/instruments/influxdb.rb +10 -6
  31. data/lib/scout_apm/instruments/middleware_detailed.rb +11 -5
  32. data/lib/scout_apm/instruments/middleware_summary.rb +11 -5
  33. data/lib/scout_apm/instruments/mongoid.rb +10 -5
  34. data/lib/scout_apm/instruments/moped.rb +11 -6
  35. data/lib/scout_apm/instruments/net_http.rb +10 -6
  36. data/lib/scout_apm/instruments/percentile_sampler.rb +8 -6
  37. data/lib/scout_apm/instruments/process/process_cpu.rb +8 -4
  38. data/lib/scout_apm/instruments/process/process_memory.rb +15 -10
  39. data/lib/scout_apm/instruments/rails_router.rb +12 -6
  40. data/lib/scout_apm/instruments/redis.rb +10 -6
  41. data/lib/scout_apm/instruments/samplers.rb +11 -0
  42. data/lib/scout_apm/instruments/sinatra.rb +5 -4
  43. data/lib/scout_apm/layaway.rb +21 -20
  44. data/lib/scout_apm/layaway_file.rb +8 -3
  45. data/lib/scout_apm/layer.rb +3 -3
  46. data/lib/scout_apm/layer_converters/converter_base.rb +6 -7
  47. data/lib/scout_apm/layer_converters/database_converter.rb +1 -1
  48. data/lib/scout_apm/layer_converters/histograms.rb +2 -2
  49. data/lib/scout_apm/layer_converters/slow_job_converter.rb +4 -3
  50. data/lib/scout_apm/layer_converters/slow_request_converter.rb +5 -4
  51. data/lib/scout_apm/logger.rb +143 -0
  52. data/lib/scout_apm/middleware.rb +7 -9
  53. data/lib/scout_apm/periodic_work.rb +28 -0
  54. data/lib/scout_apm/reporter.rb +14 -8
  55. data/lib/scout_apm/reporting.rb +135 -0
  56. data/lib/scout_apm/request_manager.rb +4 -6
  57. data/lib/scout_apm/serializers/payload_serializer.rb +1 -1
  58. data/lib/scout_apm/slow_job_policy.rb +6 -2
  59. data/lib/scout_apm/slow_job_record.rb +5 -5
  60. data/lib/scout_apm/slow_request_policy.rb +6 -2
  61. data/lib/scout_apm/slow_transaction.rb +5 -5
  62. data/lib/scout_apm/store.rb +22 -16
  63. data/lib/scout_apm/synchronous_recorder.rb +7 -3
  64. data/lib/scout_apm/tasks/doctor.rb +75 -0
  65. data/lib/scout_apm/tasks/support.rb +22 -0
  66. data/lib/scout_apm/tracer.rb +5 -5
  67. data/lib/scout_apm/tracked_request.rb +43 -19
  68. data/lib/scout_apm/utils/active_record_metric_name.rb +66 -8
  69. data/lib/scout_apm/utils/backtrace_parser.rb +1 -1
  70. data/lib/scout_apm/utils/installed_gems.rb +7 -3
  71. data/lib/scout_apm/utils/klass_helper.rb +8 -2
  72. data/lib/scout_apm/utils/scm.rb +1 -1
  73. data/lib/scout_apm/utils/sql_sanitizer.rb +3 -3
  74. data/lib/scout_apm/version.rb +1 -1
  75. data/lib/tasks/doctor.rake +11 -0
  76. data/scout_apm.gemspec +1 -0
  77. data/test/test_helper.rb +17 -2
  78. data/test/unit/agent_test.rb +1 -54
  79. data/test/unit/config_test.rb +9 -5
  80. data/test/unit/context_test.rb +4 -4
  81. data/test/unit/db_query_metric_set_test.rb +11 -4
  82. data/test/unit/fake_store_test.rb +1 -1
  83. data/test/unit/git_revision_test.rb +3 -3
  84. data/test/unit/instruments/net_http_test.rb +2 -1
  85. data/test/unit/instruments/percentile_sampler_test.rb +5 -9
  86. data/test/unit/layaway_test.rb +10 -5
  87. data/test/unit/layer_converters/metric_converter_test.rb +2 -2
  88. data/test/unit/slow_request_policy_test.rb +7 -3
  89. data/test/unit/sql_sanitizer_test.rb +0 -6
  90. data/test/unit/store_test.rb +11 -8
  91. data/test/unit/utils/active_record_metric_name_test.rb +45 -7
  92. metadata +27 -5
  93. data/lib/scout_apm/agent/logging.rb +0 -74
  94. data/lib/scout_apm/agent/reporting.rb +0 -129
  95. data/lib/scout_apm/utils/null_logger.rb +0 -13
@@ -1,25 +1,29 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class Elasticsearch
4
- attr_reader :logger
4
+ attr_reader :context
5
5
 
6
- def initalize(logger=ScoutApm::Agent.instance.logger)
7
- @logger = logger
6
+ def initialize(context)
7
+ @context = context
8
8
  @installed = false
9
9
  end
10
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
11
15
  def installed?
12
16
  @installed
13
17
  end
14
18
 
15
19
  def install
16
- @installed = true
17
-
18
20
  if defined?(::Elasticsearch) &&
19
21
  defined?(::Elasticsearch::Transport) &&
20
22
  defined?(::Elasticsearch::Transport::Client)
21
23
 
22
- ScoutApm::Agent.instance.logger.info "Instrumenting Elasticsearch"
24
+ @installed = true
25
+
26
+ logger.info "Instrumenting Elasticsearch"
23
27
 
24
28
  ::Elasticsearch::Transport::Client.class_eval do
25
29
  include ScoutApm::Tracer
@@ -1,22 +1,26 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class Grape
4
- attr_reader :logger
4
+ attr_reader :context
5
5
 
6
- def initalize(logger=ScoutApm::Agent.instance.logger)
7
- @logger = logger
6
+ def initialize(context)
7
+ @context = context
8
8
  @installed = false
9
9
  end
10
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
11
15
  def installed?
12
16
  @installed
13
17
  end
14
18
 
15
19
  def install
16
- @installed = true
17
-
18
20
  if defined?(::Grape) && defined?(::Grape::Endpoint)
19
- ScoutApm::Agent.instance.logger.info "Instrumenting Grape::Endpoint"
21
+ @installed = true
22
+
23
+ logger.info "Instrumenting Grape::Endpoint"
20
24
 
21
25
  ::Grape::Endpoint.class_eval do
22
26
  include ScoutApm::Instruments::GrapeEndpointInstruments
@@ -33,7 +37,7 @@ module ScoutApm
33
37
  request = ::Grape::Request.new(env || args.first)
34
38
  req = ScoutApm::RequestManager.lookup
35
39
 
36
- path = ScoutApm::Agent.instance.config.value("uri_reporting") == 'path' ? request.path : request.fullpath
40
+ path = ScoutApm::Agent.instance.context.config.value("uri_reporting") == 'path' ? request.path : request.fullpath
37
41
  req.annotate_request(:uri => path)
38
42
 
39
43
  # IP Spoofing Protection can throw an exception, just move on w/o remote ip
@@ -50,7 +54,7 @@ module ScoutApm
50
54
  self.options[:path].first,
51
55
  ].compact.map{ |n| n.to_s }.join("/")
52
56
  rescue => e
53
- ScoutApm::Agent.instance.logger.info("Error getting Grape Endpoint Name. Error: #{e.message}. Options: #{self.options.inspect}")
57
+ logger.info("Error getting Grape Endpoint Name. Error: #{e.message}. Options: #{self.options.inspect}")
54
58
  name = "Grape/Unknown"
55
59
  end
56
60
 
@@ -1,22 +1,26 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class HttpClient
4
- attr_reader :logger
4
+ attr_reader :context
5
5
 
6
- def initalize(logger=ScoutApm::Agent.instance.logger)
7
- @logger = logger
6
+ def initialize(context)
7
+ @context = context
8
8
  @installed = false
9
9
  end
10
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
11
15
  def installed?
12
16
  @installed
13
17
  end
14
18
 
15
19
  def install
16
- @installed = true
17
-
18
20
  if defined?(::HTTPClient)
19
- ScoutApm::Agent.instance.logger.info "Instrumenting HTTPClient"
21
+ @installed = true
22
+
23
+ logger.info "Instrumenting HTTPClient"
20
24
 
21
25
  ::HTTPClient.class_eval do
22
26
  include ScoutApm::Tracer
@@ -1,22 +1,26 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class InfluxDB
4
- attr_reader :logger
4
+ attr_reader :context
5
5
 
6
- def initalize(logger=ScoutApm::Agent.instance.logger)
7
- @logger = logger
6
+ def initialize(context)
7
+ @context = context
8
8
  @installed = false
9
9
  end
10
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
11
15
  def installed?
12
16
  @installed
13
17
  end
14
18
 
15
19
  def install
16
- @installed = true
17
-
18
20
  if defined?(::InfluxDB)
19
- ScoutApm::Agent.instance.logger.debug "Instrumenting InfluxDB"
21
+ @installed = true
22
+
23
+ logger.debug "Instrumenting InfluxDB"
20
24
 
21
25
  ::InfluxDB::Client.class_eval do
22
26
  include ScoutApm::Tracer
@@ -9,22 +9,28 @@
9
9
  module ScoutApm
10
10
  module Instruments
11
11
  class MiddlewareDetailed
12
- def initalize(logger=ScoutApm::Agent.instance.logger)
13
- @logger = logger
12
+ attr_reader :context
13
+
14
+ def initialize(context)
15
+ @context = context
14
16
  @installed = false
15
17
  end
16
18
 
19
+ def logger
20
+ context.logger
21
+ end
22
+
17
23
  def installed?
18
24
  @installed
19
25
  end
20
26
 
21
27
  def install
22
- @installed = true
23
-
24
28
  if defined?(ActionDispatch) && defined?(ActionDispatch::MiddlewareStack) && defined?(ActionDispatch::MiddlewareStack::Middleware)
29
+ @installed = true
30
+
25
31
  ActionDispatch::MiddlewareStack::Middleware.class_eval do
26
32
  def build(app)
27
- ScoutApm::Agent.instance.logger.info("Building Middleware #{klass.name}")
33
+ logger.info("Building Middleware #{klass.name}")
28
34
  new_mw = klass.new(app, *args, &block)
29
35
  MiddlewareWrapper.new(new_mw, klass.name)
30
36
  end
@@ -6,20 +6,26 @@
6
6
  module ScoutApm
7
7
  module Instruments
8
8
  class MiddlewareSummary
9
- def initalize(logger=ScoutApm::Agent.instance.logger)
10
- @logger = logger
9
+ attr_reader :context
10
+
11
+ def initialize(context)
12
+ @context = context
11
13
  @installed = false
12
14
  end
13
15
 
16
+ def logger
17
+ context.logger
18
+ end
19
+
14
20
  def installed?
15
21
  @installed
16
22
  end
17
23
 
18
24
  def install
19
- @installed = true
20
-
21
25
  if defined?(ActionDispatch) && defined?(ActionDispatch::MiddlewareStack)
22
- ScoutApm::Agent.instance.logger.info("Instrumenting Middleware")
26
+ @installed = true
27
+
28
+ logger.info("Instrumenting Middleware")
23
29
  ActionDispatch::MiddlewareStack.class_eval do
24
30
  def build_with_scout_instruments(app = nil, &block)
25
31
  mw_stack = build_without_scout_instruments(app) { block.call if block }
@@ -1,13 +1,17 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class Mongoid
4
- attr_reader :logger
4
+ attr_reader :context
5
5
 
6
- def initalize(logger=ScoutApm::Agent.instance.logger)
7
- @logger = logger
6
+ def initialize(context)
7
+ @context = context
8
8
  @installed = false
9
9
  end
10
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
11
15
  def installed?
12
16
  @installed
13
17
  end
@@ -17,7 +21,8 @@ module ScoutApm
17
21
 
18
22
  # Mongoid versions that use Moped should instrument Moped.
19
23
  if defined?(::Mongoid) and !defined?(::Moped)
20
- ScoutApm::Agent.instance.logger.info "Instrumenting Mongoid 2.x"
24
+ logger.info "Instrumenting Mongoid 2.x"
25
+ @installed = true
21
26
 
22
27
  ### OLD (2.x) mongoids
23
28
  if defined?(::Mongoid::Collection)
@@ -33,7 +38,7 @@ module ScoutApm
33
38
 
34
39
  ### 5.x Mongoid
35
40
  if (mongoid_v5? || mongoid_v6?) && defined?(::Mongoid::Contextual::Mongo)
36
- ScoutApm::Agent.instance.logger.info "Instrumenting Mongoid 5.x/6.x"
41
+ logger.info "Instrumenting Mongoid 5.x/6.x"
37
42
  # All the public methods from Mongoid::Contextual::Mongo.
38
43
  # TODO: Geo and MapReduce support (?). They are in other Contextual::* classes
39
44
  methods = [
@@ -1,22 +1,27 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class Moped
4
- attr_reader :logger
4
+ attr_reader :context
5
5
 
6
- def initalize(logger=ScoutApm::Agent.instance.logger)
7
- @logger = logger
6
+ def initialize(context)
7
+ @context = context
8
8
  @installed = false
9
9
  end
10
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
11
15
  def installed?
12
16
  @installed
13
17
  end
14
18
 
15
19
  def install
16
- @installed = true
17
-
18
20
  if defined?(::Moped)
19
- ScoutApm::Agent.instance.logger.info "Instrumenting Moped"
21
+ @installed = true
22
+
23
+ logger.info "Instrumenting Moped"
24
+
20
25
  ::Moped::Node.class_eval do
21
26
  include ScoutApm::Tracer
22
27
 
@@ -1,22 +1,26 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class NetHttp
4
- attr_reader :logger
4
+ attr_reader :context
5
5
 
6
- def initalize(logger=ScoutApm::Agent.instance.logger)
7
- @logger = logger
6
+ def initialize(context)
7
+ @context = context
8
8
  @installed = false
9
9
  end
10
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
11
15
  def installed?
12
16
  @installed
13
17
  end
14
18
 
15
19
  def install
16
- @installed = true
17
-
18
20
  if defined?(::Net) && defined?(::Net::HTTP)
19
- ScoutApm::Agent.instance.logger.info "Instrumenting Net::HTTP"
21
+ @installed = true
22
+
23
+ logger.info "Instrumenting Net::HTTP"
20
24
 
21
25
  ::Net::HTTP.class_eval do
22
26
  include ScoutApm::Tracer
@@ -18,14 +18,16 @@ module ScoutApm
18
18
  end
19
19
 
20
20
  class PercentileSampler
21
- attr_reader :logger
21
+ def initialize(context)
22
+ @context = context
23
+ end
22
24
 
23
- # A hash of { time => RequestHistograms }
24
- attr_reader :histograms
25
+ def histograms
26
+ @context.request_histograms_by_time
27
+ end
25
28
 
26
- def initialize(logger, histograms)
27
- @logger = logger
28
- @histograms = histograms
29
+ def logger
30
+ @context.logger
29
31
  end
30
32
 
31
33
  def human_name
@@ -2,14 +2,14 @@ module ScoutApm
2
2
  module Instruments
3
3
  module Process
4
4
  class ProcessCpu
5
- attr_reader :logger
6
5
  attr_reader :num_processors
7
6
  attr_accessor :last_run, :last_utime, :last_stime
7
+ attr_reader :context
8
8
 
9
+ def initialize(context)
10
+ @context = context
9
11
 
10
- def initialize(num_processors, logger)
11
- @num_processors = [num_processors, 1].compact.max
12
- @logger = logger
12
+ @num_processors = [context.environment.processors, 1].compact.max
13
13
 
14
14
  t = ::Process.times
15
15
  @last_run = Time.now
@@ -98,6 +98,10 @@ module ScoutApm
98
98
  self.last_utime = utime
99
99
  self.last_stime = stime
100
100
  end
101
+
102
+ def logger
103
+ context.logger
104
+ end
101
105
  end
102
106
  end
103
107
  end
@@ -2,23 +2,24 @@ module ScoutApm
2
2
  module Instruments
3
3
  module Process
4
4
  class ProcessMemory
5
- attr_reader :logger
6
-
7
- # Account for Darwin returning maxrss in bytes and Linux in KB. Used by the slow converters. Doesn't feel like this should go here though...more of a utility.
8
- def self.rss_to_mb(rss)
9
- rss.to_f/1024/(ScoutApm::Agent.instance.environment.os == 'darwin' ? 1024 : 1)
5
+ # Account for Darwin returning maxrss in bytes and Linux in KB. Used by
6
+ # the slow converters. Doesn't feel like this should go here
7
+ # though...more of a utility.
8
+ def rss_to_mb(rss)
9
+ kilobyte_adjust = @context.environment.os == 'darwin' ? 1024 : 1
10
+ rss.to_f / 1024 / kilobyte_adjust
10
11
  end
11
12
 
12
- def self.rss
13
+ def rss
13
14
  ::Process.rusage.maxrss
14
15
  end
15
16
 
16
- def self.rss_in_mb
17
+ def rss_in_mb
17
18
  rss_to_mb(rss)
18
19
  end
19
20
 
20
- def initialize(logger)
21
- @logger = logger
21
+ def initialize(context)
22
+ @context = context
22
23
  end
23
24
 
24
25
  def metric_type
@@ -46,7 +47,11 @@ module ScoutApm
46
47
  end
47
48
 
48
49
  def run
49
- self.class.rss_in_mb.tap { |res| logger.debug "#{human_name}: #{res.inspect}" }
50
+ rss_in_mb.tap { |res| logger.debug "#{human_name}: #{res.inspect}" }
51
+ end
52
+
53
+ def logger
54
+ @context.logger
50
55
  end
51
56
  end
52
57
  end
@@ -1,19 +1,25 @@
1
1
  module ScoutApm
2
2
  module Instruments
3
3
  class RailsRouter
4
- def initalize(logger=ScoutApm::Agent.instance.logger)
5
- @logger = logger
4
+ attr_reader :context
5
+
6
+ def initialize(context)
7
+ @context = context
6
8
  @installed = false
7
9
  end
8
10
 
11
+ def logger
12
+ context.logger
13
+ end
14
+
9
15
  def installed?
10
16
  @installed
11
17
  end
12
18
 
13
19
  def install
14
- @installed = true
15
-
16
20
  if defined?(ActionDispatch) && defined?(ActionDispatch::Routing) && defined?(ActionDispatch::Routing::RouteSet)
21
+ @installed = true
22
+
17
23
  ActionDispatch::Routing::RouteSet.class_eval do
18
24
  def call_with_scout_instruments(*args)
19
25
  req = ScoutApm::RequestManager.lookup
@@ -26,8 +32,8 @@ module ScoutApm
26
32
  end
27
33
  end
28
34
 
29
- alias call_without_scout_instruments call
30
- alias call call_with_scout_instruments
35
+ alias_method :call_without_scout_instruments, :call
36
+ alias_method :call, :call_with_scout_instruments
31
37
  end
32
38
  end
33
39
  end