scout_apm 2.6.4 → 2.6.5

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
  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