scout_apm 3.0.0.pre23 → 3.0.0.pre25

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: 64d1ac40c6dec93f6e7c59b358f8f696a1f53eee
4
- data.tar.gz: 815f98467560d0c0b9c4257eafc1f45a9784246e
3
+ metadata.gz: 0d2364c7ae5bfc518cc19c5059e90959a15203bc
4
+ data.tar.gz: 45a2372a9d6a96460b946419ec02c3ceb63a4d2d
5
5
  SHA512:
6
- metadata.gz: 439b25ab44127e59d906006f34e8c9efd94fa3bbafde58fbcfd1af34be1caf94b80d8ae84c6087af8e4de5e6866b5c03e609d971524e0cbc3a3aa0d2922f500b
7
- data.tar.gz: b6c954e72a252f9dbc113ed12b659c69b9f3e19241a58395a01ff68725ad4bd0b96b2e0bb6857cd9950063469aaba76d03ff1d3a2d802ca14d218c7996dcc10c
6
+ metadata.gz: 607f2bf5f3b6eedab959e49c277972f00c72c03d408782a8cc0466a7fc44a2e5dce11a4279da227f64cb5baeda9d1ad4ed8ead972687906abd19750973e7246b
7
+ data.tar.gz: 0bb02a39eb5dd459665b9049038e275e08fe3ddd60a1ffcb5b2d6af1f7f31f8291d58eaac2a8cac577527a8a046167f2492058af6e20d7f725691b25e0b1d40f
@@ -2,6 +2,14 @@
2
2
 
3
3
  * ScoutProf BETA
4
4
 
5
+ # 2.4.13
6
+
7
+ * Incorporating total time consumed into transaction trace policy
8
+
9
+ # 2.4.12
10
+
11
+ * Calculates DelayedJob queue latency correctly when jobs are scheduled to run in the future
12
+
5
13
  # 2.4.11
6
14
 
7
15
  * Adds transaction + periodic reporting callback extension support
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in scout_apm.gemspec
4
4
  gemspec
@@ -146,6 +146,7 @@ require 'scout_apm/slow_request_policy'
146
146
  require 'scout_apm/slow_job_policy'
147
147
  require 'scout_apm/job_record'
148
148
  require 'scout_apm/request_histograms'
149
+ require 'scout_apm/transaction_time_consumed'
149
150
 
150
151
  require 'scout_apm/attribute_arranger'
151
152
  require 'scout_apm/git_revision'
@@ -114,6 +114,10 @@ module ScoutApm
114
114
  @request_histograms_by_time ||= Hash.new { |h, k| h[k] = ScoutApm::RequestHistograms.new }
115
115
  end
116
116
 
117
+ def transaction_time_consumed
118
+ @transaction_time_consumed ||= ScoutApm::TransactionTimeConsumed.new
119
+ end
120
+
117
121
  def store
118
122
  return @store if @store
119
123
  self.store = ScoutApm::Store.new(self)
@@ -53,7 +53,7 @@ module ScoutApm
53
53
  req = ScoutApm::RequestManager.lookup
54
54
 
55
55
  begin
56
- latency = Time.now - job.created_at
56
+ latency = Time.now - [job.created_at, job.run_at].max
57
57
  req.annotate_request(:queue_latency => latency)
58
58
  rescue
59
59
  end
@@ -20,6 +20,7 @@ require 'scout_apm/environment'
20
20
  # key - the account key with Scout APM. Found in Settings in the Web UI
21
21
  # log_file_path - either a directory or "STDOUT".
22
22
  # log_level - DEBUG / INFO / WARN as usual
23
+ # max_traces - Internal: An experiment in trace quality, this requires a server-side setting as well. Setting this to a higher value will make your app server work harder for no benefit.
23
24
  # monitor - true or false. False prevents any instrumentation from starting
24
25
  # name - override the name reported to APM. This is the name that shows in the Web UI
25
26
  # profile - turn on/off scoutprof (only applicable in Gem versions including scoutprof)
@@ -57,6 +58,7 @@ module ScoutApm
57
58
  'log_level',
58
59
  'log_stderr',
59
60
  'log_stdout',
61
+ 'max_traces',
60
62
  'monitor',
61
63
  'name',
62
64
  'profile',
@@ -151,6 +153,7 @@ module ScoutApm
151
153
  "dev_trace" => BooleanCoercion.new,
152
154
  "enable_background_jobs" => BooleanCoercion.new,
153
155
  "ignore" => JsonCoercion.new,
156
+ "max_traces" => IntegerCoercion.new,
154
157
  "monitor" => BooleanCoercion.new,
155
158
  'database_metric_limit' => IntegerCoercion.new,
156
159
  'database_metric_report_limit' => IntegerCoercion.new,
@@ -250,6 +253,7 @@ module ScoutApm
250
253
  'host' => 'https://checkin.scoutapp.com',
251
254
  'ignore' => [],
252
255
  'log_level' => 'info',
256
+ 'max_traces' => 10,
253
257
  'profile' => true, # for scoutprof
254
258
  'report_format' => 'json',
255
259
  'scm_subdirectory' => '',
@@ -17,6 +17,10 @@ module ScoutApm
17
17
  # Outliers are worth up to "1000ms" of weight
18
18
  POINT_MULTIPLIER_PERCENTILE = 1.0
19
19
 
20
+ # Points for an endpoint's who's throughput * response time is a large % of
21
+ # overall time spent processing requests
22
+ POINT_MULTIPLIER_PERCENT_TIME = 2.5
23
+
20
24
  # A hash of Job Names to the last time we stored a slow trace for it.
21
25
  #
22
26
  # Defaults to a start time that is pretty close to application boot time.
@@ -60,7 +64,9 @@ module ScoutApm
60
64
  # What approximate percentile was this request?
61
65
  percentile = context.request_histograms.approximate_quantile_of_value(unique_name, total_time)
62
66
 
63
- return speed_points(total_time) + percentile_points(percentile) + age_points(age)
67
+ percent_of_total_time = context.transaction_time_consumed.percent_of_total(unique_name)
68
+
69
+ return speed_points(total_time) + percentile_points(percentile) + age_points(age) + percent_time_points(percent_of_total_time)
64
70
  end
65
71
 
66
72
  private
@@ -90,5 +96,16 @@ module ScoutApm
90
96
  def age_points(age)
91
97
  age / 60.0 * POINT_MULTIPLIER_AGE
92
98
  end
99
+
100
+ # Of the total time spent handling endpoints in this app, if this endpoint
101
+ # is a higher percent, it should get more points.
102
+ #
103
+ # A: 20 calls @ 100ms each => 2 seconds of total time
104
+ # B: 10 calls @ 100ms each => 1 second of total time
105
+ #
106
+ # Then A is 66% of the total call time
107
+ def percent_time_points(percent) # Scale 0.0 - 1.0
108
+ percent * POINT_MULTIPLIER_PERCENT_TIME
109
+ end
93
110
  end
94
111
  end
@@ -17,6 +17,10 @@ module ScoutApm
17
17
  # Outliers are worth up to "1000ms" of weight
18
18
  POINT_MULTIPLIER_PERCENTILE = 1.0
19
19
 
20
+ # Points for an endpoint's who's throughput * response time is a large % of
21
+ # overall time spent processing requests
22
+ POINT_MULTIPLIER_PERCENT_TIME = 2.5
23
+
20
24
  # A hash of Endpoint Name to the last time we stored a slow transaction for it.
21
25
  #
22
26
  # Defaults to a start time that is pretty close to application boot time.
@@ -60,7 +64,9 @@ module ScoutApm
60
64
  # What approximate percentile was this request?
61
65
  percentile = context.request_histograms.approximate_quantile_of_value(unique_name, total_time)
62
66
 
63
- return speed_points(total_time) + percentile_points(percentile) + age_points(age)
67
+ percent_of_total_time = context.transaction_time_consumed.percent_of_total(unique_name)
68
+
69
+ return speed_points(total_time) + percentile_points(percentile) + age_points(age) + percent_time_points(percent_of_total_time)
64
70
  end
65
71
 
66
72
  private
@@ -90,5 +96,16 @@ module ScoutApm
90
96
  def age_points(age)
91
97
  age / 60.0 * POINT_MULTIPLIER_AGE
92
98
  end
99
+
100
+ # Of the total time spent handling endpoints in this app, if this endpoint
101
+ # is a higher percent, it should get more points.
102
+ #
103
+ # A: 20 calls @ 100ms each => 2 seconds of total time
104
+ # B: 10 calls @ 100ms each => 1 second of total time
105
+ #
106
+ # Then A is 66% of the total call time
107
+ def percent_time_points(percent) # Scale 0.0 - 1.0
108
+ percent * POINT_MULTIPLIER_PERCENT_TIME
109
+ end
93
110
  end
94
111
  end
@@ -205,8 +205,8 @@ module ScoutApm
205
205
  def initialize(timestamp, context)
206
206
  @timestamp = timestamp
207
207
 
208
- @request_traces = ScoredItemSet.new
209
- @job_traces = ScoredItemSet.new
208
+ @request_traces = ScoredItemSet.new(context.config.value('max_traces'))
209
+ @job_traces = ScoredItemSet.new(context.config.value('max_traces'))
210
210
 
211
211
  @histograms = []
212
212
 
@@ -300,6 +300,8 @@ module ScoutApm
300
300
 
301
301
  apply_name_override
302
302
 
303
+ @agent_context.transaction_time_consumed.add(unique_name, root_layer.total_call_time)
304
+
303
305
  # Make a constant, then call converters.dup.each so it isn't inline?
304
306
  converters = {
305
307
  :histograms => LayerConverters::Histograms,
@@ -0,0 +1,51 @@
1
+ module ScoutApm
2
+ class TransactionTimeConsumed
3
+ # Private Accessor:
4
+ # A hash of Endpoint Name to an time consumed record
5
+ attr_reader :endpoints
6
+ private :endpoints
7
+
8
+ # Private Accessor:
9
+ # The total time spent across all endpoints
10
+ attr_reader :total_duration
11
+ private :total_duration
12
+
13
+ def initialize
14
+ @total_duration = 0.0
15
+ @endpoints = Hash.new { |h, k| h[k] = TotalTimeRecord.new }
16
+ end
17
+
18
+ def add(item, duration)
19
+ @total_duration += duration.to_f
20
+ @endpoints[item].add(duration.to_f)
21
+ end
22
+
23
+ def percent_of_total(item)
24
+ if total_duration == 0.0
25
+ 0
26
+ else
27
+ @endpoints[item].total_duration / total_duration
28
+ end
29
+ end
30
+
31
+ def total_time_for(item)
32
+ @endpoints[item].total_duration
33
+ end
34
+
35
+ def call_count_for(item)
36
+ @endpoints[item].count
37
+ end
38
+
39
+ # Time is in seconds
40
+ TotalTimeRecord = Struct.new(:total_duration, :count) do
41
+ def initialize
42
+ super(0, 0)
43
+ end
44
+
45
+ def add(duration)
46
+ self.total_duration += duration.to_f
47
+ self.count += 1
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  module ScoutApm
2
- VERSION = "3.0.0.pre23"
2
+ VERSION = "3.0.0.pre25"
3
3
  end
@@ -38,7 +38,7 @@ class PeriodicCallbacksTest < Minitest::Test
38
38
  private
39
39
 
40
40
  def reporting_period
41
- rp = ScoutApm::StoreReportingPeriod.new(ScoutApm::AgentContext.new, Time.at(metadata[:agent_time].to_i))
41
+ rp = ScoutApm::StoreReportingPeriod.new(Time.at(metadata[:agent_time].to_i), ScoutApm::AgentContext.new)
42
42
  rp.absorb_metrics!(metrics)
43
43
  end
44
44
 
@@ -55,4 +55,4 @@ class PeriodicCallbacksTest < Minitest::Test
55
55
  {:app_root=>"/srv/rails_app", :unique_id=>"ID", :agent_version=>"2.4.10", :agent_time=>"1523287920", :agent_pid=>21581, :platform=>"ruby"}
56
56
  end
57
57
 
58
- end
58
+ end
@@ -37,9 +37,14 @@ class SlowRequestPolicyTest < Minitest::Test
37
37
  request.set_duration(10) # 10 seconds
38
38
  policy.last_seen[request.unique_name] = Time.now - 120 # 2 minutes since last seen
39
39
  @context.request_histograms.add(request.unique_name, 1)
40
+ @context.transaction_time_consumed.add(request.unique_name, 1)
40
41
 
41
- # Actual value I have in console is 1.499
42
- assert policy.score(request) > 1.45
43
- assert policy.score(request) < 1.55
42
+ # Actual value I have in console is 4.01
43
+ # Score uses Time.now to compare w/ last_seen, and will tick up slowly as
44
+ # time passes, hence the range below.
45
+ score = policy.score(request)
46
+
47
+ assert score > 3.95
48
+ assert score < 4.05
44
49
  end
45
50
  end
@@ -0,0 +1,46 @@
1
+ require 'test_helper'
2
+
3
+ require 'scout_apm/transaction_time_consumed'
4
+
5
+ module ScoutApm
6
+ class TransactionTimeConsumedTest < Minitest::Test
7
+ def setup
8
+ @ttc = ScoutApm::TransactionTimeConsumed.new
9
+ end
10
+
11
+ def test_insert_new_times
12
+ @ttc.add("Controller/Foo", 1.5)
13
+ @ttc.add("Controller/Foo", 2.75)
14
+ assert_equal 4.25, @ttc.total_time_for("Controller/Foo")
15
+ end
16
+
17
+ def test_insert_tracks_endpoints_separately
18
+ @ttc.add("Controller/Foo", 1.5)
19
+ @ttc.add("Controller/Foo", 2.75)
20
+ @ttc.add("Controller/Bar", 5)
21
+ @ttc.add("Controller/Bar", 5)
22
+ assert_equal 4.25, @ttc.total_time_for("Controller/Foo")
23
+ assert_equal 10.0, @ttc.total_time_for("Controller/Bar")
24
+ end
25
+
26
+ def test_calculates_percent_of_total
27
+ @ttc.add("Controller/Foo", 1)
28
+ @ttc.add("Controller/Bar", 4)
29
+ assert_equal 0.2, @ttc.percent_of_total("Controller/Foo")
30
+ assert_equal 0.8, @ttc.percent_of_total("Controller/Bar")
31
+ end
32
+
33
+ def test_counts_total_call_count
34
+ @ttc.add("Controller/Foo", 1)
35
+ @ttc.add("Controller/Foo", 1)
36
+ @ttc.add("Controller/Foo", 1)
37
+ @ttc.add("Controller/Bar", 4)
38
+ assert_equal 3, @ttc.call_count_for("Controller/Foo")
39
+ assert_equal 1, @ttc.call_count_for("Controller/Bar")
40
+ end
41
+
42
+ def test_percent_of_total_is_0_with_no_data
43
+ assert_equal 0.0, @ttc.percent_of_total("Controller/Foo")
44
+ end
45
+ end
46
+ 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: 3.0.0.pre23
4
+ version: 3.0.0.pre25
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: 2018-05-07 00:00:00.000000000 Z
12
+ date: 2018-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -315,6 +315,7 @@ files:
315
315
  - lib/scout_apm/tracer.rb
316
316
  - lib/scout_apm/tracked_request.rb
317
317
  - lib/scout_apm/transaction.rb
318
+ - lib/scout_apm/transaction_time_consumed.rb
318
319
  - lib/scout_apm/utils/active_record_metric_name.rb
319
320
  - lib/scout_apm/utils/backtrace_parser.rb
320
321
  - lib/scout_apm/utils/fake_stacks.rb
@@ -369,6 +370,7 @@ files:
369
370
  - test/unit/tracer_test.rb
370
371
  - test/unit/tracked_request_test.rb
371
372
  - test/unit/transaction_test.rb
373
+ - test/unit/transaction_time_consumed_test.rb
372
374
  - test/unit/utils/active_record_metric_name_test.rb
373
375
  - test/unit/utils/backtrace_parser_test.rb
374
376
  - test/unit/utils/numbers_test.rb
@@ -395,8 +397,52 @@ required_rubygems_version: !ruby/object:Gem::Requirement
395
397
  version: 1.3.1
396
398
  requirements: []
397
399
  rubyforge_project: scout_apm
398
- rubygems_version: 2.6.12
400
+ rubygems_version: 2.4.6
399
401
  signing_key:
400
402
  specification_version: 4
401
403
  summary: Ruby application performance monitoring
402
- test_files: []
404
+ test_files:
405
+ - test/data/config_test_1.yml
406
+ - test/test_helper.rb
407
+ - test/unit/agent_test.rb
408
+ - test/unit/background_job_integrations/sidekiq_test.rb
409
+ - test/unit/config_test.rb
410
+ - test/unit/context_test.rb
411
+ - test/unit/db_query_metric_set_test.rb
412
+ - test/unit/db_query_metric_stats_test.rb
413
+ - test/unit/environment_test.rb
414
+ - test/unit/extensions/periodic_callbacks_test.rb
415
+ - test/unit/extensions/transaction_callbacks_test.rb
416
+ - test/unit/fake_store_test.rb
417
+ - test/unit/git_revision_test.rb
418
+ - test/unit/histogram_test.rb
419
+ - test/unit/ignored_uris_test.rb
420
+ - test/unit/instruments/active_record_instruments_test.rb
421
+ - test/unit/instruments/net_http_test.rb
422
+ - test/unit/instruments/percentile_sampler_test.rb
423
+ - test/unit/layaway_test.rb
424
+ - test/unit/layer_children_set_test.rb
425
+ - test/unit/layer_converters/depth_first_walker_test.rb
426
+ - test/unit/layer_converters/metric_converter_test.rb
427
+ - test/unit/layer_converters/stubs.rb
428
+ - test/unit/limited_layer_test.rb
429
+ - test/unit/logger_test.rb
430
+ - test/unit/metric_set_test.rb
431
+ - test/unit/remote/test_message.rb
432
+ - test/unit/remote/test_router.rb
433
+ - test/unit/remote/test_server.rb
434
+ - test/unit/scored_item_set_test.rb
435
+ - test/unit/serializers/payload_serializer_test.rb
436
+ - test/unit/slow_job_policy_test.rb
437
+ - test/unit/slow_request_policy_test.rb
438
+ - test/unit/sql_sanitizer_test.rb
439
+ - test/unit/store_test.rb
440
+ - test/unit/tracer_test.rb
441
+ - test/unit/tracked_request_test.rb
442
+ - test/unit/transaction_test.rb
443
+ - test/unit/transaction_time_consumed_test.rb
444
+ - test/unit/utils/active_record_metric_name_test.rb
445
+ - test/unit/utils/backtrace_parser_test.rb
446
+ - test/unit/utils/numbers_test.rb
447
+ - test/unit/utils/scm.rb
448
+ has_rdoc: