scout_apm 1.6.8 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -1
  3. data/CHANGELOG.markdown +7 -57
  4. data/ext/allocations/allocations.c +84 -0
  5. data/ext/allocations/extconf.rb +3 -0
  6. data/lib/scout_apm/agent/reporting.rb +9 -32
  7. data/lib/scout_apm/agent.rb +45 -31
  8. data/lib/scout_apm/app_server_load.rb +1 -2
  9. data/lib/scout_apm/attribute_arranger.rb +0 -4
  10. data/lib/scout_apm/background_worker.rb +6 -9
  11. data/lib/scout_apm/bucket_name_splitter.rb +3 -3
  12. data/lib/scout_apm/call_set.rb +1 -0
  13. data/lib/scout_apm/config.rb +110 -66
  14. data/lib/scout_apm/environment.rb +16 -10
  15. data/lib/scout_apm/framework_integrations/rails_2.rb +12 -14
  16. data/lib/scout_apm/framework_integrations/rails_3_or_4.rb +5 -17
  17. data/lib/scout_apm/framework_integrations/ruby.rb +0 -4
  18. data/lib/scout_apm/framework_integrations/sinatra.rb +0 -4
  19. data/lib/scout_apm/histogram.rb +0 -20
  20. data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +1 -4
  21. data/lib/scout_apm/instruments/active_record.rb +149 -8
  22. data/lib/scout_apm/instruments/mongoid.rb +5 -78
  23. data/lib/scout_apm/instruments/process/process_cpu.rb +0 -12
  24. data/lib/scout_apm/instruments/process/process_memory.rb +14 -43
  25. data/lib/scout_apm/layaway.rb +34 -134
  26. data/lib/scout_apm/layaway_file.rb +50 -27
  27. data/lib/scout_apm/layer.rb +45 -1
  28. data/lib/scout_apm/layer_converters/allocation_metric_converter.rb +17 -0
  29. data/lib/scout_apm/layer_converters/converter_base.rb +4 -6
  30. data/lib/scout_apm/layer_converters/job_converter.rb +1 -0
  31. data/lib/scout_apm/layer_converters/metric_converter.rb +2 -1
  32. data/lib/scout_apm/layer_converters/slow_job_converter.rb +42 -21
  33. data/lib/scout_apm/layer_converters/slow_request_converter.rb +58 -37
  34. data/lib/scout_apm/metric_meta.rb +1 -5
  35. data/lib/scout_apm/metric_set.rb +6 -15
  36. data/lib/scout_apm/reporter.rb +4 -6
  37. data/lib/scout_apm/serializers/metrics_to_json_serializer.rb +5 -1
  38. data/lib/scout_apm/serializers/payload_serializer_to_json.rb +1 -3
  39. data/lib/scout_apm/serializers/slow_jobs_serializer_to_json.rb +5 -3
  40. data/lib/scout_apm/slow_job_policy.rb +19 -89
  41. data/lib/scout_apm/slow_job_record.rb +12 -20
  42. data/lib/scout_apm/slow_request_policy.rb +12 -80
  43. data/lib/scout_apm/slow_transaction.rb +16 -20
  44. data/lib/scout_apm/stackprof_tree_collapser.rb +103 -0
  45. data/lib/scout_apm/store.rb +16 -78
  46. data/lib/scout_apm/tracked_request.rb +53 -36
  47. data/lib/scout_apm/utils/active_record_metric_name.rb +2 -0
  48. data/lib/scout_apm/utils/fake_stack_prof.rb +40 -0
  49. data/lib/scout_apm/utils/klass_helper.rb +26 -0
  50. data/lib/scout_apm/utils/sql_sanitizer.rb +1 -1
  51. data/lib/scout_apm/utils/sql_sanitizer_regex.rb +2 -2
  52. data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +2 -2
  53. data/lib/scout_apm/version.rb +1 -1
  54. data/lib/scout_apm.rb +13 -7
  55. data/scout_apm.gemspec +3 -1
  56. data/test/test_helper.rb +3 -4
  57. data/test/unit/layaway_test.rb +8 -5
  58. data/test/unit/serializers/payload_serializer_test.rb +2 -2
  59. data/test/unit/slow_item_set_test.rb +1 -2
  60. data/test/unit/sql_sanitizer_test.rb +0 -6
  61. metadata +28 -20
  62. data/LICENSE.md +0 -27
  63. data/lib/scout_apm/instruments/grape.rb +0 -69
  64. data/lib/scout_apm/instruments/percentile_sampler.rb +0 -37
  65. data/lib/scout_apm/request_histograms.rb +0 -46
  66. data/lib/scout_apm/scored_item_set.rb +0 -79
  67. data/test/unit/metric_set_test.rb +0 -101
  68. data/test/unit/scored_item_set_test.rb +0 -65
  69. data/test/unit/slow_request_policy_test.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60e5f3ca394fce2b63871b71be1225d9634687aa
4
- data.tar.gz: 330e89e41635be1c597179faaca221af76ccbd2e
3
+ metadata.gz: b18724905e7c795caad3fc416688b3044e624d79
4
+ data.tar.gz: ee4ec99aeb9fa9e32c7b846caec0f010070546c2
5
5
  SHA512:
6
- metadata.gz: 0d9aa3156586ae561fd952135e0974157ae2d33347d772db695fd1d7519109a0fc2b6ae663163930d76c5f701c8282357fd70c7694299bafa53092369ff61b6c
7
- data.tar.gz: 189eba2d8cafd88043b09665e82a73560b3e53a418b3846b8f796d4e80f895a1e2082e8cb5e5bf43d8ec0eb8aef0e39b5c19649d6445700596e0509c88cda41c
6
+ metadata.gz: 236bfd93df93733c409684ac735dfbc77b5412f221127b5acbec9fc679b3141c6ac8e4c46c485295532aee7821b8fda36edd648233f820ed045d667905237448
7
+ data.tar.gz: 4b43e6158568bd089b3174bd8af445baef2260f92a33c31b50ed8627722a9f194fc2e4352c509c12e677e71f824e04e22226ce5c1b7a5c542f2e806167c0aabb
data/.gitignore CHANGED
@@ -5,6 +5,13 @@ Gemfile.lock
5
5
  pkg/*
6
6
  .rvmrc
7
7
  .idea
8
+ test/tmp/*
9
+ /tmp
10
+ /ext/stack_profile/stack_profile.bundle
11
+ /ext/stack_profile/stack_profile.so
12
+ /ext/stack_profile/stack_profile.o
13
+ /ext/stack_profile/mkmf.log
14
+ /ext/stack_profile/Makefile
15
+ .DS_Store
8
16
  test/tmp/*coverage/*
9
17
  coverage/*
10
- lib/*.bundle
data/CHANGELOG.markdown CHANGED
@@ -1,67 +1,17 @@
1
- # 1.6.8
1
+ # 2.0.0
2
2
 
3
- * Don't wait on a sleeping thread during shutdown
4
-
5
- # 1.6.7
6
-
7
- * Mongoid bugfixes
8
-
9
- # 1.6.6
10
-
11
- * Bugfix related to DB detection
12
-
13
- # 1.6.5
14
-
15
- * Add Mongoid 5.x support
16
- * Fix autodetection of mysql databases
17
-
18
- # 1.6.4
19
-
20
- * Add Grape instrumentation
21
- * Handle DATABASE_URL configurations better
22
- * Change default (undeteced) database to Postgres (was Mysql)
23
-
24
- # 1.6.3
25
-
26
- * Handle nil ignore_traces when ignoring trace patterns
27
-
28
- # 1.6.2
29
-
30
- * Use a more flexible approach to storing "Layaway Files" (the temporary data
31
- files the agent uses).
32
-
33
- # 1.6.1
34
-
35
- * Remove old & unused references to Stackprof. Prevent interaction with intentional usage of Stackprof
36
-
37
- # 1.6.0
38
-
39
- * Dynamic algorithm for selecting when to collect traces. Now, we will collect a
40
- more complete cross-section of your application's performance, dynamically
41
- tuned as your application runs.
42
- * Record and report 95th percentiles for each action
43
- * A variety of bug fixes
44
-
45
- # 1.5.5
46
-
47
- * Handle backslash escaped quotes inside mysql strings.
48
-
49
- # 1.5.4
50
-
51
- * Fix issue where error counts were being misreported
52
- * Politely ignore cases when `request.remote_ip` raises exceptions.
53
-
54
- # 1.5.3
55
-
56
- * Fix another minor bug related to iso8601 timestamps
3
+ * Reporting object allocation metrics and mem delta with slow requests and jobs.
57
4
 
58
5
  # 1.5.2
59
6
 
60
- * Force timestamps to be iso8601 format
7
+ * Fix deploy webhook endpoint
61
8
 
62
9
  # 1.5.1
63
10
 
64
- * Add `ignore_traces` config option to ignore SlowTransactions from certain URIs.
11
+ * Collecting memory metrics on slow transactions
12
+ * Collecting additional fields for slow transactions:
13
+ * hostname
14
+ * seconds_since_startup (larger memory increases and other other odd behavior more common when close to startup)
65
15
 
66
16
  # 1.5.0
67
17
 
@@ -0,0 +1,84 @@
1
+ #include <ruby/ruby.h>
2
+
3
+ VALUE mScoutApm;
4
+ VALUE mInstruments;
5
+ VALUE cAllocations;
6
+
7
+ #ifdef RUBY_INTERNAL_EVENT_NEWOBJ
8
+
9
+ #include <sys/resource.h> // is this needed?
10
+ #include <sys/time.h>
11
+ #include <ruby/debug.h>
12
+
13
+ static __thread uint64_t endpoint_allocations;
14
+ void increment_allocations() {
15
+ endpoint_allocations++;
16
+ }
17
+
18
+ static VALUE
19
+ get_allocation_count() {
20
+ return ULL2NUM(endpoint_allocations);
21
+ }
22
+
23
+ static void
24
+ tracepoint_handler(VALUE tpval, void *data)
25
+ {
26
+ rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
27
+ if (rb_tracearg_event_flag(tparg) == RUBY_INTERNAL_EVENT_NEWOBJ) {
28
+ increment_allocations();
29
+ }
30
+ }
31
+
32
+ static VALUE
33
+ set_gc_hook(rb_event_flag_t event)
34
+ {
35
+ VALUE tpval;
36
+ // TODO - need to prevent applying the same tracepoint multiple times?
37
+ tpval = rb_tracepoint_new(0, event, tracepoint_handler, 0);
38
+ rb_tracepoint_enable(tpval);
39
+
40
+ return tpval;
41
+ }
42
+
43
+ void
44
+ Init_hooks(VALUE module)
45
+ {
46
+ set_gc_hook(RUBY_INTERNAL_EVENT_NEWOBJ);
47
+ }
48
+
49
+ void Init_allocations()
50
+ {
51
+ mScoutApm = rb_define_module("ScoutApm");
52
+ mInstruments = rb_define_module_under(mScoutApm, "Instruments");
53
+ cAllocations = rb_define_class_under(mInstruments, "Allocations", rb_cObject);
54
+ rb_define_singleton_method(cAllocations, "count", get_allocation_count, 0);
55
+ rb_define_singleton_method(cAllocations, "count", get_allocation_count, 0);
56
+ rb_define_const(cAllocations, "ENABLED", Qtrue);
57
+ Init_hooks(mScoutApm);
58
+ }
59
+
60
+ #else
61
+
62
+ static VALUE
63
+ get_allocation_count() {
64
+ return ULL2NUM(0);
65
+ }
66
+
67
+ void
68
+ Init_hooks(VALUE module)
69
+ {
70
+ }
71
+
72
+ void Init_allocations()
73
+ {
74
+ mScoutApm = rb_define_module("ScoutApm");
75
+ mInstruments = rb_define_module_under(mScoutApm, "Instruments");
76
+ cAllocations = rb_define_class_under(mInstruments, "Allocations", rb_cObject);
77
+ rb_define_singleton_method(cAllocations, "count", get_allocation_count, 0);
78
+ rb_define_singleton_method(cAllocations, "count", get_allocation_count, 0);
79
+ rb_define_const(cAllocations, "ENABLED", Qfalse);
80
+ Init_hooks(mScoutApm);
81
+ }
82
+
83
+ #endif //#ifdef RUBY_INTERNAL_EVENT_NEWOBJ
84
+
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('allocations')
@@ -24,35 +24,17 @@ module ScoutApm
24
24
  report_to_server
25
25
  end
26
26
 
27
+ MAX_AGE_TO_REPORT = (10 * 60) # ten minutes as seconds
28
+
27
29
  # In a running app, one process will get one period ready for delivery, the others will see 0.
28
30
  def report_to_server
29
- period_to_report = ScoutApm::StoreReportingPeriodTimestamp.minutes_ago(2)
30
-
31
- logger.debug("Attempting to claim #{period_to_report.to_s}")
32
-
33
- did_write = layaway.with_claim(period_to_report) do |rps|
34
- logger.debug("Succeeded claiming #{period_to_report.to_s}")
35
-
36
- begin
37
- merged = rps.inject { |memo, rp| memo.merge(rp) }
38
- logger.debug("Merged #{rps.length} reporting periods, delivering")
39
- deliver_period(merged)
40
- true
41
- rescue => e
42
- logger.debug("Error merging reporting periods #{e.message}")
43
- logger.debug("Error merging reporting periods #{e.backtrace}")
44
- false
45
- end
46
-
31
+ reporting_periods = layaway.periods_ready_for_delivery
32
+ reporting_periods.reject! {|rp| rp.timestamp.age_in_seconds > MAX_AGE_TO_REPORT }
33
+ reporting_periods.each do |rp|
34
+ deliver_period(rp)
47
35
  end
48
-
49
- if !did_write
50
- logger.debug("Failed to obtain claim for #{period_to_report.to_s}")
51
- end
52
-
53
36
  end
54
37
 
55
-
56
38
  def deliver_period(reporting_period)
57
39
  metrics = reporting_period.metrics_payload
58
40
  slow_transactions = reporting_period.slow_transactions_payload
@@ -68,7 +50,7 @@ module ScoutApm
68
50
  :platform => "ruby",
69
51
  }
70
52
 
71
- log_deliver(metrics, slow_transactions, metadata, slow_jobs)
53
+ log_deliver(metrics, slow_transactions, metadata)
72
54
 
73
55
  payload = ScoutApm::Serializers::PayloadSerializer.serialize(metadata, metrics, slow_transactions, jobs, slow_jobs)
74
56
  logger.debug("Payload: #{payload}")
@@ -80,7 +62,7 @@ module ScoutApm
80
62
  logger.debug e.backtrace
81
63
  end
82
64
 
83
- def log_deliver(metrics, slow_transactions, metadata, jobs_traces)
65
+ def log_deliver(metrics, slow_transactions, metadata)
84
66
  total_request_count = metrics.
85
67
  select { |meta,stats| meta.metric_name =~ /\AController/ }.
86
68
  inject(0) {|sum, (_, stat)| sum + stat.call_count }
@@ -93,12 +75,7 @@ module ScoutApm
93
75
  "Recorded across (unknown) processes"
94
76
  end
95
77
 
96
- time_clause = "[#{Time.parse(metadata[:agent_time]).strftime("%H:%M")}]"
97
- metrics_clause = "#{metrics.length} Metrics for #{total_request_count} requests"
98
- slow_trans_clause = "#{slow_transactions.length} Slow Transaction Traces"
99
- job_clause = "#{jobs_traces.length} Job Traces"
100
-
101
- logger.info "#{time_clause} Delivering #{metrics_clause} and #{slow_trans_clause} and #{job_clause}, #{process_log_str}."
78
+ logger.info "[#{Time.parse(metadata[:agent_time]).strftime("%H:%M")}] Delivering #{metrics.length} Metrics for #{total_request_count} requests and #{slow_transactions.length} Slow Transaction Traces, #{process_log_str}."
102
79
  logger.debug("Metrics: #{metrics.pretty_inspect}\nSlowTrans: #{slow_transactions.pretty_inspect}\nMetadata: #{metadata.inspect.pretty_inspect}")
103
80
  end
104
81
 
@@ -19,13 +19,7 @@ module ScoutApm
19
19
  attr_accessor :metric_lookup # Hash used to lookup metric ids based on their name and scope
20
20
  attr_reader :slow_request_policy
21
21
  attr_reader :slow_job_policy
22
-
23
- # Histogram of the cumulative requests since the start of the process
24
- attr_reader :request_histograms
25
-
26
- # Histogram of the requests, distinct by reporting period (minute)
27
- # { StoreReportingPeriodTimestamp => RequestHistograms }
28
- attr_reader :request_histograms_by_time
22
+ attr_reader :process_start_time # used when creating slow transactions to report how far from startup the transaction was recorded.
29
23
 
30
24
  # All access to the agent is thru this class method to ensure multiple Agent instances are not initialized per-Ruby process.
31
25
  def self.instance(options = {})
@@ -37,18 +31,24 @@ module ScoutApm
37
31
  # be started (when forking).
38
32
  def initialize(options = {})
39
33
  @started = false
34
+ @process_start_time = Time.now
40
35
  @options ||= options
41
- @config = ScoutApm::Config.new(options[:config_path])
42
36
 
43
- @slow_request_policy = ScoutApm::SlowRequestPolicy.new
37
+ # Start up without attempting to load a configuration file. We need to be
38
+ # able to lookup configuration options like "application_root" which would
39
+ # then in turn influence where the configuration file came from.
40
+ #
41
+ # Later in initialization, we reset @config to include the file.
42
+ @config = ScoutApm::Config.without_file
43
+
44
44
  @slow_job_policy = ScoutApm::SlowJobPolicy.new
45
- @request_histograms = ScoutApm::RequestHistograms.new
46
- @request_histograms_by_time = Hash.new { |h, k| h[k] = ScoutApm::RequestHistograms.new }
47
45
 
48
46
  @store = ScoutApm::Store.new
49
47
  @layaway = ScoutApm::Layaway.new
50
48
  @metric_lookup = Hash.new
51
49
 
50
+ @slow_request_policy = ScoutApm::SlowRequestPolicy.new
51
+
52
52
  @capacity = ScoutApm::Capacity.new
53
53
  @installed_instruments = []
54
54
  end
@@ -78,7 +78,11 @@ module ScoutApm
78
78
  end
79
79
 
80
80
  if app_server_missing?(options) && background_job_missing?
81
- logger.warn "Couldn't find a supported app server or background job framework. #{force? ? 'Forcing agent to start' : 'Not starting agent'}."
81
+ if force?
82
+ logger.warn "Agent starting (forced)"
83
+ else
84
+ logger.warn "Deferring agent start. Standing by for first request"
85
+ end
82
86
  return false unless force?
83
87
  end
84
88
 
@@ -99,6 +103,7 @@ module ScoutApm
99
103
  # It initializes the agent and starts the worker thread (if appropiate).
100
104
  def start(options = {})
101
105
  @options.merge!(options)
106
+ @config = ScoutApm::Config.with_file(@config.value("config_file"))
102
107
  init_logger
103
108
  logger.info "Attempting to start Scout Agent [#{ScoutApm::VERSION}] on [#{environment.hostname}]"
104
109
 
@@ -112,10 +117,10 @@ module ScoutApm
112
117
 
113
118
  load_instruments if should_load_instruments?(options)
114
119
 
115
- [ ScoutApm::Instruments::Process::ProcessCpu.new(environment.processors, logger),
116
- ScoutApm::Instruments::Process::ProcessMemory.new(logger),
117
- ScoutApm::Instruments::PercentileSampler.new(logger, 95),
118
- ].each { |s| store.add_sampler(s) }
120
+ @samplers = [
121
+ ScoutApm::Instruments::Process::ProcessCpu.new(environment.processors, logger),
122
+ ScoutApm::Instruments::Process::ProcessMemory.new(logger)
123
+ ]
119
124
 
120
125
  app_server_load_hook
121
126
 
@@ -183,19 +188,14 @@ module ScoutApm
183
188
  def shutdown
184
189
  logger.info "Shutting down ScoutApm"
185
190
  return if !started?
186
-
187
191
  if @background_worker
188
- logger.info("Stopping background worker")
189
192
  @background_worker.stop
190
193
  store.write_to_layaway(layaway, :force)
191
194
  end
192
195
 
193
196
  # Make sure we don't exit the process while the background worker is running its task.
194
197
  logger.debug "Joining background worker thread"
195
- if @background_worker_thread
196
- @background_worker_thread.wakeup
197
- @background_worker_thread.join
198
- end
198
+ @background_worker_thread.join if @background_worker_thread
199
199
  end
200
200
 
201
201
  def started?
@@ -232,19 +232,16 @@ module ScoutApm
232
232
  @background_worker = ScoutApm::BackgroundWorker.new
233
233
  @background_worker_thread = Thread.new do
234
234
  @background_worker.start {
235
+ # First, run periodic samplers. These should run once a minute,
236
+ # rather than per-request. "CPU Load" and similar.
237
+ run_samplers
238
+ capacity.process
239
+
235
240
  ScoutApm::Agent.instance.process_metrics
236
- clean_old_percentiles
237
241
  }
238
242
  end
239
243
  end
240
244
 
241
- def clean_old_percentiles
242
- request_histograms_by_time.
243
- keys.
244
- select {|timestamp| timestamp.age_in_seconds > 60 * 10 }.
245
- each {|old_timestamp| request_histograms_by_time.delete(old_timestamp) }
246
- end
247
-
248
245
  # If we want to skip the app_server_check, then we must load it.
249
246
  def should_load_instruments?(options={})
250
247
  return true if options[:skip_app_server_check]
@@ -277,7 +274,10 @@ module ScoutApm
277
274
  install_instrument(ScoutApm::Instruments::Redis)
278
275
  install_instrument(ScoutApm::Instruments::InfluxDB)
279
276
  install_instrument(ScoutApm::Instruments::Elasticsearch)
280
- install_instrument(ScoutApm::Instruments::Grape)
277
+
278
+ if StackProf.respond_to?(:fake?) && StackProf.fake?
279
+ logger.info 'StackProf not found - add `gem "stackprof"` to your Gemfile to enable advanced code profiling (only for Ruby 2.1+)'
280
+ end
281
281
  rescue
282
282
  logger.warn "Exception loading instruments:"
283
283
  logger.warn $!.message
@@ -304,6 +304,20 @@ module ScoutApm
304
304
  environment.deploy_integration
305
305
  end
306
306
 
307
+ # TODO: Extract a proper class / registery for these. They don't really belong here
308
+ def run_samplers
309
+ @samplers.each do |sampler|
310
+ begin
311
+ result = sampler.run
312
+ store.track_one!(sampler.metric_type, sampler.metric_name, result) if result
313
+ rescue => e
314
+ logger.info "Error reading #{sampler.human_name}"
315
+ logger.debug e.message
316
+ logger.debug e.backtrace.join("\n")
317
+ end
318
+ end
319
+ end
320
+
307
321
  def app_server_missing?(options = {})
308
322
  !environment.app_server_integration(true).found? && !options[:skip_app_server_check]
309
323
  end
@@ -34,8 +34,7 @@ module ScoutApm
34
34
  :app_server => ScoutApm::Environment.instance.app_server,
35
35
  :ruby_version => RUBY_VERSION,
36
36
  :hostname => ScoutApm::Environment.instance.hostname,
37
- :database_engine => ScoutApm::Environment.instance.database_engine, # Detected
38
- :database_adapter => ScoutApm::Environment.instance.raw_database_adapter, # Raw
37
+ :database_engine => ScoutApm::Environment.instance.database_engine,
39
38
  :application_name => ScoutApm::Environment.instance.application_name,
40
39
  :libraries => ScoutApm::Utils::InstalledGems.new.run,
41
40
  :paas => ScoutApm::Environment.instance.platform_integration.name
@@ -7,10 +7,6 @@ module ScoutApm
7
7
  case attribute
8
8
  when Array
9
9
  attribute_hash[attribute[0]] = subject.send(attribute[1])
10
- when :bucket
11
- attribute_hash[attribute] = subject.bucket_type
12
- when :name
13
- attribute_hash[attribute] = subject.bucket_name
14
10
  when Symbol
15
11
  attribute_hash[attribute] = subject.send(attribute)
16
12
  end
@@ -12,7 +12,6 @@ module ScoutApm
12
12
  end
13
13
 
14
14
  def stop
15
- ScoutApm::Agent.instance.logger.debug "Background Worker: stop requested"
16
15
  @keep_running = false
17
16
  end
18
17
 
@@ -26,33 +25,31 @@ module ScoutApm
26
25
  @task = block
27
26
 
28
27
  begin
29
- ScoutApm::Agent.instance.logger.debug "Background Worker: Starting Background Worker, running every #{period} seconds"
28
+ ScoutApm::Agent.instance.logger.debug "Starting Background Worker, running every #{period} seconds"
30
29
 
31
30
  # The first run should be 1 period of time from now
32
31
  next_time = Time.now + period
33
32
 
34
33
  loop do
35
- # Bail out if @keep_running is false
36
- unless @keep_running
37
- ScoutApm::Agent.instance.logger.debug "Background Worker: breaking from loop"
38
- break
39
- end
40
-
41
34
  now = Time.now
42
35
 
43
36
  # Sleep the correct amount of time to reach next_time
44
- while now < next_time && @keep_running
37
+ while now < next_time
45
38
  sleep_time = next_time - now
46
39
  sleep(sleep_time) if sleep_time > 0
47
40
  now = Time.now
48
41
  end
49
42
 
43
+ # Bail out if @keep_running is false
44
+ break unless @keep_running
45
+
50
46
  @task.call
51
47
 
52
48
  # Adjust the next time to run forward by @periods until it is in the future
53
49
  while next_time <= now
54
50
  next_time += period
55
51
  end
52
+
56
53
  end
57
54
  rescue
58
55
  ScoutApm::Agent.instance.logger.debug "Background Worker Exception!"
@@ -1,15 +1,15 @@
1
1
  module ScoutApm
2
2
  module BucketNameSplitter
3
- def bucket_type
3
+ def bucket
4
4
  split_metric_name(metric_name).first
5
5
  end
6
6
 
7
- def bucket_name
7
+ def name
8
8
  split_metric_name(metric_name).last
9
9
  end
10
10
 
11
11
  def key
12
- {:bucket => bucket_type, :name => bucket_name}
12
+ {:bucket => bucket, :name => name}
13
13
  end
14
14
 
15
15
  private
@@ -1,4 +1,5 @@
1
1
  module ScoutApm
2
+ # Encapsulates our logic to determine when a backtrace should be collected.
2
3
  class CallSet
3
4
 
4
5
  N_PLUS_ONE_MAGIC_NUMBER = 5 # Fetch backtraces on this number of calls to a layer. The caller data is only collected on this call to limit overhead.