scout_apm 2.6.4 → 2.6.5

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
  SHA256:
3
- metadata.gz: 96f6a10ca19691ef0b5feb036811700759fbd6164a0811efbe52b1fcaa97b6c9
4
- data.tar.gz: c2c39bcb738f22115d0a0f69f40340a5096f523e542c844fe007b15f42a324d1
3
+ metadata.gz: 41f15f4e7f91d0274a280b34d03697ff422963a39bcadc9f9056f6380b949603
4
+ data.tar.gz: c76090db49ba3f24ea685ccf61c0fbe17555affe556d947990cb584bb8f56bb5
5
5
  SHA512:
6
- metadata.gz: ea5173420001f92d54aae2a05b7ca71287ca08b3da08b27769895b9ddc0aca791dfb226c93ed84464728cc02a7c6defc486b3b1d606e58f64323d7c523dfdbfb
7
- data.tar.gz: 91b7ace32216ea11bffa119d782b3f43dba518fc1adf07bae866e20c8cf83e25e055ded16fd57ee2d6dc7d1c2f4b92c88849ab207adf316435d520b016bf7e3a
6
+ metadata.gz: b33379d021bbb49e1c2c60ca0c1a72f4603539142830b92f3846e87fdf9c9d2244e73dd0be5a84fc567945ca028b62450f48dbfd6fdc0fcab81eb6d44f82bab9
7
+ data.tar.gz: 35183553754b6a56397ff10579f014abf168c1b3ef83c22318c691ba6ab2798d6a4264e7d17270b318fe43c0ea5a61ab75c025b974354b10f4f5b1395ad77bb5
@@ -1,3 +1,12 @@
1
+ # 2.6.5
2
+
3
+ * Add a tag to any requests that reach maximum number of spans (#316)
4
+ * Update testing library Mocha (#315)
5
+ * Fix case sensitivity mismatch in Job renaming (#314)
6
+ * Add support for Sneakers 2.5 (#313)
7
+ * Fix edge case with Resque instrumentation (#312)
8
+ * Fix missing source code when used with BugSnag (#308)
9
+
1
10
  # 2.6.4
2
11
 
3
12
  * Add defensive check against a nil @address in Net/HTTP instruments (#306)
@@ -26,6 +35,7 @@
26
35
  # 2.5.3
27
36
 
28
37
  * Add Que support (#265)
38
+ * Add Memcached support (#279)
29
39
 
30
40
  # 2.5.2
31
41
 
@@ -1,4 +1,5 @@
1
1
  eval_gemfile("../Gemfile")
2
2
 
3
+ gem "json", "1.8.6"
3
4
  gem "rails", "~> 3.2"
4
5
  gem "sqlite3", "~> 1.3.5"
@@ -63,6 +63,7 @@ require 'scout_apm/background_job_integrations/resque'
63
63
  require 'scout_apm/background_job_integrations/shoryuken'
64
64
  require 'scout_apm/background_job_integrations/sneakers'
65
65
  require 'scout_apm/background_job_integrations/que'
66
+ require 'scout_apm/background_job_integrations/legacy_sneakers'
66
67
 
67
68
  require 'scout_apm/framework_integrations/rails_2'
68
69
  require 'scout_apm/framework_integrations/rails_3_or_4'
@@ -112,6 +113,7 @@ require 'scout_apm/utils/time'
112
113
  require 'scout_apm/utils/unique_id'
113
114
  require 'scout_apm/utils/numbers'
114
115
  require 'scout_apm/utils/gzip_helper'
116
+ require 'scout_apm/utils/marshal_logging'
115
117
 
116
118
  require 'scout_apm/config'
117
119
  require 'scout_apm/environment'
@@ -8,7 +8,7 @@ module ScoutApm
8
8
  if Rails.controller_path?(path) & !Rails.ignore?(path)
9
9
  begin
10
10
  new_code = Rails.rewrite(path)
11
- return self.compile(new_code, File.basename(path), path)
11
+ return self.compile(new_code, path, path)
12
12
  rescue
13
13
  warn "Failed to apply auto-instrumentation to #{path}: #{$!}"
14
14
  end
@@ -0,0 +1,55 @@
1
+ # This is different than other BackgroundJobIntegrations and must be prepended
2
+ # manually in each job.
3
+ #
4
+ # class MyWorker
5
+ # prepend ScoutApm::BackgroundJobIntegrations::LegacySneakers
6
+ #
7
+ # def work(msg)
8
+ # ...
9
+ # end
10
+ # end
11
+ module ScoutApm
12
+ module BackgroundJobIntegrations
13
+ module LegacySneakers
14
+ UNKNOWN_QUEUE_PLACEHOLDER = 'default'.freeze
15
+
16
+ def self.prepended(base)
17
+ ScoutApm::Agent.instance.logger.info("Prepended LegacySneakers in #{base}")
18
+ end
19
+
20
+ def initialize(*args)
21
+ super
22
+
23
+ # Save off the existing value to call the correct existing work
24
+ # function in the instrumentation. But then override Sneakers to always
25
+ # use the extra-argument version, which has data Scout needs
26
+ @call_work = respond_to?(:work)
27
+ end
28
+
29
+ def work_with_params(msg, delivery_info, metadata)
30
+ queue = delivery_info[:routing_key] || UNKNOWN_QUEUE_PLACEHOLDER
31
+ job_class = self.class.name
32
+ req = ScoutApm::RequestManager.lookup
33
+
34
+ begin
35
+ req.start_layer(ScoutApm::Layer.new('Queue', queue))
36
+ started_queue = true
37
+ req.start_layer(ScoutApm::Layer.new('Job', job_class))
38
+ started_job = true
39
+
40
+ if @call_work
41
+ work(msg)
42
+ else
43
+ super
44
+ end
45
+ rescue Exception
46
+ req.error!
47
+ raise
48
+ ensure
49
+ req.stop_layer if started_job
50
+ req.stop_layer if started_queue
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,14 +1,22 @@
1
1
  module ScoutApm
2
2
  module BackgroundJobIntegrations
3
3
  class Sneakers
4
- attr_reader :logger
5
-
6
4
  def name
7
5
  :sneakers
8
6
  end
9
7
 
10
8
  def present?
11
- defined?(::Sneakers)
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
12
20
  end
13
21
 
14
22
  def forking?
@@ -69,14 +77,6 @@ module ScoutApm
69
77
  alias_method :process_work_without_scout, :process_work
70
78
  alias_method :process_work, :process_work_with_scout
71
79
  end
72
-
73
- # msg = {
74
- # "job_class":"DummyWorker",
75
- # "job_id":"ea23ba1c-3022-4e05-870b-c3bcb1c4f328",
76
- # "queue_name":"default",
77
- # "arguments":["fjdkl"],
78
- # "locale":"en"
79
- # }
80
80
  end
81
81
 
82
82
  ACTIVE_JOB_KLASS = 'ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper'.freeze
@@ -32,8 +32,10 @@ module ScoutApm
32
32
 
33
33
  # Modifies self and returns self, after merging in `other`.
34
34
  def combine!(other)
35
- same_job = queue_name == other.queue_name && job_name == other.job_name
36
- raise "Mismatched Merge of Background Job" unless same_job
35
+ if !self.eql?(other)
36
+ ScoutApm::Agent.instance.logger.debug("Mismatched Merge of Background Job: (Queue #{queue_name} == #{other.queue_name}) (Name #{job_name} == #{other.job_name}) (Hash #{hash} == #{other.hash})")
37
+ return self
38
+ end
37
39
 
38
40
  @errors += other.errors
39
41
  @metric_set = metric_set.combine!(other.metric_set)
@@ -30,6 +30,10 @@ module ScoutApm
30
30
 
31
31
  def serialize(data)
32
32
  Marshal.dump(data)
33
+ rescue
34
+ ScoutApm::Agent.instance.logger.info("Failed Marshalling LayawayFile")
35
+ ScoutApm::Agent.instance.logger.info(ScoutApm::Utils::MarshalLogging.new(data).dive) rescue nil
36
+ raise
33
37
  end
34
38
 
35
39
  def deserialize(data)
@@ -46,9 +46,15 @@ module ScoutApm
46
46
  set = child_set(metric_type)
47
47
 
48
48
  if set.size >= unique_cutoff
49
- # find limited_layer
50
- @limited_layers || init_limited_layers
51
- @limited_layers[metric_type].absorb(child)
49
+ # find or create limited_layer
50
+ @limited_layers ||= Hash.new
51
+ layer = if @limited_layers.has_key?(metric_type)
52
+ @limited_layers[metric_type]
53
+ else
54
+ @limited_layers[metric_type] = LimitedLayer.new(metric_type)
55
+ end
56
+
57
+ layer.absorb(child)
52
58
  else
53
59
  # we have space just add it
54
60
  set << child
@@ -76,10 +82,5 @@ module ScoutApm
76
82
  def size
77
83
  @children.size
78
84
  end
79
-
80
- # hold off initializing this until we know we need it
81
- def init_limited_layers
82
- @limited_layers ||= Hash.new { |hash, key| hash[key] = LimitedLayer.new(key) }
83
- end
84
85
  end
85
86
  end
@@ -58,6 +58,9 @@ module ScoutApm
58
58
  code = "" # User#index for instance
59
59
 
60
60
  spans = create_spans(request.root_layer)
61
+ if limited?
62
+ tags[:"scout.reached_span_cap"] = true
63
+ end
61
64
 
62
65
  DetailedTrace.new(
63
66
  transaction_id,
@@ -17,6 +17,10 @@ module ScoutApm
17
17
 
18
18
  def encode
19
19
  Marshal.dump(self)
20
+ rescue
21
+ ScoutApm::Agent.instance.logger.info("Failed Marshalling Remote::Message")
22
+ ScoutApm::Agent.instance.logger.info(ScoutApm::Utils::MarshalLogging.new(self).dive) rescue nil
23
+ raise
20
24
  end
21
25
  end
22
26
  end
@@ -5,6 +5,10 @@ module ScoutApm
5
5
  class AppServerLoadSerializer
6
6
  def self.serialize(data)
7
7
  Marshal.dump(data)
8
+ rescue
9
+ ScoutApm::Agent.instance.logger.info("Failed Marshalling AppServerLoad")
10
+ ScoutApm::Agent.instance.logger.info(ScoutApm::Utils::MarshalLogging.new(data).dive) rescue nil
11
+ raise
8
12
  end
9
13
 
10
14
  def self.deserialize(data)
@@ -5,6 +5,10 @@ module ScoutApm
5
5
  class DirectiveSerializer
6
6
  def self.serialize(data)
7
7
  Marshal.dump(data)
8
+ rescue
9
+ ScoutApm::Agent.instance.logger.info("Failed Marshalling Directive")
10
+ ScoutApm::Agent.instance.logger.info(ScoutApm::Utils::MarshalLogging.new(data).dive) rescue nil
11
+ raise
8
12
  end
9
13
 
10
14
  def self.deserialize(data)
@@ -0,0 +1,90 @@
1
+ module ScoutApm
2
+ module Utils
3
+ class Error < StandardError; end
4
+
5
+ class InstanceVar
6
+ attr_reader :name
7
+ attr_reader :obj
8
+
9
+ def initialize(name, obj, parent)
10
+ @name = name
11
+ @obj = obj
12
+ @parent = parent
13
+ end
14
+
15
+ def to_s
16
+ "#{@name} - #{obj.class}"
17
+ end
18
+
19
+ def history
20
+ (@parent.nil? ? [] : @parent.history) + [to_s]
21
+ end
22
+ end
23
+
24
+ class MarshalLogging
25
+ def initialize(base_obj)
26
+ @base_obj = base_obj
27
+ end
28
+
29
+ def dive
30
+ to_investigate = [InstanceVar.new('Root', @base_obj, nil)]
31
+ max_to_check = 10000
32
+ checked = 0
33
+
34
+ while (var = to_investigate.shift)
35
+ checked += 1
36
+ if checked > max_to_check
37
+ return "Limiting Checks (max = #{max_to_check})"
38
+ end
39
+
40
+ obj = var.obj
41
+
42
+ if offending_hash?(obj)
43
+ return "Found undumpable object: #{var.history}"
44
+ end
45
+
46
+ if !dumps?(obj)
47
+ if obj.is_a? Hash
48
+ keys = obj.keys
49
+ keys.each do |key|
50
+ to_investigate.push(
51
+ InstanceVar.new(key.to_s, obj[key], var)
52
+ )
53
+ end
54
+ elsif obj.is_a? Array
55
+ obj.each_with_index do |value, idx|
56
+ to_investigate.push(
57
+ InstanceVar.new("Index #{idx}", value, var)
58
+ )
59
+ end
60
+ else
61
+ symbols = obj.instance_variables
62
+ if !symbols.any?
63
+ return "Found undumpable object: #{var.history}"
64
+ end
65
+
66
+ symbols.each do |sym|
67
+ to_investigate.push(
68
+ InstanceVar.new(sym, obj.instance_variable_get(sym), var)
69
+ )
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ true
76
+ end
77
+
78
+ def dumps?(obj)
79
+ Marshal.dump(obj)
80
+ true
81
+ rescue TypeError
82
+ false
83
+ end
84
+
85
+ def offending_hash?(obj)
86
+ obj.is_a?(Hash) && !obj.default_proc.nil?
87
+ end
88
+ end
89
+ end
90
+ end
@@ -1,3 +1,3 @@
1
1
  module ScoutApm
2
- VERSION = "2.6.4"
2
+ VERSION = "2.6.5"
3
3
  end
@@ -5,7 +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
+ require 'mocha/minitest'
9
9
  require 'pry'
10
10
 
11
11
 
@@ -71,6 +71,15 @@ class LayerChildrenSetTest < Minitest::Test
71
71
  limited_layers.each { |ml| assert_equal 5, ml.count }
72
72
  end
73
73
 
74
+ def test_works_with_marshal
75
+ s = SET.new(5)
76
+ 10.times do
77
+ s << make_layer("LayerType", "LayerName")
78
+ end
79
+
80
+ Marshal.dump(s)
81
+ end
82
+
74
83
  #############
75
84
  # Helpers #
76
85
  #############
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.6.4
4
+ version: 2.6.5
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: 2019-11-14 00:00:00.000000000 Z
12
+ date: 2019-12-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -250,6 +250,7 @@ files:
250
250
  - lib/scout_apm/auto_instrument/parser.rb
251
251
  - lib/scout_apm/auto_instrument/rails.rb
252
252
  - lib/scout_apm/background_job_integrations/delayed_job.rb
253
+ - lib/scout_apm/background_job_integrations/legacy_sneakers.rb
253
254
  - lib/scout_apm/background_job_integrations/que.rb
254
255
  - lib/scout_apm/background_job_integrations/resque.rb
255
256
  - lib/scout_apm/background_job_integrations/shoryuken.rb
@@ -376,6 +377,7 @@ files:
376
377
  - lib/scout_apm/utils/gzip_helper.rb
377
378
  - lib/scout_apm/utils/installed_gems.rb
378
379
  - lib/scout_apm/utils/klass_helper.rb
380
+ - lib/scout_apm/utils/marshal_logging.rb
379
381
  - lib/scout_apm/utils/numbers.rb
380
382
  - lib/scout_apm/utils/scm.rb
381
383
  - lib/scout_apm/utils/sql_sanitizer.rb