scout_apm 2.1.0 → 2.1.1

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