scout_apm 3.0.0.pre23 → 3.0.0.pre25

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