scout_apm 3.0.0.pre26 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) 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 +143 -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 +39 -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 +126 -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 +87 -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/database_converter.rb +2 -15
  70. data/lib/scout_apm/layer_converters/slow_job_converter.rb +12 -2
  71. data/lib/scout_apm/layer_converters/slow_request_converter.rb +14 -4
  72. data/lib/scout_apm/layer_converters/trace_converter.rb +184 -0
  73. data/lib/scout_apm/limited_layer.rb +0 -7
  74. data/lib/scout_apm/metric_stats.rb +0 -8
  75. data/lib/scout_apm/middleware.rb +1 -1
  76. data/lib/scout_apm/periodic_work.rb +19 -0
  77. data/lib/scout_apm/remote/message.rb +4 -0
  78. data/lib/scout_apm/remote/server.rb +13 -1
  79. data/lib/scout_apm/reporter.rb +8 -3
  80. data/lib/scout_apm/reporting.rb +2 -1
  81. data/lib/scout_apm/request_histograms.rb +8 -0
  82. data/lib/scout_apm/serializers/app_server_load_serializer.rb +4 -0
  83. data/lib/scout_apm/serializers/directive_serializer.rb +4 -0
  84. data/lib/scout_apm/serializers/payload_serializer.rb +2 -2
  85. data/lib/scout_apm/serializers/payload_serializer_to_json.rb +30 -15
  86. data/lib/scout_apm/slow_job_record.rb +5 -1
  87. data/lib/scout_apm/slow_policy/age_policy.rb +33 -0
  88. data/lib/scout_apm/slow_policy/percent_policy.rb +22 -0
  89. data/lib/scout_apm/slow_policy/percentile_policy.rb +24 -0
  90. data/lib/scout_apm/slow_policy/policy.rb +21 -0
  91. data/lib/scout_apm/slow_policy/speed_policy.rb +16 -0
  92. data/lib/scout_apm/slow_request_policy.rb +18 -77
  93. data/lib/scout_apm/slow_transaction.rb +3 -1
  94. data/lib/scout_apm/store.rb +12 -8
  95. data/lib/scout_apm/tracked_request.rb +39 -30
  96. data/lib/scout_apm/utils/active_record_metric_name.rb +16 -3
  97. data/lib/scout_apm/utils/backtrace_parser.rb +3 -0
  98. data/lib/scout_apm/utils/marshal_logging.rb +90 -0
  99. data/lib/scout_apm/utils/sql_sanitizer.rb +10 -1
  100. data/lib/scout_apm/utils/sql_sanitizer_regex.rb +8 -1
  101. data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +6 -0
  102. data/lib/scout_apm/utils/unique_id.rb +27 -0
  103. data/lib/scout_apm/version.rb +1 -1
  104. data/scout_apm.gemspec +13 -7
  105. data/test/test_helper.rb +2 -2
  106. data/test/unit/agent_context_test.rb +29 -0
  107. data/test/unit/auto_instrument/assignments-instrumented.rb +31 -0
  108. data/test/unit/auto_instrument/assignments.rb +31 -0
  109. data/test/unit/auto_instrument/controller-ast.txt +57 -0
  110. data/test/unit/auto_instrument/controller-instrumented.rb +49 -0
  111. data/test/unit/auto_instrument/controller.rb +49 -0
  112. data/test/unit/auto_instrument/rescue_from-instrumented.rb +13 -0
  113. data/test/unit/auto_instrument/rescue_from.rb +13 -0
  114. data/test/unit/auto_instrument_test.rb +54 -0
  115. data/test/unit/environment_test.rb +2 -2
  116. data/test/unit/error_service/error_buffer_test.rb +25 -0
  117. data/test/unit/error_service/ignored_exceptions_test.rb +49 -0
  118. data/test/unit/instruments/active_record_test.rb +40 -0
  119. data/test/unit/layer_children_set_test.rb +9 -0
  120. data/test/unit/request_histograms_test.rb +17 -0
  121. data/test/unit/serializers/payload_serializer_test.rb +39 -5
  122. data/test/unit/slow_request_policy_test.rb +41 -13
  123. data/test/unit/sql_sanitizer_test.rb +78 -0
  124. data/test/unit/utils/active_record_metric_name_test.rb +10 -2
  125. metadata +100 -18
  126. data/ext/stacks/extconf.rb +0 -37
  127. data/ext/stacks/scout_atomics.h +0 -86
  128. data/ext/stacks/stacks.c +0 -814
  129. data/lib/scout_apm/slow_job_policy.rb +0 -111
  130. data/lib/scout_apm/trace_compactor.rb +0 -312
  131. data/lib/scout_apm/utils/fake_stacks.rb +0 -88
  132. data/test/unit/instruments/active_record_instruments_test.rb +0 -5
  133. data/test/unit/slow_job_policy_test.rb +0 -6
  134. data/tester.rb +0 -53
@@ -12,22 +12,27 @@ module ScoutApm
12
12
  # Converts an SQL string and the name (typically assigned automatically
13
13
  # by rails) into a Scout metric_name.
14
14
  #
15
+ # This prefers to use the ActiveRecord-provided name over parsing SQL as parsing is slower.
16
+ #
15
17
  # sql: SELECT "places".* FROM "places" ORDER BY "places"."position" ASC
16
18
  # name: Place Load
17
19
  # metric_name: Place/find
18
20
  def to_s
21
+ return @to_s if @to_s
19
22
  parsed = parse_operation
20
23
  if parsed
21
- "#{model}/#{parsed}"
24
+ @to_s = "#{model}/#{parsed}"
22
25
  else
23
- regex_name(sql)
26
+ @to_s = regex_name(sql)
24
27
  end
25
28
  end
26
29
 
30
+ # This only returns a value if a name is provided via +initialize+.
27
31
  def model
28
32
  parts.first
29
33
  end
30
34
 
35
+ # This only returns a value if a name is provided via +initialize+.
31
36
  def normalized_operation
32
37
  parse_operation
33
38
  end
@@ -49,12 +54,14 @@ module ScoutApm
49
54
 
50
55
  private
51
56
 
57
+ # This only returns a value if a name is provided via +initialize+.
52
58
  def operation
53
59
  if parts.length >= 2
54
60
  parts[1].downcase
55
61
  end
56
62
  end
57
63
 
64
+ # This only returns a value if a name is provided via +initialize+.
58
65
  def parts
59
66
  name.split(" ")
60
67
  end
@@ -86,6 +93,8 @@ module ScoutApm
86
93
  NON_GREEDY_CONSUME = '.*?'
87
94
  TABLE = '(?:"|`)?(.*?)(?:"|`)?\s'
88
95
  COUNT = 'COUNT\(.*?\)'
96
+ BEGIN_STATEMENT = 'BEGIN'.freeze # BEGIN is a reserved keyword
97
+ COMMIT = 'COMMIT'.freeze
89
98
 
90
99
  SELECT_REGEX = /\A#{WHITE_SPACE}(SELECT)#{WHITE_SPACE}(#{COUNT})?#{NON_GREEDY_CONSUME}#{FROM}#{WHITE_SPACE}#{TABLE}/i.freeze
91
100
  UPDATE_REGEX = /\A#{WHITE_SPACE}(UPDATE)#{WHITE_SPACE}#{TABLE}/i.freeze
@@ -121,13 +130,17 @@ module ScoutApm
121
130
  else
122
131
  SELECT_LABEL
123
132
  end
124
- "#{match[3].classify}/#{operation}"
133
+ "#{match[3].gsub(/\W/,'').classify}/#{operation}"
125
134
  elsif match = UPDATE_REGEX.match(sql)
126
135
  "#{match[2].classify}/#{UPDATE_LABEL}"
127
136
  elsif match = INSERT_REGEX.match(sql)
128
137
  "#{match[2].classify}/#{INSERT_LABEL}"
129
138
  elsif match = DELETE_REGEX.match(sql)
130
139
  "#{match[2].classify}/#{DELETE_LABEL}"
140
+ elsif sql == BEGIN_STATEMENT
141
+ "SQL/#{BEGIN_STATEMENT.downcase}"
142
+ elsif sql == COMMIT
143
+ "SQL/#{COMMIT.downcase}"
131
144
  else
132
145
  UNKNOWN_LABEL
133
146
  end
@@ -11,6 +11,9 @@ module ScoutApm
11
11
 
12
12
  attr_reader :call_stack
13
13
 
14
+ # call_stack - an +Array+ of calls, typically generated via the +caller+ method.
15
+ # Example single line:
16
+ # "/Users/dlite/.rvm/rubies/ruby-2.4.5/lib/ruby/2.4.0/irb/workspace.rb:87:in `eval'"
14
17
  def initialize(call_stack, root=ScoutApm::Agent.instance.context.environment.root)
15
18
  @call_stack = call_stack
16
19
  # We can't use a constant as it'd be too early to fetch environment info
@@ -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
@@ -34,15 +34,24 @@ module ScoutApm
34
34
  when :postgres then to_s_postgres
35
35
  when :mysql then to_s_mysql
36
36
  when :sqlite then to_s_sqlite
37
+ when :sqlserver then to_s_sqlserver
37
38
  end
38
39
  end
39
40
 
40
41
  private
41
42
 
43
+ def to_s_sqlserver
44
+ sql.gsub!(SQLSERVER_EXECUTESQL, '\1')
45
+ sql.gsub!(SQLSERVER_REMOVE_INTEGERS, '?')
46
+ sql.gsub!(SQLSERVER_IN_CLAUSE, 'IN (?)')
47
+ sql
48
+ end
49
+
42
50
  def to_s_postgres
43
51
  sql.gsub!(PSQL_PLACEHOLDER, '?')
44
52
  sql.gsub!(PSQL_VAR_INTERPOLATION, '')
45
- sql.gsub!(PSQL_REMOVE_STRINGS, '?')
53
+ sql.gsub!(PSQL_AFTER_WHERE) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
54
+ sql.gsub!(PSQL_AFTER_SET) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
46
55
  sql.gsub!(PSQL_REMOVE_INTEGERS, '?')
47
56
  sql.gsub!(PSQL_IN_CLAUSE, 'IN (?)')
48
57
  sql.gsub!(MULTIPLE_SPACES, ' ')
@@ -5,11 +5,13 @@ module ScoutApm
5
5
  MULTIPLE_SPACES = %r|\s+|.freeze
6
6
  MULTIPLE_QUESTIONS = /\?(,\?)+/.freeze
7
7
 
8
- PSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
8
+ PSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*\z|.freeze
9
9
  PSQL_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
10
10
  PSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
11
11
  PSQL_PLACEHOLDER = /\$\d+/.freeze
12
12
  PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
13
+ PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|\z)/im.freeze
14
+ PSQL_AFTER_SET = /(?:SET\s+).*?(?:WHERE|\z)/im.freeze
13
15
 
14
16
  MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
15
17
  MYSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
@@ -20,6 +22,11 @@ module ScoutApm
20
22
  SQLITE_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
21
23
  SQLITE_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
22
24
  SQLITE_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
25
+
26
+ # => "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE (age > 50) ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY', N'@0 int', @0 = 10"
27
+ SQLSERVER_EXECUTESQL = /EXEC sp_executesql N'(.*?)'.*/
28
+ SQLSERVER_REMOVE_INTEGERS = /(?<!LIMIT )\b(?<!@)\d+\b/.freeze
29
+ SQLSERVER_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
23
30
  end
24
31
  end
25
32
  end
@@ -10,6 +10,8 @@ module ScoutApm
10
10
  PSQL_REMOVE_INTEGERS = /\b\d+\b/.freeze
11
11
  PSQL_PLACEHOLDER = /\$\d+/.freeze
12
12
  PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
13
+ PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|$)/i.freeze
14
+ PSQL_AFTER_SET = /(?:SET\s+).*?(?:WHERE|$)/i.freeze
13
15
 
14
16
  MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
15
17
  MYSQL_REMOVE_INTEGERS = /\b\d+\b/.freeze
@@ -21,6 +23,10 @@ module ScoutApm
21
23
  SQLITE_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
22
24
  SQLITE_REMOVE_INTEGERS = /\b\d+\b/.freeze
23
25
 
26
+ # This is not officially supported, but will do its best.
27
+ SQLSERVER_EXECUTESQL = /EXEC sp_executesql N'(.*?)'.*/
28
+ SQLSERVER_REMOVE_INTEGERS = /\b\d+\b/.freeze
29
+ SQLSERVER_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
24
30
  end
25
31
  end
26
32
  end
@@ -11,5 +11,32 @@ module ScoutApm
11
11
  s
12
12
  end
13
13
  end
14
+
15
+ # Represents a random ID that we can use to track a certain transaction.
16
+ # The `trans` prefix is only for ease of reading logs - it should not be
17
+ # interpreted to convey any sort of meaning.
18
+ class TransactionId
19
+ def initialize
20
+ @random = SecureRandom.hex(16)
21
+ end
22
+
23
+ def to_s
24
+ "trans-#{@random}"
25
+ end
26
+ end
27
+
28
+ # Represents a random ID that we can use to track a certain span. The
29
+ # `span` prefix is only for ease of reading logs - it should not be
30
+ # interpreted to convey any sort of meaning.
31
+ class SpanId
32
+ def initialize
33
+ @random = SecureRandom.hex(16)
34
+ end
35
+
36
+ def to_s
37
+ "span-#{@random}"
38
+ end
39
+ end
40
+
14
41
  end
15
42
  end
@@ -1,3 +1,3 @@
1
1
  module ScoutApm
2
- VERSION = "3.0.0.pre26"
2
+ VERSION = "4.0.2"
3
3
  end
@@ -19,9 +19,10 @@ Gem::Specification.new do |s|
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib","data"]
21
21
  s.extensions << 'ext/allocations/extconf.rb'
22
- s.extensions << 'ext/stacks/extconf.rb'
23
22
  s.extensions << 'ext/rusage/extconf.rb'
24
23
 
24
+ s.required_ruby_version = '>= 2.1'
25
+
25
26
  s.add_development_dependency "minitest"
26
27
  s.add_development_dependency "mocha"
27
28
  s.add_development_dependency "pry"
@@ -29,11 +30,16 @@ Gem::Specification.new do |s|
29
30
  s.add_development_dependency "rake-compiler"
30
31
  s.add_development_dependency "addressable"
31
32
  s.add_development_dependency "activesupport"
33
+ s.add_runtime_dependency "parser"
34
+
35
+ # These are general development dependencies which are used in instrumentation
36
+ # tests. Specific versions are pulled in using specific gemfiles, e.g.
37
+ # `gems/rails3.gemfile`.
38
+ s.add_development_dependency "activerecord"
39
+ s.add_development_dependency "sqlite3"
32
40
 
33
- if RUBY_VERSION >= "1.9.3"
34
- s.add_development_dependency "rubocop"
35
- s.add_development_dependency "guard"
36
- s.add_development_dependency "guard-minitest"
37
- s.add_development_dependency "m"
38
- end
41
+ s.add_development_dependency "rubocop"
42
+ s.add_development_dependency "guard"
43
+ s.add_development_dependency "guard-minitest"
44
+ s.add_development_dependency "m"
39
45
  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
 
@@ -100,7 +100,7 @@ class Minitest::Test
100
100
  end
101
101
 
102
102
  def agent_context
103
- ScoutApm::AgentContext.new
103
+ ScoutApm::Agent.instance.context
104
104
  end
105
105
 
106
106
  DATA_FILE_DIR = File.dirname(__FILE__) + '/tmp'
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+ require "scout_apm/agent_context"
4
+
5
+ class AgentContextTest < Minitest::Test
6
+ def test_has_error_service_ignored_exceptions
7
+ context = ScoutApm::AgentContext.new
8
+ assert ScoutApm::ErrorService::IgnoredExceptions, context.ignored_exceptions.class
9
+ end
10
+
11
+ def test_has_error_buffer
12
+ context = ScoutApm::AgentContext.new
13
+ assert ScoutApm::ErrorService::ErrorBuffer, context.error_buffer.class
14
+ end
15
+
16
+
17
+ class TestPolicy
18
+ def call(req); 1; end
19
+ def stored!(req); end
20
+ end
21
+
22
+ def test_customize_slow_request_policy
23
+ context = ScoutApm::AgentContext.new
24
+ assert 4, context.slow_request_policy.policies
25
+
26
+ context.slow_request_policy.add(TestPolicy.new)
27
+ assert 5, context.slow_request_policy.policies
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+
2
+ class Assignments
3
+ def test_op_asgn
4
+ foo.bar += ::ScoutApm::AutoInstrument("User.size",["ROOT/test/unit/auto_instrument/assignments.rb:4:in `test_op_asgn'"]){User.size}
5
+ foo.bar -= ::ScoutApm::AutoInstrument("User.size",["ROOT/test/unit/auto_instrument/assignments.rb:5:in `test_op_asgn'"]){User.size}
6
+ end
7
+
8
+ def nested_assignment
9
+ @email ||= if (email = ::ScoutApm::AutoInstrument("session[\"email\"]",["ROOT/test/unit/auto_instrument/assignments.rb:9:in `nested_assignment'"]){session["email"]}).present?
10
+ ::ScoutApm::AutoInstrument("User.where(email: email).first",["ROOT/test/unit/auto_instrument/assignments.rb:10:in `nested_assignment'"]){User.where(email: email).first}
11
+ else
12
+ nil
13
+ end
14
+ end
15
+
16
+ def paginate_collection(coll)
17
+ page = (::ScoutApm::AutoInstrument("params[:page].present?",["ROOT/test/unit/auto_instrument/assignments.rb:17:in `paginate_collection'"]){params[:page].present?} ? ::ScoutApm::AutoInstrument("params[:page].to_i",["ROOT/test/unit/auto_instrument/assignments.rb:17:in `paginate_collection'"]){params[:page].to_i} : 1)
18
+ per_page = (::ScoutApm::AutoInstrument("params[:per_page].present?",["ROOT/test/unit/auto_instrument/assignments.rb:18:in `paginate_collection'"]){params[:per_page].present?} ? ::ScoutApm::AutoInstrument("params[:per_page].to_i",["ROOT/test/unit/auto_instrument/assignments.rb:18:in `paginate_collection'"]){params[:per_page].to_i} : 20)
19
+ pagination, self.collection = ::ScoutApm::AutoInstrument("pagy(...",["ROOT/test/unit/auto_instrument/assignments.rb:19:in `paginate_collection'"]){pagy(
20
+ coll,
21
+ items: per_page,
22
+ page: page
23
+ )}
24
+ ::ScoutApm::AutoInstrument("headers[PAGINATION_TOTAL_HEADER] = pagination.count.to_s",["ROOT/test/unit/auto_instrument/assignments.rb:24:in `paginate_collection'"]){headers[PAGINATION_TOTAL_HEADER] = pagination.count.to_s}
25
+ ::ScoutApm::AutoInstrument("headers[PAGINATION_TOTAL_PAGES_HEADER] = pagination.pages.to_s",["ROOT/test/unit/auto_instrument/assignments.rb:25:in `paginate_collection'"]){headers[PAGINATION_TOTAL_PAGES_HEADER] = pagination.pages.to_s}
26
+ ::ScoutApm::AutoInstrument("headers[PAGINATION_PER_PAGE_HEADER] = per_page.to_s",["ROOT/test/unit/auto_instrument/assignments.rb:26:in `paginate_collection'"]){headers[PAGINATION_PER_PAGE_HEADER] = per_page.to_s}
27
+ ::ScoutApm::AutoInstrument("headers[PAGINATION_PAGE_HEADER] = pagination.page.to_s",["ROOT/test/unit/auto_instrument/assignments.rb:27:in `paginate_collection'"]){headers[PAGINATION_PAGE_HEADER] = pagination.page.to_s}
28
+ ::ScoutApm::AutoInstrument("headers[PAGINATION_NEXT_PAGE_HEADER] = pagination.next.to_s",["ROOT/test/unit/auto_instrument/assignments.rb:28:in `paginate_collection'"]){headers[PAGINATION_NEXT_PAGE_HEADER] = pagination.next.to_s}
29
+ ::ScoutApm::AutoInstrument("collection",["ROOT/test/unit/auto_instrument/assignments.rb:29:in `paginate_collection'"]){collection}
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+
2
+ class Assignments
3
+ def test_op_asgn
4
+ foo.bar += User.size
5
+ foo.bar -= User.size
6
+ end
7
+
8
+ def nested_assignment
9
+ @email ||= if (email = session["email"]).present?
10
+ User.where(email: email).first
11
+ else
12
+ nil
13
+ end
14
+ end
15
+
16
+ def paginate_collection(coll)
17
+ page = (params[:page].present? ? params[:page].to_i : 1)
18
+ per_page = (params[:per_page].present? ? params[:per_page].to_i : 20)
19
+ pagination, self.collection = pagy(
20
+ coll,
21
+ items: per_page,
22
+ page: page
23
+ )
24
+ headers[PAGINATION_TOTAL_HEADER] = pagination.count.to_s
25
+ headers[PAGINATION_TOTAL_PAGES_HEADER] = pagination.pages.to_s
26
+ headers[PAGINATION_PER_PAGE_HEADER] = per_page.to_s
27
+ headers[PAGINATION_PAGE_HEADER] = pagination.page.to_s
28
+ headers[PAGINATION_NEXT_PAGE_HEADER] = pagination.next.to_s
29
+ collection
30
+ end
31
+ end
@@ -0,0 +1,57 @@
1
+ s(:class,
2
+ s(:const, nil, :ClientsController),
3
+ s(:const, nil, :ApplicationController),
4
+ s(:begin,
5
+ s(:send, nil, :before_action,
6
+ s(:sym, :check_authorization)),
7
+ s(:def, :index,
8
+ s(:args),
9
+ s(:if,
10
+ s(:send,
11
+ s(:send,
12
+ s(:send, nil, :params), :[],
13
+ s(:sym, :status)), :==,
14
+ s(:str, "activated")),
15
+ s(:ivasgn, :@clients,
16
+ s(:send,
17
+ s(:const, nil, :Client), :activated)),
18
+ s(:ivasgn, :@clients,
19
+ s(:send,
20
+ s(:const, nil, :Client), :inactivated)))),
21
+ s(:def, :create,
22
+ s(:args),
23
+ s(:begin,
24
+ s(:ivasgn, :@client,
25
+ s(:send,
26
+ s(:const, nil, :Client), :new,
27
+ s(:send,
28
+ s(:send, nil, :params), :[],
29
+ s(:sym, :client)))),
30
+ s(:if,
31
+ s(:send,
32
+ s(:ivar, :@client), :save),
33
+ s(:send, nil, :redirect_to,
34
+ s(:ivar, :@client)),
35
+ s(:send, nil, :render,
36
+ s(:str, "new"))))),
37
+ s(:def, :edit,
38
+ s(:args),
39
+ s(:begin,
40
+ s(:ivasgn, :@client,
41
+ s(:send,
42
+ s(:const, nil, :Client), :new,
43
+ s(:send,
44
+ s(:send, nil, :params), :[],
45
+ s(:sym, :client)))),
46
+ s(:if,
47
+ s(:send,
48
+ s(:send, nil, :request), :post?),
49
+ s(:block,
50
+ s(:send,
51
+ s(:ivar, :@client), :transaction),
52
+ s(:args),
53
+ s(:send,
54
+ s(:ivar, :@client), :update_attributes,
55
+ s(:send,
56
+ s(:send, nil, :params), :[],
57
+ s(:sym, :client)))), nil)))))