scout_apm 2.0.0.pre → 2.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.markdown +22 -5
  4. data/Rakefile +5 -0
  5. data/lib/scout_apm.rb +4 -0
  6. data/lib/scout_apm/agent.rb +22 -8
  7. data/lib/scout_apm/agent/reporting.rb +8 -3
  8. data/lib/scout_apm/attribute_arranger.rb +4 -0
  9. data/lib/scout_apm/bucket_name_splitter.rb +3 -3
  10. data/lib/scout_apm/config.rb +5 -2
  11. data/lib/scout_apm/histogram.rb +20 -0
  12. data/lib/scout_apm/instant_reporting.rb +40 -0
  13. data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +11 -1
  14. data/lib/scout_apm/instruments/percentile_sampler.rb +38 -0
  15. data/lib/scout_apm/layaway.rb +1 -4
  16. data/lib/scout_apm/layaway_file.rb +26 -2
  17. data/lib/scout_apm/layer.rb +1 -1
  18. data/lib/scout_apm/layer_converters/converter_base.rb +6 -4
  19. data/lib/scout_apm/layer_converters/slow_job_converter.rb +21 -13
  20. data/lib/scout_apm/layer_converters/slow_request_converter.rb +37 -24
  21. data/lib/scout_apm/metric_meta.rb +5 -1
  22. data/lib/scout_apm/metric_set.rb +15 -6
  23. data/lib/scout_apm/reporter.rb +9 -3
  24. data/lib/scout_apm/request_histograms.rb +46 -0
  25. data/lib/scout_apm/scored_item_set.rb +79 -0
  26. data/lib/scout_apm/serializers/payload_serializer_to_json.rb +2 -0
  27. data/lib/scout_apm/serializers/slow_jobs_serializer_to_json.rb +2 -0
  28. data/lib/scout_apm/slow_job_policy.rb +89 -19
  29. data/lib/scout_apm/slow_job_record.rb +18 -1
  30. data/lib/scout_apm/slow_request_policy.rb +80 -12
  31. data/lib/scout_apm/slow_transaction.rb +22 -3
  32. data/lib/scout_apm/store.rb +35 -13
  33. data/lib/scout_apm/tracked_request.rb +63 -11
  34. data/lib/scout_apm/utils/backtrace_parser.rb +4 -4
  35. data/lib/scout_apm/utils/sql_sanitizer.rb +1 -1
  36. data/lib/scout_apm/utils/sql_sanitizer_regex.rb +2 -2
  37. data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +2 -2
  38. data/lib/scout_apm/version.rb +1 -1
  39. data/scout_apm.gemspec +1 -0
  40. data/test/test_helper.rb +4 -3
  41. data/test/unit/layaway_test.rb +5 -8
  42. data/test/unit/metric_set_test.rb +101 -0
  43. data/test/unit/scored_item_set_test.rb +65 -0
  44. data/test/unit/serializers/payload_serializer_test.rb +2 -1
  45. data/test/unit/slow_item_set_test.rb +2 -1
  46. data/test/unit/slow_request_policy_test.rb +42 -0
  47. data/test/unit/sql_sanitizer_test.rb +6 -0
  48. metadata +28 -3
@@ -75,7 +75,7 @@ module ScoutApm
75
75
  end
76
76
 
77
77
  def scrubbed(str)
78
- return '' if !str.is_a?(String) || str.length > 1000 # safeguard - don't sanitize or scrub large SQL statements
78
+ return '' if !str.is_a?(String) || str.length > 4000 # safeguard - don't sanitize or scrub large SQL statements
79
79
  return str if !str.respond_to?(:encode) # Ruby <= 1.8 doesn't have string encoding
80
80
  return str if str.valid_encoding? # Whatever encoding it is, it is valid and we can operate on it
81
81
  ScoutApm::Agent.instance.logger.debug "Scrubbing invalid sql encoding."
@@ -13,8 +13,8 @@ module ScoutApm
13
13
 
14
14
  MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
15
15
  MYSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
16
- MYSQL_REMOVE_SINGLE_QUOTE_STRINGS = /'(?:[^']|'')*'/.freeze
17
- MYSQL_REMOVE_DOUBLE_QUOTE_STRINGS = /"(?:[^"]|"")*"/.freeze
16
+ MYSQL_REMOVE_SINGLE_QUOTE_STRINGS = %r{'(?:\\'|[^']|'')*'}.freeze
17
+ MYSQL_REMOVE_DOUBLE_QUOTE_STRINGS = %r{"(?:\\"|[^"]|"")*"}.freeze
18
18
  MYSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
19
19
 
20
20
  SQLITE_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
@@ -13,8 +13,8 @@ module ScoutApm
13
13
 
14
14
  MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
15
15
  MYSQL_REMOVE_INTEGERS = /\b\d+\b/.freeze
16
- MYSQL_REMOVE_SINGLE_QUOTE_STRINGS = /'(?:[^']|'')*'/.freeze
17
- MYSQL_REMOVE_DOUBLE_QUOTE_STRINGS = /"(?:[^"]|"")*"/.freeze
16
+ MYSQL_REMOVE_SINGLE_QUOTE_STRINGS = /'(?:\\'|[^']|'')*'/.freeze
17
+ MYSQL_REMOVE_DOUBLE_QUOTE_STRINGS = /"(?:\\"|[^"]|"")*"/.freeze
18
18
  MYSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
19
19
 
20
20
  SQLITE_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "2.0.0.pre"
2
+ VERSION = "2.0.0.pre2"
3
3
  end
4
4
 
@@ -25,4 +25,5 @@ Gem::Specification.new do |s|
25
25
  s.add_development_dependency "pry"
26
26
  s.add_development_dependency "m"
27
27
  s.add_development_dependency "simplecov"
28
+ s.add_development_dependency "rake-compiler"
28
29
  end
@@ -1,11 +1,12 @@
1
+ # Load & Start simplecov before loading scout_apm
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+
1
5
  require 'minitest/autorun'
2
6
  require 'minitest/unit'
3
7
  require 'minitest/pride'
4
8
  require 'pry'
5
9
 
6
- # Load & Start simplecov before loading scout_apm
7
- require 'simplecov'
8
- SimpleCov.start
9
10
 
10
11
  require 'scout_apm'
11
12
 
@@ -18,15 +18,12 @@ class LayawayTest < Minitest::Test
18
18
 
19
19
  def test_merge_reporting_period
20
20
  File.open(DATA_FILE_PATH, 'w') { |file| file.write(Marshal.dump(NEW_FORMAT)) }
21
- ScoutApm::Agent.instance.start
22
-
23
- data = ScoutApm::Layaway.new
24
- t = ScoutApm::StoreReportingPeriodTimestamp.new
25
- data.add_reporting_period(TIMESTAMP,ScoutApm::StoreReportingPeriod.new(TIMESTAMP))
26
- assert_equal [TIMESTAMP], Marshal.load(File.read(DATA_FILE_PATH)).keys
27
- # TODO - add tests to verify metrics+slow transactions are merged
21
+ layaway = ScoutApm::Layaway.new
22
+ layaway.add_reporting_period(TIMESTAMP, ScoutApm::StoreReportingPeriod.new(TIMESTAMP))
23
+ unmarshalled = Marshal.load(File.read(DATA_FILE_PATH))
24
+ assert_equal [TIMESTAMP], unmarshalled.keys
28
25
  end
29
26
 
30
27
  TIMESTAMP = ScoutApm::StoreReportingPeriodTimestamp.new(Time.parse("2015-01-01"))
31
28
  NEW_FORMAT = {TIMESTAMP => ScoutApm::StoreReportingPeriod.new(TIMESTAMP)} # Format for 1.2+ agents
32
- end
29
+ end
@@ -0,0 +1,101 @@
1
+ require 'test_helper'
2
+
3
+ require 'scout_apm/metric_set'
4
+
5
+ module ScoutApm
6
+ class MetricSetTest < Minitest::Test
7
+ def setup
8
+ @metric_set = ScoutApm::MetricSet.new
9
+ end
10
+
11
+ def test_absorb_one_passthrough_metric
12
+ @metric_set.absorb(make_fake_stat("Controller/Foo", 1))
13
+
14
+ assert_equal 1, @metric_set.metrics.length
15
+ assert_equal "Controller/Foo", @metric_set.metrics.first.first.metric_name
16
+ end
17
+
18
+ def test_absorb_one_aggregate_metric
19
+ @metric_set.absorb(make_fake_stat("ActiveRecord/Foo", 1))
20
+
21
+ assert_equal 1, @metric_set.metrics.length
22
+ assert_equal "ActiveRecord/all", @metric_set.metrics.first.first.metric_name
23
+ end
24
+
25
+ def test_absorb_many_aggregate_metric
26
+ @metric_set.absorb(make_fake_stat("ActiveRecord/Foo", 1))
27
+ @metric_set.absorb(make_fake_stat("ActiveRecord/Bar", 1))
28
+ @metric_set.absorb(make_fake_stat("ActiveRecord/Baz", 1))
29
+ @metric_set.absorb(make_fake_stat("HTTP/Get", 1))
30
+ @metric_set.absorb(make_fake_stat("HTTP/Post", 1))
31
+
32
+ metrics = @metric_set.metrics.to_a.sort_by { |m| m.first.metric_name }
33
+ assert_equal 2, metrics.length
34
+ assert_equal "ActiveRecord/all", metrics[0][0].metric_name
35
+ assert_equal "HTTP/all", metrics[1][0].metric_name
36
+ assert_equal 3, metrics[0][1].call_count
37
+ assert_equal 2, metrics[1][1].call_count
38
+ end
39
+
40
+ def test_absorb_one_error
41
+ @metric_set.absorb(make_fake_stat("Errors/Controller/public/index", 1))
42
+
43
+ metrics = @metric_set.metrics.to_a.sort_by { |m| m.first.metric_name }
44
+ assert_equal 2, metrics.length
45
+ assert_equal "Errors/Controller/public/index", metrics[0].first.metric_name
46
+ assert_equal "Errors/Request", metrics[1].first.metric_name
47
+ end
48
+
49
+ def test_absorb_many_metrics
50
+ @metric_set.absorb_all([
51
+ make_fake_stat("ActiveRecord/Foo", 1),
52
+ make_fake_stat("Controller/Bar", 1)
53
+ ])
54
+
55
+ metrics = @metric_set.metrics.to_a.sort_by { |m| m.first.metric_name }
56
+ assert_equal 2, metrics.length
57
+ assert_equal "ActiveRecord/all", metrics[0].first.metric_name
58
+ assert_equal "Controller/Bar", metrics[1].first.metric_name
59
+ end
60
+
61
+ def test_combine
62
+ @other_set = ScoutApm::MetricSet.new
63
+
64
+ @metric_set.absorb_all([
65
+ make_fake_stat("ActiveRecord/Foo", 1),
66
+ make_fake_stat("Controller/Bar", 1),
67
+ make_fake_stat("Errors/Controller/public/index", 1),
68
+ ])
69
+
70
+ @other_set.absorb_all([
71
+ make_fake_stat("ActiveRecord/Foo", 1),
72
+ make_fake_stat("Controller/Bar", 1),
73
+ make_fake_stat("Errors/Controller/public/index", 1),
74
+ ])
75
+
76
+ @metric_set.combine!(@other_set)
77
+
78
+ metrics = @metric_set.metrics.to_a.sort_by { |m| m.first.metric_name }
79
+ assert_equal 4, metrics.length
80
+ assert_equal "ActiveRecord/all", metrics[0][0].metric_name
81
+ assert_equal "Controller/Bar", metrics[1][0].metric_name
82
+ assert_equal "Errors/Controller/public/index", metrics[2][0].metric_name
83
+ assert_equal "Errors/Request", metrics[3][0].metric_name
84
+
85
+ assert_equal 2, metrics[0][1].call_count
86
+ assert_equal 2, metrics[1][1].call_count
87
+ assert_equal 2, metrics[2][1].call_count
88
+ assert_equal 2, metrics[3][1].call_count
89
+ end
90
+
91
+ ############################################################
92
+ # Test helper functions
93
+ ############################################################
94
+ def make_fake_stat(name, count)
95
+ meta = MetricMeta.new(name)
96
+ stat = MetricStats.new
97
+ stat.update!(count)
98
+ [meta, stat]
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+
3
+ require 'scout_apm/scored_item_set'
4
+
5
+ class FakeScoredItem
6
+ def initialize(name, score)
7
+ @name = name
8
+ @score = score
9
+ end
10
+ def name; @name; end
11
+ def score; @score; end
12
+ def call; "called_#{@score}_#{@name}"; end
13
+ end
14
+
15
+ class ScoredItemSetTest < Minitest::Test
16
+ def test_empty_set_always_adds_item
17
+ set = ScoutApm::ScoredItemSet.new
18
+ set << FakeScoredItem.new("users/index", 10)
19
+
20
+ assert_equal set.to_a.first, "called_10_users/index"
21
+ assert_equal set.count, 1
22
+ end
23
+
24
+ def test_repeated_additions_chooses_most_expensive
25
+ set = ScoutApm::ScoredItemSet.new
26
+
27
+ [ FakeScoredItem.new("users/index", 10),
28
+ FakeScoredItem.new("users/index", 11),
29
+ FakeScoredItem.new("users/index", 12)
30
+ ].shuffle.each { |fsi| set << fsi }
31
+
32
+ assert_equal set.to_a.first, "called_12_users/index"
33
+ assert_equal set.count, 1
34
+ end
35
+
36
+ def test_multiple_items_occupy_different_buckets
37
+ set = ScoutApm::ScoredItemSet.new
38
+
39
+ [ FakeScoredItem.new("users/index", 10),
40
+ FakeScoredItem.new("users/index", 11),
41
+ FakeScoredItem.new("users/show", 12),
42
+ FakeScoredItem.new("users/show", 10)
43
+ ].shuffle.each { |fsi| set << fsi }
44
+
45
+ assert_equal set.count, 2
46
+ assert set.to_a.include?("called_11_users/index")
47
+ assert set.to_a.include?("called_12_users/show")
48
+ end
49
+
50
+ def test_evicts_at_capacity
51
+ set = ScoutApm::ScoredItemSet.new(3) # Force max_size to 3
52
+
53
+ [ FakeScoredItem.new("users/index", 10),
54
+ FakeScoredItem.new("users/show", 11),
55
+ FakeScoredItem.new("posts/index", 12),
56
+ FakeScoredItem.new("posts/move", 13)
57
+ ].shuffle.each { |fsi| set << fsi }
58
+
59
+ assert_equal set.count, 3
60
+ assert !set.to_a.include?("called_10_users/index"), "Did not Expect to see users/index in #{set.to_a.inspect}"
61
+ assert set.to_a.include?("called_11_users/show"), "Expected to see users/show in #{set.to_a.inspect}"
62
+ assert set.to_a.include?("called_12_posts/index"), "Expected to see posts/index in #{set.to_a.inspect}"
63
+ assert set.to_a.include?("called_13_posts/move"), "Expected to see posts/move in #{set.to_a.inspect}"
64
+ end
65
+ end
@@ -145,7 +145,7 @@ class PayloadSerializerTest < Minitest::Test
145
145
  context = ScoutApm::Context.new
146
146
  context.add({"this" => "that"})
147
147
  context.add_user({"hello" => "goodbye"})
148
- slow_t = ScoutApm::SlowTransaction.new("http://example.com/blabla", "Buckethead/something/else", 1.23, slow_transaction_metrics, context, Time.at(1448198788), [])
148
+ slow_t = ScoutApm::SlowTransaction.new("http://example.com/blabla", "Buckethead/something/else", 1.23, slow_transaction_metrics, context, Time.at(1448198788), [], 10)
149
149
  payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize({}, {}, [slow_t], [], [])
150
150
  formatted_slow_transactions = [
151
151
  {
@@ -158,6 +158,7 @@ class PayloadSerializerTest < Minitest::Test
158
158
  "uri" => "http://example.com/blabla",
159
159
  "context" => {"this"=>"that", "user"=>{"hello"=>"goodbye"}},
160
160
  "prof" => [],
161
+ "score" => 10,
161
162
  "metrics" => [
162
163
  {
163
164
  "key" => {
@@ -88,6 +88,7 @@ class SlowItemSetTest < Minitest::Test
88
88
  {}, # metrics
89
89
  {}, # context
90
90
  Time.now, # end time
91
- []) # stackprof
91
+ [], # stackprof
92
+ 0)
92
93
  end
93
94
  end
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ require 'scout_apm/slow_request_policy'
4
+ require 'scout_apm/layer'
5
+
6
+ class FakeRequest
7
+ def initialize(name)
8
+ @name = name
9
+ @root_layer = ScoutApm::Layer.new("Controller", name)
10
+ @root_layer.instance_variable_set("@stop_time", Time.now)
11
+ end
12
+ def unique_name; "Controller/foo/bar"; end
13
+ def root_layer; @root_layer; end
14
+ def set_duration(seconds)
15
+ @root_layer.instance_variable_set("@start_time", Time.now - seconds)
16
+ end
17
+ end
18
+
19
+ class SlowRequestPolicyTest < Minitest::Test
20
+ def test_stored_records_current_time
21
+ test_start = Time.now
22
+ policy = ScoutApm::SlowRequestPolicy.new
23
+ request = FakeRequest.new("users/index")
24
+
25
+ policy.stored!(request)
26
+ assert policy.last_seen[request.unique_name] > test_start
27
+ end
28
+
29
+ def test_score
30
+ policy = ScoutApm::SlowRequestPolicy.new
31
+ request = FakeRequest.new("users/index")
32
+
33
+ request.set_duration(10) # 10 seconds
34
+ policy.last_seen[request.unique_name] = Time.now - 120 # 2 minutes since last seen
35
+ agent.request_histograms.add(request.unique_name, 1)
36
+
37
+ # Actual value I have in console is 1.599
38
+ assert policy.score(request) > 1.5
39
+ assert policy.score(request) < 2.0
40
+
41
+ end
42
+ end
@@ -85,6 +85,12 @@ module ScoutApm
85
85
  assert_equal %q|SELECT `blogs`.* FROM `blogs` WHERE (title = ?)|, ss.to_s
86
86
  end
87
87
 
88
+ def test_mysql_quotes
89
+ sql = %q|INSERT INTO `users` VALUES ('foo', 'b\'ar')|
90
+ ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :mysql }
91
+ assert_equal %q|INSERT INTO `users` VALUES (?, ?)|, ss.to_s
92
+ end
93
+
88
94
  def test_scrubs_invalid_encoding
89
95
  sql = "SELECT `blogs`.* FROM `blogs` WHERE (title = 'a\255c')".force_encoding('UTF-8')
90
96
  assert_equal false, sql.valid_encoding?
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.0.0.pre
4
+ version: 2.0.0.pre2
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-05-10 00:00:00.000000000 Z
12
+ date: 2016-06-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rusage
@@ -81,6 +81,20 @@ dependencies:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rake-compiler
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
84
98
  description: Monitors Ruby apps and reports detailed metrics on performance to Scout.
85
99
  email:
86
100
  - support@scoutapp.com
@@ -121,6 +135,7 @@ files:
121
135
  - lib/scout_apm/framework_integrations/ruby.rb
122
136
  - lib/scout_apm/framework_integrations/sinatra.rb
123
137
  - lib/scout_apm/histogram.rb
138
+ - lib/scout_apm/instant_reporting.rb
124
139
  - lib/scout_apm/instruments/.DS_Store
125
140
  - lib/scout_apm/instruments/action_controller_rails_2.rb
126
141
  - lib/scout_apm/instruments/action_controller_rails_3_rails4.rb
@@ -134,6 +149,7 @@ files:
134
149
  - lib/scout_apm/instruments/mongoid.rb
135
150
  - lib/scout_apm/instruments/moped.rb
136
151
  - lib/scout_apm/instruments/net_http.rb
152
+ - lib/scout_apm/instruments/percentile_sampler.rb
137
153
  - lib/scout_apm/instruments/process/process_cpu.rb
138
154
  - lib/scout_apm/instruments/process/process_memory.rb
139
155
  - lib/scout_apm/instruments/rails_router.rb
@@ -160,7 +176,9 @@ files:
160
176
  - lib/scout_apm/platform_integrations/heroku.rb
161
177
  - lib/scout_apm/platform_integrations/server.rb
162
178
  - lib/scout_apm/reporter.rb
179
+ - lib/scout_apm/request_histograms.rb
163
180
  - lib/scout_apm/request_manager.rb
181
+ - lib/scout_apm/scored_item_set.rb
164
182
  - lib/scout_apm/serializers/app_server_load_serializer.rb
165
183
  - lib/scout_apm/serializers/deploy_serializer.rb
166
184
  - lib/scout_apm/serializers/directive_serializer.rb
@@ -207,9 +225,12 @@ files:
207
225
  - test/unit/histogram_test.rb
208
226
  - test/unit/instruments/active_record_instruments_test.rb
209
227
  - test/unit/layaway_test.rb
228
+ - test/unit/metric_set_test.rb
229
+ - test/unit/scored_item_set_test.rb
210
230
  - test/unit/serializers/payload_serializer_test.rb
211
231
  - test/unit/slow_item_set_test.rb
212
232
  - test/unit/slow_job_policy_test.rb
233
+ - test/unit/slow_request_policy_test.rb
213
234
  - test/unit/sql_sanitizer_test.rb
214
235
  - test/unit/utils/active_record_metric_name_test.rb
215
236
  homepage: https://github.com/scoutapp/scout_apm_ruby
@@ -232,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
253
  version: 1.3.1
233
254
  requirements: []
234
255
  rubyforge_project: scout_apm
235
- rubygems_version: 2.4.6
256
+ rubygems_version: 2.6.2
236
257
  signing_key:
237
258
  specification_version: 4
238
259
  summary: Ruby application performance monitoring
@@ -245,8 +266,12 @@ test_files:
245
266
  - test/unit/histogram_test.rb
246
267
  - test/unit/instruments/active_record_instruments_test.rb
247
268
  - test/unit/layaway_test.rb
269
+ - test/unit/metric_set_test.rb
270
+ - test/unit/scored_item_set_test.rb
248
271
  - test/unit/serializers/payload_serializer_test.rb
249
272
  - test/unit/slow_item_set_test.rb
250
273
  - test/unit/slow_job_policy_test.rb
274
+ - test/unit/slow_request_policy_test.rb
251
275
  - test/unit/sql_sanitizer_test.rb
252
276
  - test/unit/utils/active_record_metric_name_test.rb
277
+ has_rdoc: