scout_apm 2.1.0 → 2.1.1

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
  SHA1:
3
- metadata.gz: bf1eaf130d67f52fcfcf414c6db4347fa4b94521
4
- data.tar.gz: 0386d415a40a707645a65662237f0d44b9bbbdd8
3
+ metadata.gz: 18409ba68d80eefddd0a94c5c8f47f7e8061d921
4
+ data.tar.gz: 7ab7791459924188b16c1551bf3682defd268937
5
5
  SHA512:
6
- metadata.gz: 71d5d59042427c3bf1afbd753fb8646e012c6187c940a0f6a2854a6123cbc5259b8297ca168a5d91793d6722b6082cd0a7c5da520399a13085b4ca7fc274cf3a
7
- data.tar.gz: a2ca63e84f57dd17828072076d0c1bd1b757caf1ef3f82a7954ca928b4d09c973ebbda094cb6a5d1ecbbf1c28c3813838239ca55be7c2b1c24c50f430fe49559
6
+ metadata.gz: a586e1f036a81decca9bdda9d15735174e1676157af56c78cd1c8251b44046872811bfd2fcb4b017c7c973bd6e7daf8e608169c6958f33542a5b32cf16b29d3f
7
+ data.tar.gz: fb8e623a8f354686a3c3a37ba7e3b9a16db3e17cbefe58b2f7fad198ce5c70b187e33b0d487fcb3f7f71860e8e9b76d2648f81728d6923fdd71bc8e4efee2b7e
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,9 @@
1
+ # 2.1.1
2
+
3
+ * Fix an issue with AR instrumentation and complex queries
4
+ * Fix use of configuration option `data_file`
5
+ * Update unit tests
6
+
1
7
  # 2.1.0
2
8
 
3
9
  * Added ignore key to configuration to entirely ignore an endpoint. No traces
data/lib/scout_apm.rb CHANGED
@@ -120,7 +120,6 @@ require 'scout_apm/metric_meta'
120
120
  require 'scout_apm/metric_stats'
121
121
  require 'scout_apm/slow_transaction'
122
122
  require 'scout_apm/slow_job_record'
123
- require 'scout_apm/slow_item_set'
124
123
  require 'scout_apm/scored_item_set'
125
124
  require 'scout_apm/slow_request_policy'
126
125
  require 'scout_apm/slow_job_policy'
@@ -55,7 +55,7 @@ module ScoutApm
55
55
  @request_histograms_by_time = Hash.new { |h, k| h[k] = ScoutApm::RequestHistograms.new }
56
56
 
57
57
  @store = ScoutApm::Store.new
58
- @layaway = ScoutApm::Layaway.new
58
+ @layaway = ScoutApm::Layaway.new(config, environment)
59
59
  @metric_lookup = Hash.new
60
60
 
61
61
  @capacity = ScoutApm::Capacity.new
@@ -137,11 +137,17 @@ module ScoutApm
137
137
  end
138
138
 
139
139
  def initialize(overlays)
140
- @overlays = overlays
140
+ @overlays = Array(overlays)
141
141
  end
142
142
 
143
143
  def value(key)
144
- raw_value = @overlays.detect{ |overlay| overlay.has_key?(key) }.value(key)
144
+ o = @overlays.detect{ |overlay| overlay.has_key?(key) }
145
+ raw_value = if o
146
+ o.value(key)
147
+ else
148
+ # No overlay said it could handle this key, bail out with nil.
149
+ nil
150
+ end
145
151
 
146
152
  coercion = SETTING_COERCIONS[key] || NullCoercion.new
147
153
  coercion.coerce(raw_value)
@@ -61,7 +61,7 @@ module ScoutApm
61
61
  :platform => "ruby",
62
62
  }
63
63
  hash = ScoutApm::Serializers::PayloadSerializerToJson.rearrange_slow_transaction(trace)
64
- hash.merge!(metadata:metadata)
64
+ hash.merge!(:metadata => metadata)
65
65
  payload = ScoutApm::Serializers::PayloadSerializerToJson.jsonify_hash(hash)
66
66
 
67
67
  if env['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' || content_type.include?("application/json")
@@ -105,4 +105,4 @@ module ScoutApm
105
105
  end
106
106
  end
107
107
  end
108
- end
108
+ end
@@ -173,7 +173,7 @@ module ScoutApm
173
173
  req.start_layer(layer)
174
174
  req.ignore_children!
175
175
  begin
176
- find_by_sql_without_scout_instruments(*args)
176
+ find_by_sql_without_scout_instruments(*args, &block)
177
177
  ensure
178
178
  req.acknowledge_children!
179
179
  req.stop_layer
@@ -199,7 +199,7 @@ module ScoutApm
199
199
  req.start_layer(layer)
200
200
  req.ignore_children!
201
201
  begin
202
- find_with_associations_without_scout_instruments(*args)
202
+ find_with_associations_without_scout_instruments(*args, &block)
203
203
  ensure
204
204
  req.acknowledge_children!
205
205
  req.stop_layer
@@ -18,8 +18,12 @@ module ScoutApm
18
18
  # Must be sortable as an integer
19
19
  TIME_FORMAT = "%Y%m%d%H%M"
20
20
 
21
- def initialize(directory=nil)
22
- @directory = directory
21
+ attr_reader :config
22
+ attr_reader :environment
23
+
24
+ def initialize(config, environment)
25
+ @config = config
26
+ @environment = environment
23
27
  end
24
28
 
25
29
  # Returns a Pathname object with the fully qualified directory where the layaway files can be placed.
@@ -30,12 +34,12 @@ module ScoutApm
30
34
  def directory
31
35
  return @directory if @directory
32
36
 
33
- data_file = ScoutApm::Agent.instance.config.value("data_file")
34
- data_file = File.dirname(data_file) if data_file && !File.directory?
37
+ data_file = config.value("data_file")
38
+ data_file = File.dirname(data_file) if data_file && !File.directory?(data_file)
35
39
 
36
40
  candidates = [
37
41
  data_file,
38
- "#{ScoutApm::Agent.instance.environment.root}/tmp",
42
+ "#{environment.root}/tmp",
39
43
  "/tmp"
40
44
  ].compact
41
45
 
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "2.1.0"
2
+ VERSION = "2.1.1"
3
3
  end
4
4
 
data/test/test_helper.rb CHANGED
@@ -17,6 +17,34 @@ Kernel.module_eval do
17
17
  end
18
18
  end
19
19
 
20
+ # A test helper class to create a temporary "configuration" we can control entirely purposes
21
+ class FakeConfigOverlay
22
+ def initialize(values)
23
+ @values = values
24
+ end
25
+
26
+ def value(key)
27
+ @values[key]
28
+ end
29
+
30
+ def has_key?(key)
31
+ @values.has_key?(key)
32
+ end
33
+ end
34
+
35
+ class FakeEnvironment
36
+ def initialize(values)
37
+ @values = values
38
+ end
39
+
40
+ def method_missing(sym)
41
+ if @values.has_key?(sym)
42
+ @values[sym]
43
+ else
44
+ raise "#{sym} not found in FakeEnvironment"
45
+ end
46
+ end
47
+ end
20
48
 
21
49
  # Helpers available to all tests
22
50
  class Minitest::Test
@@ -42,6 +70,16 @@ class Minitest::Test
42
70
  ScoutApm::Agent.instance.instance_variable_set("@logger", @logger)
43
71
  end
44
72
 
73
+ def make_fake_environment(values)
74
+ FakeEnvironment.new(values)
75
+ end
76
+
77
+ def make_fake_config(values)
78
+ ScoutApm::Config.new(FakeConfigOverlay.new(values))
79
+ end
80
+
45
81
  DATA_FILE_DIR = File.dirname(__FILE__) + '/tmp'
46
82
  DATA_FILE_PATH = "#{DATA_FILE_DIR}/scout_apm.db"
47
83
  end
84
+
85
+
@@ -4,7 +4,7 @@ require 'scout_apm/config'
4
4
 
5
5
  class ConfigTest < Minitest::Test
6
6
  def test_initalize_without_a_config
7
- conf = ScoutApm::Config.new(nil)
7
+ conf = ScoutApm::Config.without_file
8
8
 
9
9
  # nil for random keys
10
10
  assert_nil conf.value("log_file_path")
@@ -21,7 +21,7 @@ class ConfigTest < Minitest::Test
21
21
  set_rack_env("production")
22
22
 
23
23
  conf_file = File.expand_path("../../data/config_test_1.yml", __FILE__)
24
- conf = ScoutApm::Config.new(conf_file)
24
+ conf = ScoutApm::Config.with_file(conf_file)
25
25
 
26
26
  assert_equal "debug", conf.value('log_level')
27
27
  assert_equal "APM Test Conf (Production)", conf.value('name')
@@ -5,25 +5,20 @@ require 'scout_apm/metric_stats'
5
5
  require 'scout_apm/context'
6
6
  require 'scout_apm/store'
7
7
 
8
+ require 'fileutils'
8
9
  class LayawayTest < Minitest::Test
9
- def test_add_reporting_period
10
- File.open(DATA_FILE_PATH, 'w') { |file| file.write(Marshal.dump(NEW_FORMAT)) }
11
- ScoutApm::Agent.instance.start
10
+ def test_directory_uses_DATA_FILE_option
11
+ FileUtils.mkdir_p '/tmp/scout_apm_test/data_file_option'
12
+ config = make_fake_config("data_file" => "/tmp/scout_apm_test/data_file_option")
12
13
 
13
- data = ScoutApm::Layaway.new
14
- t = ScoutApm::StoreReportingPeriodTimestamp.new
15
- data.add_reporting_period(t,ScoutApm::StoreReportingPeriod.new(t))
16
- assert_equal [TIMESTAMP,t].sort_by(&:timestamp), Marshal.load(File.read(DATA_FILE_PATH)).keys.sort_by(&:timestamp)
14
+ assert_equal Pathname.new("/tmp/scout_apm_test/data_file_option"), ScoutApm::Layaway.new(config, ScoutApm::Agent.instance.environment).directory
17
15
  end
18
16
 
19
- def test_merge_reporting_period
20
- File.open(DATA_FILE_PATH, 'w') { |file| file.write(Marshal.dump(NEW_FORMAT)) }
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
25
- end
17
+ def test_directory_looks_for_root_slash_tmp
18
+ FileUtils.mkdir_p '/tmp/scout_apm_test/tmp'
19
+ config = make_fake_config({})
20
+ env = make_fake_environment(:root => "/tmp/scout_apm_test")
26
21
 
27
- TIMESTAMP = ScoutApm::StoreReportingPeriodTimestamp.new(Time.parse("2015-01-01"))
28
- NEW_FORMAT = {TIMESTAMP => ScoutApm::StoreReportingPeriod.new(TIMESTAMP)} # Format for 1.2+ agents
22
+ assert_equal Pathname.new("/tmp/scout_apm_test/tmp"), ScoutApm::Layaway.new(config, env).directory
23
+ end
29
24
  end
@@ -6,26 +6,11 @@ require 'scout_apm/serializers/payload_serializer_to_json'
6
6
  require 'scout_apm/slow_transaction'
7
7
  require 'scout_apm/metric_meta'
8
8
  require 'scout_apm/metric_stats'
9
- require 'scout_apm/utils/fake_stack_prof'
10
9
  require 'scout_apm/context'
11
10
  require 'ostruct'
12
11
  require 'json' # to deserialize what has been manually serialized by the production code
13
12
 
14
- # stub the report_format value
15
- # class ScoutApm::Agent
16
- # module Config
17
- # def self.value(key)
18
- # 'json'
19
- # end
20
- # end
21
-
22
- # def self.instance
23
- # OpenStruct.new(:config => Config)
24
- # end
25
- # end
26
-
27
13
  class PayloadSerializerTest < Minitest::Test
28
-
29
14
  def test_serializes_metadata_as_json
30
15
  metadata = {
31
16
  :app_root => "/srv/app/rootz",
@@ -112,93 +97,6 @@ class PayloadSerializerTest < Minitest::Test
112
97
  assert_equal formatted_metrics, JSON.parse(payload)["metrics"]
113
98
  end
114
99
 
115
- def test_serializes_slow_transactions_as_json
116
- slow_transaction_metrics = {
117
- ScoutApm::MetricMeta.new('ActiveRecord/all').tap { |meta|
118
- meta.desc = "SELECT *\nfrom users where filter=?"
119
- meta.extra = {:user => 'cooluser'}
120
- meta.metric_id = nil
121
- meta.scope = "Controller/apps/checkin"
122
- } => ScoutApm::MetricStats.new.tap { |stats|
123
- stats.call_count = 16
124
- stats.max_call_time = 0.005338062
125
- stats.min_call_time = 0.000613518
126
- stats.sum_of_squares = 9.8040860751126e-05
127
- stats.total_call_time = 0.033245704
128
- stats.total_exclusive_time = 0.033245704
129
- },
130
- ScoutApm::MetricMeta.new("Controller/apps/checkin").tap { |meta|
131
- meta.desc = nil
132
- meta.extra = {}
133
- meta.metric_id = nil
134
- meta.scope = nil
135
- } => ScoutApm::MetricStats.new.tap { |stats|
136
- stats.call_count = 2
137
- stats.max_call_time = 0.078521419
138
- stats.min_call_time = 0.034881757
139
- stats.sum_of_squares = 0.007382350213180609
140
- stats.total_call_time = 0.113403176
141
- stats.total_exclusive_time = 0.07813208899999999
142
- }
143
- }
144
- context = ScoutApm::Context.new
145
- context.add({"this" => "that"})
146
- context.add_user({"hello" => "goodbye"})
147
- slow_t = ScoutApm::SlowTransaction.new("http://example.com/blabla", "Buckethead/something/else", 1.23, slow_transaction_metrics, context, Time.at(1448198788), [], 10)
148
- payload = ScoutApm::Serializers::PayloadSerializerToJson.serialize({}, {}, [slow_t], [], [])
149
- formatted_slow_transactions = [
150
- {
151
- "key" => {
152
- "bucket" => "Buckethead",
153
- "name" => "something/else"
154
- },
155
- "time" => "2015-11-22 06:26:28 -0700",
156
- "total_call_time" => 1.23,
157
- "uri" => "http://example.com/blabla",
158
- "context" => {"this"=>"that", "user"=>{"hello"=>"goodbye"}},
159
- "prof" => [],
160
- "score" => 10,
161
- "metrics" => [
162
- {
163
- "key" => {
164
- "bucket" => "ActiveRecord",
165
- "name" => "all",
166
- "desc" => "SELECT *\nfrom users where filter=?",
167
- "extra" => {
168
- "user" => "cooluser",
169
- },
170
- "scope" => {
171
- "bucket" => "Controller",
172
- "name" => "apps/checkin",
173
- },
174
- },
175
- "call_count" => 16,
176
- "max_call_time" => 0.005338062,
177
- "min_call_time" => 0.000613518,
178
- "total_call_time" => 0.033245704,
179
- "total_exclusive_time" => 0.033245704,
180
- },
181
- {
182
- "key" => {
183
- "bucket" => "Controller",
184
- "name" => "apps/checkin",
185
- "desc" => nil,
186
- "extra" => {},
187
- "scope" => nil,
188
- },
189
- "call_count" => 2,
190
- "max_call_time" => 0.078521419,
191
- "min_call_time" => 0.034881757,
192
- "total_call_time" => 0.113403176,
193
- "total_exclusive_time" => 0.07813208899999999,
194
- }
195
- ]
196
- }
197
- ]
198
-
199
- assert_equal formatted_slow_transactions, JSON.parse(payload)["slow_transactions"]
200
- end
201
-
202
100
  def test_escapes_json_quotes
203
101
  metadata = {
204
102
  :quotie => "here are some \"quotes\"",
@@ -3,53 +3,4 @@ require 'test_helper'
3
3
  require 'scout_apm/slow_job_policy'
4
4
 
5
5
  class SlowJobPolicyTest < Minitest::Test
6
- def test_first_call_is_not_slow
7
- policy = ScoutApm::SlowJobPolicy.new
8
- assert !policy.slow?("TestWorker", 10)
9
- end
10
-
11
- # All of these get faster and faster, so none are marked as slow.
12
- def test_fast_calls_are_not_slow
13
- policy = ScoutApm::SlowJobPolicy.new
14
- assert !policy.slow?("TestWorker", 10)
15
- assert !policy.slow?("TestWorker", 8)
16
- assert !policy.slow?("TestWorker", 6)
17
- assert !policy.slow?("TestWorker", 4)
18
- assert !policy.slow?("TestWorker", 2)
19
- end
20
-
21
- def test_slow_calls_are_marked_as_slow
22
- policy = ScoutApm::SlowJobPolicy.new
23
- policy.slow?("TestWorker", 10) # Prime it with a not-slow
24
-
25
- assert policy.slow?("TestWorker", 12)
26
- assert policy.slow?("TestWorker", 14)
27
- assert policy.slow?("TestWorker", 16)
28
- assert policy.slow?("TestWorker", 18)
29
- end
30
-
31
- def test_mix_of_fast_and_slow
32
- policy = ScoutApm::SlowJobPolicy.new
33
- policy.slow?("TestWorker", 10) # Prime it with a not-slow
34
-
35
- assert policy.slow?("TestWorker", 12)
36
- assert !policy.slow?("TestWorker", 8)
37
- assert policy.slow?("TestWorker", 13)
38
- assert !policy.slow?("TestWorker", 6)
39
- end
40
-
41
- def test_different_workers_dont_interfere
42
- policy = ScoutApm::SlowJobPolicy.new
43
- policy.slow?("TestWorker", 10) # Prime it with a not-slow
44
- policy.slow?("OtherWorker", 1.0) # Prime it with a not-slow
45
-
46
- assert !policy.slow?("TestWorker", 8)
47
- assert policy.slow?("OtherWorker", 2)
48
- assert !policy.slow?("TestWorker", 1)
49
- assert policy.slow?("OtherWorker", 3)
50
- assert policy.slow?("TestWorker", 12)
51
- assert !policy.slow?("OtherWorker", 1)
52
- assert policy.slow?("TestWorker", 12)
53
- assert policy.slow?("OtherWorker", 4)
54
- end
55
6
  end
@@ -32,11 +32,10 @@ class SlowRequestPolicyTest < Minitest::Test
32
32
 
33
33
  request.set_duration(10) # 10 seconds
34
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
35
+ ScoutApm::Agent.instance.request_histograms.add(request.unique_name, 1)
40
36
 
37
+ # Actual value I have in console is 1.499
38
+ assert policy.score(request) > 1.45
39
+ assert policy.score(request) < 1.55
41
40
  end
42
41
  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.1.0
4
+ version: 2.1.1
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-12 00:00:00.000000000 Z
12
+ date: 2016-08-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rusage
@@ -200,7 +200,6 @@ files:
200
200
  - lib/scout_apm/server_integrations/thin.rb
201
201
  - lib/scout_apm/server_integrations/unicorn.rb
202
202
  - lib/scout_apm/server_integrations/webrick.rb
203
- - lib/scout_apm/slow_item_set.rb
204
203
  - lib/scout_apm/slow_job_policy.rb
205
204
  - lib/scout_apm/slow_job_record.rb
206
205
  - lib/scout_apm/slow_request_policy.rb
@@ -233,7 +232,6 @@ files:
233
232
  - test/unit/metric_set_test.rb
234
233
  - test/unit/scored_item_set_test.rb
235
234
  - test/unit/serializers/payload_serializer_test.rb
236
- - test/unit/slow_item_set_test.rb
237
235
  - test/unit/slow_job_policy_test.rb
238
236
  - test/unit/slow_request_policy_test.rb
239
237
  - test/unit/sql_sanitizer_test.rb
@@ -277,7 +275,6 @@ test_files:
277
275
  - test/unit/metric_set_test.rb
278
276
  - test/unit/scored_item_set_test.rb
279
277
  - test/unit/serializers/payload_serializer_test.rb
280
- - test/unit/slow_item_set_test.rb
281
278
  - test/unit/slow_job_policy_test.rb
282
279
  - test/unit/slow_request_policy_test.rb
283
280
  - test/unit/sql_sanitizer_test.rb
@@ -1,80 +0,0 @@
1
- # In order to keep load down, only record a sample of Slow Items (Transactions
2
- # or Jobs). In order to make that sampling as fair as possible, follow a basic
3
- # algorithm:
4
- #
5
- # When adding a new Slow Item:
6
- # * Just add it if there is an open spot
7
- # * If there isn't an open spot, attempt to remove an over-represented
8
- # item instead ("attempt_to_evict"). Overrepresented is simply "has more
9
- # than @fair number of Matching Items in the set". The fastest of the
10
- # overrepresented items is removed.
11
- # * If there isn't an open spot, and no Item is valid to evict, drop the
12
- # incoming Item without adding.
13
- #
14
- # There is no way to remove Items from this set, create a new object
15
- # for each reporting period.
16
- #
17
- # Item must respond to:
18
- # #metric_name - string - grouping key to see if one kind of thing is overrepresented
19
- # #total_call_time - float - duration of the item
20
-
21
- module ScoutApm
22
- class SlowItemSet
23
- include Enumerable
24
-
25
- DEFAULT_TOTAL = 10
26
- DEFAULT_FAIR = 1
27
-
28
- attr_reader :total
29
- attr_reader :fair
30
-
31
- def initialize(total=DEFAULT_TOTAL, fair=DEFAULT_FAIR)
32
- @total = total
33
- @fair = fair
34
- @items = []
35
- end
36
-
37
- def each
38
- @items.each { |s| yield s }
39
- end
40
-
41
- def <<(item)
42
- return if attempt_append(item)
43
- attempt_to_evict
44
- attempt_append(item)
45
- end
46
-
47
- def empty_slot?
48
- @items.length < total
49
- end
50
-
51
- def attempt_append(item)
52
- if empty_slot?
53
- @items.push(item)
54
- true
55
- else
56
- false
57
- end
58
- end
59
-
60
- def attempt_to_evict
61
- return if @items.length == 0
62
-
63
- overrepresented = @items.
64
- group_by { |item| unique_name_for(item) }.
65
- to_a.
66
- sort_by { |(_, items)| items.length }.
67
- last
68
-
69
- if overrepresented[1].length > fair
70
- fastest = overrepresented[1].sort_by { |item| item.total_call_time }.first
71
- @items.delete(fastest)
72
- end
73
- end
74
-
75
- # Determine this items' "hash key"
76
- def unique_name_for(item)
77
- item.metric_name
78
- end
79
- end
80
- end
@@ -1,94 +0,0 @@
1
- require 'test_helper'
2
-
3
- require 'scout_apm/slow_item_set'
4
- require 'scout_apm/slow_transaction'
5
-
6
- class SlowItemSetTest < Minitest::Test
7
- def test_adding_to_empty_set
8
- set = ScoutApm::SlowItemSet.new(3, 1)
9
- set << make_slow("Controller/Foo")
10
- assert_equal 1, set.count
11
- end
12
-
13
- def test_adding_to_partially_full_set
14
- set = ScoutApm::SlowItemSet.new(3, 1)
15
- set << make_slow("Controller/Foo")
16
- set << make_slow("Controller/Foo")
17
- assert_equal 2, set.count
18
- end
19
-
20
- def test_overflow_of_one_type
21
- max_size = 3
22
- set = ScoutApm::SlowItemSet.new(max_size, 1)
23
- set << make_slow("Controller/Foo")
24
- set << make_slow("Controller/Foo")
25
- set << make_slow("Controller/Foo")
26
- set << make_slow("Controller/Foo")
27
- set << make_slow("Controller/Foo")
28
- set << make_slow("Controller/Foo")
29
- assert_equal max_size, set.count
30
- end
31
-
32
- def test_eviction_of_overrepresented
33
- max_size = 3
34
- set = ScoutApm::SlowItemSet.new(max_size, 1)
35
- set << make_slow("Controller/Foo")
36
- set << make_slow("Controller/Foo")
37
- set << make_slow("Controller/Foo")
38
- set << make_slow("Controller/Foo")
39
- set << make_slow("Controller/Foo")
40
- set << make_slow("Controller/Bar")
41
-
42
- # 3 total
43
- assert_equal max_size, set.count
44
- assert_equal 1, set.select{|sl| sl.metric_name == "Controller/Bar"}.length
45
- assert_equal 2, set.select{|sl| sl.metric_name == "Controller/Foo"}.length
46
- end
47
-
48
- # Fill the set with /Foo records, then add a /Bar to evict. Check that the
49
- # evicted one was the fastest of the Foos
50
- def test_eviction_of_fastest
51
- max_size = 3
52
- set = ScoutApm::SlowItemSet.new(max_size, 1)
53
-
54
- [1,2,3].shuffle.each do |seconds| # Shuffle to remove any assumptions on order
55
- set << make_slow("Controller/Foo", seconds)
56
- end
57
- set << make_slow("Controller/Bar", 8)
58
-
59
- # The foo taking 1 second should be evicted
60
- assert_equal 2, set.select{|sl| sl.metric_name == "Controller/Foo"}.map{ |sl| sl.total_call_time}.min
61
- end
62
-
63
- def test_eviction_when_no_overrepresented
64
- max_size = 4
65
- fair = 2
66
- set = ScoutApm::SlowItemSet.new(max_size, fair)
67
-
68
- # Full, but each is at fair level
69
- set << make_slow("Controller/Bar")
70
- set << make_slow("Controller/Bar")
71
- set << make_slow("Controller/Foo")
72
- set << make_slow("Controller/Foo")
73
-
74
- set << make_slow("Controller/Quux")
75
- assert_equal max_size, set.count
76
- assert_equal 0, set.select{|sl| sl.metric_name == "Controller/Quux" }.length
77
- end
78
-
79
- ##############
80
- #### Helpers
81
- ##############
82
-
83
- def make_slow(metric, time=5)
84
- ScoutApm::SlowTransaction.new(
85
- "http://foo.app/#{metric}",
86
- metric,
87
- time,
88
- {}, # metrics
89
- {}, # context
90
- Time.now, # end time
91
- [], # stackprof
92
- 0)
93
- end
94
- end