scout_apm 3.0.0.pre27 → 4.0.3

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 (131) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/test.yml +49 -0
  3. data/.gitignore +1 -1
  4. data/.rubocop.yml +5 -5
  5. data/.travis.yml +19 -14
  6. data/CHANGELOG.markdown +139 -4
  7. data/Gemfile +1 -7
  8. data/README.markdown +13 -4
  9. data/Rakefile +1 -1
  10. data/ext/allocations/allocations.c +2 -0
  11. data/gems/README.md +28 -0
  12. data/gems/octoshark.gemfile +4 -0
  13. data/gems/rails3.gemfile +5 -0
  14. data/gems/rails4.gemfile +4 -0
  15. data/gems/rails5.gemfile +4 -0
  16. data/gems/rails6.gemfile +4 -0
  17. data/lib/scout_apm.rb +38 -9
  18. data/lib/scout_apm/agent.rb +29 -10
  19. data/lib/scout_apm/agent/exit_handler.rb +0 -1
  20. data/lib/scout_apm/agent_context.rb +22 -3
  21. data/lib/scout_apm/app_server_load.rb +7 -2
  22. data/lib/scout_apm/attribute_arranger.rb +0 -2
  23. data/lib/scout_apm/auto_instrument.rb +5 -0
  24. data/lib/scout_apm/auto_instrument/instruction_sequence.rb +31 -0
  25. data/lib/scout_apm/auto_instrument/layer.rb +23 -0
  26. data/lib/scout_apm/auto_instrument/parser.rb +27 -0
  27. data/lib/scout_apm/auto_instrument/rails.rb +175 -0
  28. data/lib/scout_apm/background_job_integrations/legacy_sneakers.rb +55 -0
  29. data/lib/scout_apm/background_job_integrations/que.rb +134 -0
  30. data/lib/scout_apm/background_job_integrations/resque.rb +6 -2
  31. data/lib/scout_apm/background_job_integrations/shoryuken.rb +124 -0
  32. data/lib/scout_apm/background_job_integrations/sidekiq.rb +5 -19
  33. data/lib/scout_apm/background_job_integrations/sneakers.rb +87 -0
  34. data/lib/scout_apm/config.rb +45 -8
  35. data/lib/scout_apm/detailed_trace.rb +217 -0
  36. data/lib/scout_apm/environment.rb +19 -1
  37. data/lib/scout_apm/error.rb +27 -0
  38. data/lib/scout_apm/error_service.rb +32 -0
  39. data/lib/scout_apm/error_service/error_buffer.rb +39 -0
  40. data/lib/scout_apm/error_service/error_record.rb +211 -0
  41. data/lib/scout_apm/error_service/ignored_exceptions.rb +66 -0
  42. data/lib/scout_apm/error_service/middleware.rb +32 -0
  43. data/lib/scout_apm/error_service/notifier.rb +33 -0
  44. data/lib/scout_apm/error_service/payload.rb +47 -0
  45. data/lib/scout_apm/error_service/periodic_work.rb +17 -0
  46. data/lib/scout_apm/error_service/railtie.rb +11 -0
  47. data/lib/scout_apm/error_service/sidekiq.rb +80 -0
  48. data/lib/scout_apm/extensions/transaction_callback_payload.rb +1 -1
  49. data/lib/scout_apm/fake_store.rb +3 -0
  50. data/lib/scout_apm/framework_integrations/rails_2.rb +2 -1
  51. data/lib/scout_apm/framework_integrations/rails_3_or_4.rb +3 -1
  52. data/lib/scout_apm/git_revision.rb +6 -3
  53. data/lib/scout_apm/instant/middleware.rb +2 -1
  54. data/lib/scout_apm/instrument_manager.rb +9 -7
  55. data/lib/scout_apm/instruments/action_controller_rails_2.rb +3 -1
  56. data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +56 -55
  57. data/lib/scout_apm/instruments/action_view.rb +122 -26
  58. data/lib/scout_apm/instruments/active_record.rb +66 -18
  59. data/lib/scout_apm/instruments/http.rb +48 -0
  60. data/lib/scout_apm/instruments/memcached.rb +43 -0
  61. data/lib/scout_apm/instruments/mongoid.rb +9 -4
  62. data/lib/scout_apm/instruments/net_http.rb +8 -1
  63. data/lib/scout_apm/instruments/typhoeus.rb +88 -0
  64. data/lib/scout_apm/job_record.rb +4 -2
  65. data/lib/scout_apm/layaway_file.rb +4 -0
  66. data/lib/scout_apm/layer.rb +6 -57
  67. data/lib/scout_apm/layer_children_set.rb +9 -8
  68. data/lib/scout_apm/layer_converters/converter_base.rb +15 -30
  69. data/lib/scout_apm/layer_converters/slow_job_converter.rb +12 -2
  70. data/lib/scout_apm/layer_converters/slow_request_converter.rb +14 -4
  71. data/lib/scout_apm/layer_converters/trace_converter.rb +184 -0
  72. data/lib/scout_apm/limited_layer.rb +0 -7
  73. data/lib/scout_apm/metric_stats.rb +0 -8
  74. data/lib/scout_apm/middleware.rb +1 -1
  75. data/lib/scout_apm/periodic_work.rb +19 -0
  76. data/lib/scout_apm/remote/message.rb +4 -0
  77. data/lib/scout_apm/remote/server.rb +13 -1
  78. data/lib/scout_apm/reporter.rb +8 -3
  79. data/lib/scout_apm/reporting.rb +2 -1
  80. data/lib/scout_apm/request_histograms.rb +8 -0
  81. data/lib/scout_apm/serializers/app_server_load_serializer.rb +4 -0
  82. data/lib/scout_apm/serializers/directive_serializer.rb +4 -0
  83. data/lib/scout_apm/serializers/payload_serializer.rb +2 -2
  84. data/lib/scout_apm/serializers/payload_serializer_to_json.rb +30 -15
  85. data/lib/scout_apm/slow_job_record.rb +5 -1
  86. data/lib/scout_apm/slow_policy/age_policy.rb +33 -0
  87. data/lib/scout_apm/slow_policy/percent_policy.rb +22 -0
  88. data/lib/scout_apm/slow_policy/percentile_policy.rb +24 -0
  89. data/lib/scout_apm/slow_policy/policy.rb +21 -0
  90. data/lib/scout_apm/slow_policy/speed_policy.rb +16 -0
  91. data/lib/scout_apm/slow_request_policy.rb +18 -77
  92. data/lib/scout_apm/slow_transaction.rb +3 -1
  93. data/lib/scout_apm/store.rb +0 -1
  94. data/lib/scout_apm/tracked_request.rb +39 -30
  95. data/lib/scout_apm/utils/backtrace_parser.rb +3 -0
  96. data/lib/scout_apm/utils/marshal_logging.rb +90 -0
  97. data/lib/scout_apm/utils/sql_sanitizer.rb +10 -1
  98. data/lib/scout_apm/utils/sql_sanitizer_regex.rb +8 -1
  99. data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +6 -0
  100. data/lib/scout_apm/utils/unique_id.rb +27 -0
  101. data/lib/scout_apm/version.rb +1 -1
  102. data/scout_apm.gemspec +13 -7
  103. data/test/test_helper.rb +2 -2
  104. data/test/unit/agent_context_test.rb +29 -0
  105. data/test/unit/auto_instrument/assignments-instrumented.rb +31 -0
  106. data/test/unit/auto_instrument/assignments.rb +31 -0
  107. data/test/unit/auto_instrument/controller-ast.txt +57 -0
  108. data/test/unit/auto_instrument/controller-instrumented.rb +49 -0
  109. data/test/unit/auto_instrument/controller.rb +49 -0
  110. data/test/unit/auto_instrument/rescue_from-instrumented.rb +13 -0
  111. data/test/unit/auto_instrument/rescue_from.rb +13 -0
  112. data/test/unit/auto_instrument_test.rb +54 -0
  113. data/test/unit/environment_test.rb +2 -2
  114. data/test/unit/error_service/error_buffer_test.rb +25 -0
  115. data/test/unit/error_service/ignored_exceptions_test.rb +49 -0
  116. data/test/unit/instruments/active_record_test.rb +40 -0
  117. data/test/unit/layer_children_set_test.rb +9 -0
  118. data/test/unit/request_histograms_test.rb +17 -0
  119. data/test/unit/serializers/payload_serializer_test.rb +39 -5
  120. data/test/unit/slow_request_policy_test.rb +41 -13
  121. data/test/unit/sql_sanitizer_test.rb +78 -0
  122. metadata +101 -62
  123. data/ext/stacks/extconf.rb +0 -37
  124. data/ext/stacks/scout_atomics.h +0 -86
  125. data/ext/stacks/stacks.c +0 -814
  126. data/lib/scout_apm/slow_job_policy.rb +0 -111
  127. data/lib/scout_apm/trace_compactor.rb +0 -312
  128. data/lib/scout_apm/utils/fake_stacks.rb +0 -88
  129. data/test/unit/instruments/active_record_instruments_test.rb +0 -5
  130. data/test/unit/slow_job_policy_test.rb +0 -6
  131. data/tester.rb +0 -53
@@ -0,0 +1,134 @@
1
+ module ScoutApm
2
+ module BackgroundJobIntegrations
3
+ class Que
4
+
5
+ UNKNOWN_CLASS_PLACEHOLDER = 'UnknownJob'.freeze
6
+ ACTIVE_JOB_KLASS = 'ActiveJob::QueueAdapters::QueAdapter::JobWrapper'.freeze
7
+ UNKNOWN_QUEUE_PLACEHOLDER = 'UnknownQueue'.freeze
8
+
9
+ attr_reader :logger
10
+
11
+ def name
12
+ :que
13
+ end
14
+
15
+ def present?
16
+ if defined?(::Que) && File.basename($PROGRAM_NAME).start_with?('que')
17
+ # 0.x releases used "Version" constant.
18
+ # 1.x releases used "VERSION" constant.
19
+ return defined?(::Que::Version)
20
+ end
21
+ end
22
+
23
+ def forking?
24
+ false
25
+ end
26
+
27
+ def install
28
+ install_tracer
29
+ install_worker
30
+ install_job
31
+ end
32
+
33
+ def install_tracer
34
+ ::Que::Job.class_eval do
35
+ include ScoutApm::Tracer
36
+ end
37
+ end
38
+
39
+ def install_worker
40
+ ::Que::Worker.class_eval do
41
+ def initialize_with_scout(*args)
42
+ agent = ::ScoutApm::Agent.instance
43
+ agent.start
44
+ initialize_without_scout(*args)
45
+ end
46
+
47
+ alias_method :initialize_without_scout, :initialize
48
+ alias_method :initialize, :initialize_with_scout
49
+ end
50
+ end
51
+
52
+ def install_job
53
+ ::Que::Job.class_eval do
54
+ # attrs = {
55
+ # "queue"=>"",
56
+ # "priority"=>100,
57
+ # "run_at"=>2018-12-19 15:12:32 -0700,
58
+ # "job_id"=>4,
59
+ # "job_class"=>"ExampleJob",
60
+ # "args"=>[{"key"=>"value"}],
61
+ # "error_count"=>0
62
+ # }
63
+ #
64
+ # With ActiveJob, v0.14.3:
65
+ # attrs = {
66
+ # "queue"=>"",
67
+ # "priority"=>100,
68
+ # "run_at"=>2018-12-19 15:29:18 -0700,
69
+ # "job_id"=>6,
70
+ # "job_class"=>"ActiveJob::QueueAdapters::QueAdapter::JobWrapper",
71
+ # "args"=> [{
72
+ # "job_class"=>"ExampleJob",
73
+ # "job_id"=>"60798b45-4b55-436e-806d-693939266c97",
74
+ # "provider_job_id"=>nil,
75
+ # "queue_name"=>"default",
76
+ # "priority"=>nil,
77
+ # "arguments"=>[],
78
+ # "executions"=>0,
79
+ # "locale"=>"en"
80
+ # }],
81
+ # "error_count"=>0
82
+ # }
83
+ #
84
+ # With ActiveJob, v1.0:
85
+ # There are changes here to make Que more compatible with ActiveJob
86
+ # and this probably needs to be revisited.
87
+
88
+ def _run_with_scout(*args)
89
+ # default queue unless specifed is a blank string
90
+ queue = attrs['queue'] || UNKNOWN_QUEUE_PLACEHOLDER
91
+
92
+ job_class = begin
93
+ if self.class == ActiveJob::QueueAdapters::QueAdapter::JobWrapper
94
+ Array(attrs['args']).first['job_class'] || UNKNOWN_CLASS_PLACEHOLDER
95
+ else
96
+ self.class.name
97
+ end
98
+ rescue => e
99
+ UNKNOWN_CLASS_PLACEHOLDER
100
+ end
101
+
102
+ latency = begin
103
+ Time.now - attrs['run_at']
104
+ rescue
105
+ 0
106
+ end
107
+
108
+ req = ScoutApm::RequestManager.lookup
109
+ req.annotate_request(:queue_latency => latency)
110
+
111
+ begin
112
+ req.start_layer(ScoutApm::Layer.new('Queue', queue))
113
+ started_queue = true
114
+ req.start_layer(ScoutApm::Layer.new('Job', job_class))
115
+ started_job = true
116
+
117
+ _run_without_scout(*args)
118
+ rescue Exception => e
119
+ req.error!
120
+ raise
121
+ ensure
122
+ req.stop_layer if started_job
123
+ req.stop_layer if started_queue
124
+ end
125
+ end
126
+
127
+ alias_method :_run_without_scout, :_run
128
+ alias_method :_run, :_run_with_scout
129
+ end
130
+ end
131
+ end
132
+
133
+ end
134
+ end
@@ -26,8 +26,12 @@ module ScoutApm
26
26
  def install_before_fork
27
27
  ::Resque.before_first_fork do
28
28
  begin
29
- ScoutApm::Agent.instance.start
30
- ScoutApm::Agent.instance.context.start_remote_server!(bind, port)
29
+ if ScoutApm::Agent.instance.context.config.value('start_resque_server_instrument')
30
+ ScoutApm::Agent.instance.start
31
+ ScoutApm::Agent.instance.context.start_remote_server!(bind, port)
32
+ else
33
+ logger.info("Not starting remote server due to 'start_resque_server_instrument' setting")
34
+ end
31
35
  rescue Errno::EADDRINUSE
32
36
  ScoutApm::Agent.instance.context.logger.warn "Error while Installing Resque Instruments, Port #{port} already in use. Set via the `remote_agent_port` configuration option"
33
37
  rescue => e
@@ -0,0 +1,124 @@
1
+ module ScoutApm
2
+ module BackgroundJobIntegrations
3
+ class Shoryuken
4
+ attr_reader :logger
5
+
6
+ def name
7
+ :shoryuken
8
+ end
9
+
10
+ def present?
11
+ defined?(::Shoryuken) && File.basename($PROGRAM_NAME).start_with?('shoryuken')
12
+ end
13
+
14
+ def forking?
15
+ false
16
+ end
17
+
18
+ def install
19
+ install_tracer
20
+ add_middleware
21
+ install_processor
22
+ end
23
+
24
+ def install_tracer
25
+ # ScoutApm::Tracer is not available when this class is defined
26
+ ShoryukenMiddleware.class_eval do
27
+ include ScoutApm::Tracer
28
+ end
29
+ end
30
+
31
+ def add_middleware
32
+ ::Shoryuken.configure_server do |config|
33
+ config.server_middleware do |chain|
34
+ chain.add ShoryukenMiddleware
35
+ end
36
+ end
37
+ end
38
+
39
+ def install_processor
40
+ require 'shoryuken/processor' # sidekiq v4 has not loaded this file by this point
41
+
42
+ ::Shoryuken::Processor.class_eval do
43
+ def initialize_with_scout(*args)
44
+ agent = ::ScoutApm::Agent.instance
45
+ agent.start
46
+ initialize_without_scout(*args)
47
+ end
48
+
49
+ alias_method :initialize_without_scout, :initialize
50
+ alias_method :initialize, :initialize_with_scout
51
+ end
52
+ end
53
+ end
54
+
55
+ # We insert this middleware into the Shoryuken stack, to capture each job,
56
+ # and time them.
57
+ class ShoryukenMiddleware
58
+ def call(worker_instance, queue, msg, body)
59
+ job_class =
60
+ begin
61
+ if worker_instance.class.to_s == ACTIVE_JOB_KLASS
62
+ body["job_class"]
63
+ else
64
+ worker_instance.class.to_s
65
+ end
66
+ rescue
67
+ UNKNOWN_CLASS_PLACEHOLDER
68
+ end
69
+
70
+ req = ScoutApm::RequestManager.lookup
71
+ req.annotate_request(:queue_latency => latency(msg))
72
+
73
+ begin
74
+ req.start_layer(ScoutApm::Layer.new('Queue', queue))
75
+ started_queue = true
76
+ req.start_layer(ScoutApm::Layer.new('Job', job_class))
77
+ started_job = true
78
+
79
+ yield
80
+ rescue Exception => e
81
+ req.error!
82
+ raise
83
+ ensure
84
+ req.stop_layer if started_job
85
+ req.stop_layer if started_queue
86
+ end
87
+ end
88
+
89
+ UNKNOWN_CLASS_PLACEHOLDER = 'UnknownJob'.freeze
90
+ ACTIVE_JOB_KLASS = 'ActiveJob::QueueAdapters::ShoryukenAdapter::JobWrapper'.freeze
91
+
92
+ def latency(msg, time = Time.now.to_f)
93
+ ms_since_epoch_str = msg.attributes.fetch('SentTimestamp', 0)
94
+ return 0 if ms_since_epoch_str.nil?
95
+
96
+ # Convert from ms to seconds as a float
97
+ created_at = ms_since_epoch_str.to_i / 1000.0
98
+
99
+ time - created_at
100
+ rescue => e
101
+ 0
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ # MSG: #<Shoryuken::Message:0x007fb742a96950 @client=#<Aws::SQS::Client>
108
+ # @data=#<struct Aws::SQS::Types::Message message_id="7a2ef0af-2bbd-4368-9c39-34cc89e4da15"
109
+ # receipt_handle="AQEB8YK4+TCyvCM3p0EanmhZiTbBCM6uMeyCn7zibNn+XZcMnjZp2Z8D8yoUs4mMX9vJqlQvaS8gRUGBYG7ciq+BthmEqDWfxbcJ8jN+Vp/PXIyyTgYL3vvlnHcQajDz3H7Bd30UmLu80sqeLSjXXNEiKolcIxdGuIsIdSM4aUEPXsecr5eH7o8pZHcDV+bGcLuE7VbvKRZT3A2HeezW7wWwkYve/wt6asS1bYB+VJurAORY0y26xgCooEMNbs5yqxcnSD/CiNT822hkmw0eHNpTHOjF9WLgxLbkpITnQl1lsfK5TsM/ukE1oB1F9nN5ZkCBVCDeFYJDBAo81VvVV9G16knxyCYzjnmpwhvHg2BqTA56iV6r9KZYbiwOaMPdH5ealKLRnWhFoLOEPNA4yjG1yw=="
110
+ # md5_of_body="8b3be018857a74f9e46b4c6ef3c3f515"
111
+ # body="Unique Person #7532"
112
+ # attributes={"SenderId"=>"AIDAJZXBVF26MLZPE6FOO"
113
+ # "ApproximateFirstReceiveTimestamp"=>"1534873932213"
114
+ # "ApproximateReceiveCount"=>"1"
115
+ # "SentTimestamp"=>"1534873927868"}
116
+ # md5_of_message_attributes="c70f52a6566cf42ec5e61e81877132dd"
117
+ # message_attributes={"shoryuken_class"=>#<struct Aws::SQS::Types::MessageAttributeValue string_value="DummyWorker"
118
+ # binary_value=nil
119
+ # string_list_values=[]
120
+ # binary_list_values=[]
121
+ # data_type="String">}>
122
+ # @queue_url="https://sqs.us-west-2.amazonaws.com/023109228371/shoryuken_test"
123
+ # @queue_name="shoryuken_test">
124
+
@@ -40,10 +40,10 @@ module ScoutApm
40
40
  require 'sidekiq/processor' # sidekiq v4 has not loaded this file by this point
41
41
 
42
42
  ::Sidekiq::Processor.class_eval do
43
- def initialize_with_scout(boss)
43
+ def initialize_with_scout(*args)
44
44
  agent = ::ScoutApm::Agent.instance
45
45
  agent.start
46
- initialize_without_scout(boss)
46
+ initialize_without_scout(*args)
47
47
  end
48
48
 
49
49
  alias_method :initialize_without_scout, :initialize
@@ -59,20 +59,10 @@ module ScoutApm
59
59
  req = ScoutApm::RequestManager.lookup
60
60
  req.annotate_request(:queue_latency => latency(msg))
61
61
 
62
- queue_layer = ScoutApm::Layer.new('Queue', queue)
63
- job_layer = ScoutApm::Layer.new('Job', job_class(msg))
64
-
65
- if ScoutApm::Agent.instance.context.config.value('profile') && SidekiqMiddleware.version_supports_profiling?
66
- # Capture ScoutProf if we can
67
- #req.enable_profiled_thread!
68
- #job_layer.set_root_class(job_class)
69
- #job_layer.traced!
70
- end
71
-
72
62
  begin
73
- req.start_layer(queue_layer)
63
+ req.start_layer(ScoutApm::Layer.new('Queue', queue))
74
64
  started_queue = true
75
- req.start_layer(job_layer)
65
+ req.start_layer(ScoutApm::Layer.new('Job', job_class(msg)))
76
66
  started_job = true
77
67
 
78
68
  yield
@@ -131,10 +121,6 @@ module ScoutApm
131
121
  rescue
132
122
  0
133
123
  end
134
-
135
- def self.version_supports_profiling?
136
- @@sidekiq_supports_profling ||= defined?(::Sidekiq::VERSION) && Gem::Dependency.new('', '~> 4.0').match?('', ::Sidekiq::VERSION.to_s)
137
- end
138
- end # SidekiqMiddleware
124
+ end
139
125
  end
140
126
  end
@@ -0,0 +1,87 @@
1
+ module ScoutApm
2
+ module BackgroundJobIntegrations
3
+ class Sneakers
4
+ def name
5
+ :sneakers
6
+ end
7
+
8
+ def present?
9
+ defined?(::Sneakers) && supported_version?
10
+ end
11
+
12
+ # Only support Sneakers 2.7 and up
13
+ def supported_version?
14
+ result = Gem::Version.new(::Sneakers::VERSION) > Gem::Version.new("2.7.0")
15
+ ScoutApm::Agent.instance.logger.info("Skipping Sneakers instrumentation. Only versions 2.7+ are supported. See docs or contact support@scoutapm.com for instrumentation of older versions.")
16
+ result
17
+ rescue
18
+ ScoutApm::Agent.instance.logger.info("Failed comparing Sneakers Version. Skipping")
19
+ false
20
+ end
21
+
22
+ def forking?
23
+ false
24
+ end
25
+
26
+ def install
27
+ install_worker_override
28
+ end
29
+
30
+ def install_worker_override
31
+ ::Sneakers::Worker.module_eval do
32
+ def initialize_with_scout(*args)
33
+ agent = ::ScoutApm::Agent.instance
34
+ agent.start
35
+ initialize_without_scout(*args)
36
+ end
37
+
38
+ alias_method :initialize_without_scout, :initialize
39
+ alias_method :initialize, :initialize_with_scout
40
+
41
+ def process_work_with_scout(*args)
42
+ delivery_info, _metadata, msg, _handler = args
43
+
44
+ queue = delivery_info[:routing_key] || UNKNOWN_QUEUE_PLACEHOLDER
45
+
46
+ job_class = begin
47
+ if self.class == ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper
48
+ msg["job_class"] || UNKNOWN_CLASS_PLACEHOLDER
49
+ else
50
+ self.class.name
51
+ end
52
+ rescue => e
53
+ UNKNOWN_CLASS_PLACEHOLDER
54
+ end
55
+
56
+ req = ScoutApm::RequestManager.lookup
57
+
58
+ # RabbitMQ does not store a created-at timestamp
59
+ # req.annotate_request(:queue_latency => latency(msg))
60
+
61
+ begin
62
+ req.start_layer(ScoutApm::Layer.new('Queue', queue))
63
+ started_queue = true
64
+ req.start_layer(ScoutApm::Layer.new('Job', job_class))
65
+ started_job = true
66
+
67
+ process_work_without_scout(*args)
68
+ rescue Exception => e
69
+ req.error!
70
+ raise
71
+ ensure
72
+ req.stop_layer if started_job
73
+ req.stop_layer if started_queue
74
+ end
75
+ end
76
+
77
+ alias_method :process_work_without_scout, :process_work
78
+ alias_method :process_work, :process_work_with_scout
79
+ end
80
+ end
81
+
82
+ ACTIVE_JOB_KLASS = 'ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper'.freeze
83
+ UNKNOWN_CLASS_PLACEHOLDER = 'UnknownJob'.freeze
84
+ UNKNOWN_QUEUE_PLACEHOLDER = 'default'.freeze
85
+ end
86
+ end
87
+ end
@@ -6,10 +6,11 @@ require 'scout_apm/environment'
6
6
  # Valid Config Options:
7
7
  #
8
8
  # This list is complete, but some are old and unused, or for developers of
9
- # scout_apm itself. See the documentation at http://help.apm.scoutapp.com for
9
+ # scout_apm itself. See the documentation at https://docs.scoutapm.com for
10
10
  # customer-focused documentation.
11
11
  #
12
12
  # application_root - override the detected directory of the application
13
+ # collect_remote_ip - automatically capture user's IP into a Trace's Context
13
14
  # compress_payload - true/false to enable gzipping of payload
14
15
  # data_file - override the default temporary storage location. Must be a location in a writable directory
15
16
  # dev_trace - true or false. Enables always-on tracing in development environmen only
@@ -30,6 +31,10 @@ require 'scout_apm/environment'
30
31
  # uri_reporting - 'path' or 'full_path' default is 'full_path', which reports URL params as well as the path.
31
32
  # remote_agent_host - Internal: What host to bind to, and also send messages to for remote. Default: 127.0.0.1.
32
33
  # remote_agent_port - What port to bind the remote webserver to
34
+ # start_resque_server_instrument - Used in special situations with certain Resque installs
35
+ # timeline_traces - true/false to enable sending of of the timeline trace format.
36
+ # auto_instruments - true/false whether to install autoinstruments. Only installed if on a supported Ruby version.
37
+ # auto_instruments_ignore - An array of file names to exclude from autoinstruments (Ex: ['application_controller']).
33
38
  #
34
39
  # Any of these config settings can be set with an environment variable prefixed
35
40
  # by SCOUT_ and uppercasing the key: SCOUT_LOG_LEVEL for instance.
@@ -39,6 +44,7 @@ module ScoutApm
39
44
  KNOWN_CONFIG_OPTIONS = [
40
45
  'application_root',
41
46
  'async_recording',
47
+ 'collect_remote_ip',
42
48
  'compress_payload',
43
49
  'config_file',
44
50
  'data_file',
@@ -66,9 +72,21 @@ module ScoutApm
66
72
  'remote_agent_host',
67
73
  'remote_agent_port',
68
74
  'report_format',
75
+ 'revision_sha',
69
76
  'scm_subdirectory',
77
+ 'start_resque_server_instrument',
78
+ 'ssl_cert_file',
70
79
  'uri_reporting',
71
80
  'instrument_http_url_length',
81
+ 'timeline_traces',
82
+ 'auto_instruments',
83
+ 'auto_instruments_ignore',
84
+
85
+ # Error Service Related Configuration
86
+ 'errors_enabled',
87
+ 'errors_ignored_exceptions',
88
+ 'errors_filtered_params',
89
+ 'errors_host',
72
90
  ]
73
91
 
74
92
  ################################################################################
@@ -148,16 +166,25 @@ module ScoutApm
148
166
 
149
167
 
150
168
  SETTING_COERCIONS = {
151
- "async_recording" => BooleanCoercion.new,
152
- "detailed_middleware" => BooleanCoercion.new,
153
- "dev_trace" => BooleanCoercion.new,
154
- "enable_background_jobs" => BooleanCoercion.new,
155
- "ignore" => JsonCoercion.new,
156
- "max_traces" => IntegerCoercion.new,
157
- "monitor" => BooleanCoercion.new,
169
+ 'async_recording' => BooleanCoercion.new,
170
+ 'detailed_middleware' => BooleanCoercion.new,
171
+ 'dev_trace' => BooleanCoercion.new,
172
+ 'enable_background_jobs' => BooleanCoercion.new,
173
+ 'ignore' => JsonCoercion.new,
174
+ 'max_traces' => IntegerCoercion.new,
175
+ 'monitor' => BooleanCoercion.new,
176
+ 'collect_remote_ip' => BooleanCoercion.new,
177
+ 'compress_payload' => BooleanCoercion.new,
158
178
  'database_metric_limit' => IntegerCoercion.new,
159
179
  'database_metric_report_limit' => IntegerCoercion.new,
160
180
  'instrument_http_url_length' => IntegerCoercion.new,
181
+ 'start_resque_server_instrument' => BooleanCoercion.new,
182
+ 'timeline_traces' => BooleanCoercion.new,
183
+ 'auto_instruments' => BooleanCoercion.new,
184
+ 'auto_instruments_ignore' => JsonCoercion.new,
185
+ 'errors_enabled' => BooleanCoercion.new,
186
+ 'errors_ignored_exceptions' => JsonCoercion.new,
187
+ 'errors_filtered_params' => JsonCoercion.new,
161
188
  }
162
189
 
163
190
 
@@ -263,6 +290,16 @@ module ScoutApm
263
290
  'database_metric_limit' => 5000, # The hard limit on db metrics
264
291
  'database_metric_report_limit' => 1000,
265
292
  'instrument_http_url_length' => 300,
293
+ 'start_resque_server_instrument' => true, # still only starts if Resque is detected
294
+ 'collect_remote_ip' => true,
295
+ 'timeline_traces' => true,
296
+ 'auto_instruments' => false,
297
+ 'auto_instruments_ignore' => [],
298
+ 'ssl_cert_file' => File.join( File.dirname(__FILE__), *%w[.. .. data cacert.pem] ),
299
+ 'errors_enabled' => false,
300
+ 'errors_ignored_exceptions' => %w(ActiveRecord::RecordNotFound ActionController::RoutingError),
301
+ 'errors_filtered_params' => %w(password s3-key),
302
+ 'errors_host' => 'https://errors.scoutapm.com',
266
303
  }.freeze
267
304
 
268
305
  def value(key)