scout_apm 2.2.0.pre2 → 2.2.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9b1ea1128aa9aa0aa0b5086860810f324ffe732c
4
- data.tar.gz: 00e3f0e517bfb8b580205bd7709a040fd13d611a
3
+ metadata.gz: b4fa1f78b691cca73f89e5f79902cdc097633773
4
+ data.tar.gz: da4c781988cd5996d6d565b42d5ce25e90e4608a
5
5
  SHA512:
6
- metadata.gz: bea83409eb9f21cccbfc9aeeeeae3f4a22113cfdd13fa1f51ede6df3422ed5a0d2b7a15d922c7d132632c486430372c68616482b9d2356fd80689ba0cf9d74e8
7
- data.tar.gz: 43c32ce10c3e01134904e19a1d2068c1b4a06ac928d44dbb3f1fd46e781ab98414737f9c004858f3ced00fe29534f91af0804f9b2559364ac3e15ad856020918
6
+ metadata.gz: dc8f935276423d6cb568af1dded73c38af744747b07fb8ed390a0f3f968c6ff7188e912da1acd1c3599d683a1ee8160196ff7756c2b55c384b4584342e677ca9
7
+ data.tar.gz: e5709ffa058e1ffed9d16bc37733f38c0d777f1d33d597447f2d38c7a168635ecbca9d13540be7baa3a8e84a8f082b68ce23b2a62b3d92b7cb0c103010443bc5
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ # 80 is stifling, especially with a few levels of nesting before we even start.
2
+ # So bump it to 100 to keep really long lines from creeping in.
3
+ Metrics/LineLength:
4
+ Max: 100
5
+
6
+ Style/UseHashRocketsWithSymbolValues: false
7
+
8
+
data/CHANGELOG.markdown CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  * ScoutProf BETA
4
4
 
5
+ # 2.1.4
6
+
7
+ * Enhance regular expression that determines if a backtrace line is "inside"
8
+ the application
9
+ * Avoids labeling vendor/ as part of the monitored app
10
+
11
+ # 2.1.3
12
+
13
+ * Less noisy output on errors with Context
14
+ * Not logging errors w/nil keys or values
15
+ * Bumping log level down from WARN => INFO on errors
16
+ * Fix error with complicated AR queries
17
+ * Caused high log noise
18
+ * Sidekiq instrumentation changes to handle a variety of edge cases
19
+
20
+ # 2.1.2
21
+
22
+ * Applies `Rails.application.config.filter_parameters` settings to reported transaction trace uris
23
+ * Fix incompatibility with ResqueWeb and middleware instrumentation
24
+
5
25
  # 2.1.1
6
26
 
7
27
  * Fix an issue with AR instrumentation and complex queries
@@ -8,7 +8,7 @@ module ScoutApm
8
8
  end
9
9
 
10
10
  def present?
11
- defined?(::Sidekiq) && (File.basename($0) =~ /\Asidekiq/)
11
+ defined?(::Sidekiq) && File.basename($PROGRAM_NAME).start_with?('sidekiq')
12
12
  end
13
13
 
14
14
  def forking?
@@ -16,22 +16,33 @@ module ScoutApm
16
16
  end
17
17
 
18
18
  def install
19
+ install_tracer
20
+ add_middleware
21
+ install_processor
22
+ end
23
+
24
+ def install_tracer
19
25
  # ScoutApm::Tracer is not available when this class is defined
20
26
  SidekiqMiddleware.class_eval do
21
27
  include ScoutApm::Tracer
22
28
  end
29
+ end
23
30
 
31
+ def add_middleware
24
32
  ::Sidekiq.configure_server do |config|
25
33
  config.server_middleware do |chain|
26
34
  chain.add SidekiqMiddleware
27
35
  end
28
36
  end
37
+ end
29
38
 
39
+ def install_processor
30
40
  require 'sidekiq/processor' # sidekiq v4 has not loaded this file by this point
31
41
 
32
42
  ::Sidekiq::Processor.class_eval do
33
43
  def initialize_with_scout(boss)
34
- ::ScoutApm::Agent.instance.start_background_worker unless ::ScoutApm::Agent.instance.background_worker_running?
44
+ agent = ::ScoutApm::Agent.instance
45
+ agent.start_background_worker
35
46
  initialize_without_scout(boss)
36
47
  end
37
48
 
@@ -41,21 +52,18 @@ module ScoutApm
41
52
  end
42
53
  end
43
54
 
55
+ # We insert this middleware into the Sidekiq stack, to capture each job,
56
+ # and time them.
44
57
  class SidekiqMiddleware
45
- def call(worker, msg, queue)
46
- job_class = msg["class"] # TODO: Validate this across different versions of Sidekiq
47
- if job_class == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper" && msg.has_key?("wrapped")
48
- job_class = msg["wrapped"]
49
- end
50
-
51
- latency = (Time.now.to_f - (msg['enqueued_at'] || msg['created_at']))
58
+ ACTIVE_JOB_KLASS = 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper'.freeze
52
59
 
60
+ def call(_worker, msg, queue)
53
61
  req = ScoutApm::RequestManager.lookup
54
62
  req.job!
55
- req.annotate_request(:queue_latency => latency)
63
+ req.annotate_request(:queue_latency => latency(msg))
56
64
 
57
- queue_layer = ScoutApm::Layer.new("Queue", queue)
58
- job_layer = ScoutApm::Layer.new("Job", job_class)
65
+ queue_layer = ScoutApm::Layer.new('Queue', queue)
66
+ job_layer = ScoutApm::Layer.new('Job', job_class(msg))
59
67
 
60
68
  if ScoutApm::Agent.instance.config.value('profile') && SidekiqMiddleware.version_supports_profiling?
61
69
  # Capture ScoutProf if we can
@@ -64,18 +72,43 @@ module ScoutApm
64
72
  #job_layer.traced!
65
73
  end
66
74
 
67
- req.start_layer(queue_layer)
68
- req.start_layer(job_layer)
69
-
70
75
  begin
76
+ req.start_layer(queue_layer)
77
+ started_queue = true
78
+ req.start_layer(job_layer)
79
+ started_job = true
80
+
71
81
  yield
72
82
  rescue
73
83
  req.error!
74
84
  raise
85
+ ensure
86
+ req.stop_layer if started_job
87
+ req.stop_layer if started_queue
88
+ end
89
+ end
90
+
91
+ UNKNOWN_CLASS_PLACEHOLDER = 'UnknownJob'.freeze
92
+
93
+ def job_class(msg)
94
+ job_class = msg.fetch('class', UNKNOWN_CLASS_PLACEHOLDER)
95
+ if job_class == ACTIVE_JOB_KLASS && msg.key?('wrapped')
96
+ job_class = msg['wrapped']
97
+ end
98
+ job_class
99
+ rescue
100
+ UNKNOWN_CLASS_PLACEHOLDER
101
+ end
102
+
103
+ def latency(msg, time = Time.now.to_f)
104
+ created_at = msg['enqueued_at'] || msg['created_at']
105
+ if created_at
106
+ (time - created_at)
107
+ else
108
+ 0
75
109
  end
76
- ensure
77
- req.stop_layer # Job
78
- req.stop_layer # Queue
110
+ rescue
111
+ 0
79
112
  end
80
113
 
81
114
  def self.version_supports_profiling?
@@ -75,8 +75,10 @@ module ScoutApm
75
75
  def value_valid?(key_value)
76
76
  # ensure one of our accepted types.
77
77
  value = key_value.values.last
78
- if !valid_type?([String, Symbol, Numeric, Time, Date, TrueClass, FalseClass],value)
79
- ScoutApm::Agent.instance.logger.warn "The value for [#{key_value.keys.first}] is not a valid type [#{value.class}]."
78
+ if value.nil?
79
+ false # don't log this ... easy to happen
80
+ elsif !valid_type?([String, Symbol, Numeric, Time, Date, TrueClass, FalseClass],value)
81
+ ScoutApm::Agent.instance.logger.info "The value for [#{key_value.keys.first}] is not a valid type [#{value.class}]."
80
82
  false
81
83
  else
82
84
  true
@@ -86,14 +88,16 @@ module ScoutApm
86
88
  # for consistently with #value_valid?, takes a hash eventhough the value isn't yet used.
87
89
  def key_valid?(key_value)
88
90
  key = key_value.keys.first
91
+ if key.nil?
92
+ false # don't log this ... easy to happen
89
93
  # ensure a string or a symbol
90
- if !valid_type?([String, Symbol],key)
91
- ScoutApm::Agent.instance.logger.warn "The key [#{key}] is not a valid type [#{key.class}]."
94
+ elsif !valid_type?([String, Symbol],key)
95
+ ScoutApm::Agent.instance.logger.info "The key [#{key}] is not a valid type [#{key.class}]."
92
96
  return false
93
97
  end
94
98
  # only alphanumeric, dash, and underscore allowed.
95
99
  if key.to_s.match(/[^\w-]/)
96
- ScoutApm::Agent.instance.logger.warn "They key name [#{key}] is not valid."
100
+ ScoutApm::Agent.instance.logger.info "They key name [#{key}] is not valid."
97
101
  return false
98
102
  end
99
103
  true
@@ -48,8 +48,7 @@ module ScoutApm
48
48
  # specific controller actions.
49
49
  def perform_action_with_scout_instruments(*args, &block)
50
50
  req = ScoutApm::RequestManager.lookup
51
- path = ScoutApm::Agent.instance.config.value("uri_reporting") == 'path' ? request.path : request.fullpath
52
- req.annotate_request(:uri => path)
51
+ req.annotate_request(:uri => request.path) # for security by-default, we don't use request.fullpath which could reveal filtered params.
53
52
  req.context.add_user(:ip => request.remote_ip)
54
53
  req.set_headers(request.headers)
55
54
  req.start_layer( ScoutApm::Layer.new("Controller", "#{controller_path}/#{action_name}") )
@@ -60,8 +60,7 @@ module ScoutApm
60
60
  module ActionControllerRails3Rails4Instruments
61
61
  def process_action(*args)
62
62
  req = ScoutApm::RequestManager.lookup
63
- path = ScoutApm::Agent.instance.config.value("uri_reporting") == 'path' ? request.path : request.fullpath
64
- req.annotate_request(:uri => path)
63
+ req.annotate_request(:uri => scout_transaction_uri(request))
65
64
 
66
65
  # IP Spoofing Protection can throw an exception, just move on w/o remote ip
67
66
  req.context.add_user(:ip => request.remote_ip) rescue nil
@@ -95,8 +94,19 @@ module ScoutApm
95
94
  ensure
96
95
  req.stop_layer
97
96
  end
97
+ end # process_action
98
+
99
+ # Given an +ActionDispatch::Request+, formats the uri based on config settings.
100
+ def scout_transaction_uri(request)
101
+ case ScoutApm::Agent.instance.config.value("uri_reporting")
102
+ when 'path'
103
+ request.path # strips off the query string for more security
104
+ else # default handles filtered params
105
+ request.filtered_path
106
+ end
98
107
  end
99
- end
108
+
109
+ end # ActionControllerRails3Rails4Instruments
100
110
  end
101
111
  end
102
112
 
@@ -23,7 +23,15 @@ module ScoutApm
23
23
  ActionDispatch::MiddlewareStack.class_eval do
24
24
  def build_with_scout_instruments(app = nil, &block)
25
25
  mw_stack = build_without_scout_instruments(app) { block.call if block }
26
- MiddlewareSummaryWrapper.new(mw_stack)
26
+ if app == mw_stack
27
+ # Return the raw middleware stack if it equaled app. No
28
+ # middlewares were created, so nothing to wrap & test.
29
+ #
30
+ # Avoids instrumentation of something that doesn't exist
31
+ mw_stack
32
+ else
33
+ MiddlewareSummaryWrapper.new(mw_stack)
34
+ end
27
35
  end
28
36
 
29
37
  alias_method :build_without_scout_instruments, :build
@@ -45,6 +53,36 @@ module ScoutApm
45
53
  ensure
46
54
  req.stop_layer
47
55
  end
56
+
57
+ # Some code (found in resque_web initially) attempts to call methods
58
+ # directly on `MyApplication.app`, which is the middleware stack.
59
+ # If it hits our middleware instead of the object at the root of the
60
+ # app that it expected, then a method it expects will not be there, and an
61
+ # error thrown.
62
+ #
63
+ # Specifically, resque_web assumes `ResqueWeb::Engine.app.url_helpers`
64
+ # is a method call on rails router for its own Engine, when in fact,
65
+ # we've added a middleware before it.
66
+ #
67
+ # So method_missing just proxies anything to the nested @app object
68
+ #
69
+ # While method_missing is not very performant, this is only here to
70
+ # handle edge-cases in other code, and should not be regularly called
71
+ def method_missing(sym, *arguments, &block)
72
+ if @app.respond_to?(sym)
73
+ @app.send(sym, *arguments, &block)
74
+ else
75
+ super
76
+ end
77
+ end
78
+
79
+ def respond_to?(sym, include_private = false)
80
+ if @app.respond_to?(sym, include_private)
81
+ true
82
+ else
83
+ super
84
+ end
85
+ end
48
86
  end
49
87
  end
50
88
  end
@@ -47,7 +47,7 @@ module ScoutApm
47
47
  @layers = []
48
48
  @call_set = Hash.new { |h, k| h[k] = CallSet.new }
49
49
  @annotations = {}
50
- @ignoring_children = false
50
+ @ignoring_children = 0
51
51
  @context = Context.new
52
52
  @root_layer = nil
53
53
  @error = false
@@ -323,27 +323,41 @@ module ScoutApm
323
323
  # specific, and useful than the fact that InfluxDB happens to use Net::HTTP
324
324
  # internally
325
325
  #
326
- # When enabled, new layers won't be added to the current Request.
326
+ # When enabled, new layers won't be added to the current Request, and calls
327
+ # to stop_layer will be ignored.
327
328
  #
328
329
  # Do not forget to turn if off when leaving a layer, it is the
329
330
  # instrumentation's task to do that.
331
+ #
332
+ # When you use this in code, be sure to use it in this order:
333
+ #
334
+ # start_layer
335
+ # ignore_children
336
+ # -> call
337
+ # acknowledge_children
338
+ # stop_layer
339
+ #
340
+ # If you don't call it in this order, it's possible to get out of sync, and
341
+ # have an ignored start and an actually-executed stop, causing layers to
342
+ # get out of sync
330
343
 
331
344
  def ignore_children!
332
- @ignoring_children = true
345
+ @ignoring_children += 1
333
346
  end
334
347
 
335
348
  def acknowledge_children!
336
- @ignoring_children = false
349
+ if @ignoring_children > 0
350
+ @ignoring_children -= 1
351
+ end
337
352
  end
338
353
 
339
354
  def ignoring_children?
340
- @ignoring_children
355
+ @ignoring_children > 0
341
356
  end
342
357
 
343
358
  # Grab backtraces more aggressively when running in dev trace mode
344
359
  def backtrace_threshold
345
360
  dev_trace ? 0.05 : 0.5 # the minimum threshold in seconds to record the backtrace for a metric.
346
361
  end
347
-
348
362
  end
349
363
  end
@@ -14,7 +14,10 @@ module ScoutApm
14
14
  def initialize(call_stack, root=ScoutApm::Environment.instance.root)
15
15
  @call_stack = call_stack
16
16
  # We can't use a constant as it'd be too early to fetch environment info
17
- @@app_dir_regex = %r|#{root}/(.*)|
17
+ #
18
+ # This regex looks for files under the app root, inside lib/, app/, and
19
+ # config/ dirs, and captures the path under root.
20
+ @@app_dir_regex = %r[#{root}/((?:lib/|app/|config/).*)]
18
21
  end
19
22
 
20
23
  def call
@@ -27,7 +30,6 @@ module ScoutApm
27
30
  end
28
31
  stack
29
32
  end
30
-
31
33
  end
32
34
  end
33
35
  end
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "2.2.0.pre2"
2
+ VERSION = "2.2.0.pre3"
3
3
  end
4
4
 
data/scout_apm.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  s.add_runtime_dependency "rusage", '~> 0.2.0'
25
25
 
26
26
  s.add_development_dependency "minitest"
27
+ s.add_development_dependency 'mocha'
27
28
  s.add_development_dependency "pry"
28
29
  s.add_development_dependency "m"
29
30
  s.add_development_dependency "simplecov"
data/test/test_helper.rb CHANGED
@@ -5,6 +5,7 @@ SimpleCov.start
5
5
  require 'minitest/autorun'
6
6
  require 'minitest/unit'
7
7
  require 'minitest/pride'
8
+ require 'mocha/mini_test'
8
9
  require 'pry'
9
10
 
10
11
 
@@ -82,4 +83,3 @@ class Minitest::Test
82
83
  DATA_FILE_PATH = "#{DATA_FILE_DIR}/scout_apm.db"
83
84
  end
84
85
 
85
-
@@ -0,0 +1,104 @@
1
+ require 'test_helper'
2
+ require 'scout_apm/request_manager'
3
+ require 'scout_apm/background_job_integrations/sidekiq'
4
+
5
+ class SidekiqTest < Minitest::Test
6
+ SidekiqMiddleware = ScoutApm::BackgroundJobIntegrations::SidekiqMiddleware
7
+
8
+ ########################################
9
+ # Middleware
10
+ ########################################
11
+ def test_middleware_call_happy_path
12
+ fake_request = mock
13
+ fake_request.expects(:annotate_request)
14
+ fake_request.expects(:job!)
15
+ fake_request.expects(:start_layer).twice
16
+ fake_request.expects(:stop_layer).twice
17
+ fake_request.expects(:error!).never
18
+
19
+ ScoutApm::RequestManager.stubs(:lookup).returns(fake_request)
20
+
21
+ block_called = false
22
+ msg = { 'class' => 'MyJobClass',
23
+ 'created_at' => Time.now }
24
+
25
+ SidekiqMiddleware.new.call(nil, msg, "defaultqueue") { block_called = true }
26
+ assert_equal true, block_called
27
+ end
28
+
29
+ def test_middleware_call_job_exception
30
+ fake_request = mock
31
+ fake_request.expects(:annotate_request)
32
+ fake_request.expects(:job!)
33
+ fake_request.expects(:start_layer).twice
34
+ fake_request.expects(:stop_layer).twice
35
+ fake_request.expects(:error!)
36
+
37
+ ScoutApm::RequestManager.stubs(:lookup).returns(fake_request)
38
+
39
+ msg = { 'class' => 'MyJobClass',
40
+ 'created_at' => Time.now }
41
+
42
+ assert_raises RuntimeError do
43
+ SidekiqMiddleware.new.call(nil, msg, "defaultqueue") { raise "TheJobFailed" }
44
+ end
45
+ end
46
+
47
+ def test_middleware_call_edge_cases
48
+ fake_request = mock
49
+ fake_request.expects(:annotate_request)
50
+ fake_request.expects(:job!)
51
+ fake_request.expects(:start_layer).twice
52
+ fake_request.expects(:stop_layer).twice
53
+ fake_request.expects(:error!)
54
+
55
+ ScoutApm::RequestManager.stubs(:lookup).returns(fake_request)
56
+
57
+ # msg doesn't have anything
58
+ msg = { }
59
+
60
+ assert_raises RuntimeError do
61
+ SidekiqMiddleware.new.call(nil, msg, "defaultqueue") { raise "TheJobFailed" }
62
+ end
63
+ end
64
+
65
+ ########################################
66
+ # Job Class Determination
67
+ ########################################
68
+ def test_job_class_name_normally
69
+ msg = { 'class' => 'AGreatJob' }
70
+ assert_equal 'AGreatJob', SidekiqMiddleware.new.job_class(msg)
71
+ end
72
+
73
+ def test_job_class_name_activejob
74
+ msg = { 'class' => 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper',
75
+ 'wrapped' => 'RealJobClass' }
76
+ assert_equal 'RealJobClass', SidekiqMiddleware.new.job_class(msg)
77
+ end
78
+
79
+ def test_job_class_name_error_default
80
+ msg = {}
81
+ assert_equal 'UnknownJob', SidekiqMiddleware.new.job_class(msg)
82
+ end
83
+
84
+ ########################################
85
+ # Latency Calculation
86
+ ########################################
87
+ def test_latency_from_created_at
88
+ # Created at time 80, but now it is 200. Latency was 120
89
+ msg = { 'created_at' => 80 }
90
+ assert_equal 120, SidekiqMiddleware.new.latency(msg, 200)
91
+ end
92
+
93
+ def test_latency_from_enqueued_at
94
+ # Created at time 80, but now it is 200. Latency was 120
95
+ msg = { 'enqueued_at' => 80 }
96
+ assert_equal 120, SidekiqMiddleware.new.latency(msg, 200)
97
+ end
98
+
99
+ def test_latency_fallback
100
+ # No created at time, so fall back to 0
101
+ msg = {}
102
+ assert_equal 0, SidekiqMiddleware.new.latency(msg, 200)
103
+ end
104
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ require 'scout_apm/context'
4
+
5
+ class ContextText < Minitest::Test
6
+ def test_ignore_nil_value
7
+ context = ScoutApm::Context.new
8
+ assert hash = context.add(:nil_key => nil, :org => 'org')
9
+ assert_equal ({:org => 'org'}), hash
10
+ end
11
+
12
+ def test_ignore_nil_key
13
+ context = ScoutApm::Context.new
14
+ assert hash = context.add(nil => nil, :org => 'org')
15
+ assert_equal ({:org => 'org'}), hash
16
+ end
17
+
18
+ def test_ignore_unsupported_value_type
19
+ context = ScoutApm::Context.new
20
+ assert hash = context.add(:array => [1,2,3,4], :org => 'org')
21
+ assert_equal ({:org => 'org'}), hash
22
+ end
23
+
24
+ def test_ignore_unsupported_key_type
25
+ context = ScoutApm::Context.new
26
+ assert hash = context.add([1,2,3,4] => 'hey', :org => 'org')
27
+ assert_equal ({:org => 'org'}), hash
28
+ end
29
+ end
30
+
@@ -49,4 +49,18 @@ class BacktraceParserTest < Minitest::Test
49
49
  result = ScoutApm::Utils::BacktraceParser.new(raw_backtrace, "/Users/scout/different-secrets").call
50
50
  assert_equal 0, result.length
51
51
  end
52
+
53
+ def test_excludes_vendor_paths
54
+ raw_backtrace = [
55
+ "#{root}/vendor/ruby/thing.rb",
56
+ "#{root}/app/controllers/users_controller.rb",
57
+ "#{root}/vendor/ruby/thing.rb",
58
+ "#{root}/config/initializers/inject_something.rb",
59
+ ]
60
+ result = ScoutApm::Utils::BacktraceParser.new(raw_backtrace, root).call
61
+
62
+ assert_equal 2, result.length
63
+ assert_equal false, (result[0] =~ %r|app/controllers/users_controller.rb|).nil?
64
+ assert_equal false, (result[1] =~ %r|config/initializers/inject_something.rb|).nil?
65
+ end
52
66
  end
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: 2.2.0.pre2
4
+ version: 2.2.0.pre3
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-08-22 00:00:00.000000000 Z
12
+ date: 2016-08-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rusage
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: mocha
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: pry
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +119,7 @@ extensions:
105
119
  extra_rdoc_files: []
106
120
  files:
107
121
  - ".gitignore"
122
+ - ".rubocop.yml"
108
123
  - CHANGELOG.markdown
109
124
  - Gemfile
110
125
  - LICENSE.md
@@ -229,7 +244,9 @@ files:
229
244
  - test/data/config_test_1.yml
230
245
  - test/test_helper.rb
231
246
  - test/unit/agent_test.rb
247
+ - test/unit/background_job_integrations/sidekiq_test.rb
232
248
  - test/unit/config_test.rb
249
+ - test/unit/context_test.rb
233
250
  - test/unit/environment_test.rb
234
251
  - test/unit/histogram_test.rb
235
252
  - test/unit/ignored_uris_test.rb