scout_apm 3.0.0.pre13 → 3.0.0.pre14

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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/lib/scout_apm.rb +20 -10
  3. data/lib/scout_apm/agent.rb +114 -319
  4. data/lib/scout_apm/agent/exit_handler.rb +66 -0
  5. data/lib/scout_apm/agent/preconditions.rb +69 -0
  6. data/lib/scout_apm/agent_context.rb +234 -0
  7. data/lib/scout_apm/app_server_load.rb +24 -14
  8. data/lib/scout_apm/background_job_integrations/resque.rb +7 -8
  9. data/lib/scout_apm/background_job_integrations/sidekiq.rb +2 -2
  10. data/lib/scout_apm/background_recorder.rb +8 -3
  11. data/lib/scout_apm/background_worker.rb +14 -7
  12. data/lib/scout_apm/config.rb +35 -26
  13. data/lib/scout_apm/context.rb +11 -4
  14. data/lib/scout_apm/db_query_metric_set.rb +17 -5
  15. data/lib/scout_apm/debug.rb +1 -1
  16. data/lib/scout_apm/environment.rb +10 -14
  17. data/lib/scout_apm/framework_integrations/sinatra.rb +1 -1
  18. data/lib/scout_apm/git_revision.rb +13 -8
  19. data/lib/scout_apm/histogram.rb +1 -1
  20. data/lib/scout_apm/instant/middleware.rb +7 -7
  21. data/lib/scout_apm/instant_reporting.rb +7 -7
  22. data/lib/scout_apm/instrument_manager.rb +87 -0
  23. data/lib/scout_apm/instruments/action_controller_rails_2.rb +12 -7
  24. data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +17 -12
  25. data/lib/scout_apm/instruments/action_view.rb +11 -7
  26. data/lib/scout_apm/instruments/active_record.rb +25 -11
  27. data/lib/scout_apm/instruments/elasticsearch.rb +10 -6
  28. data/lib/scout_apm/instruments/grape.rb +12 -8
  29. data/lib/scout_apm/instruments/http_client.rb +10 -6
  30. data/lib/scout_apm/instruments/influxdb.rb +10 -6
  31. data/lib/scout_apm/instruments/middleware_detailed.rb +11 -5
  32. data/lib/scout_apm/instruments/middleware_summary.rb +11 -5
  33. data/lib/scout_apm/instruments/mongoid.rb +10 -5
  34. data/lib/scout_apm/instruments/moped.rb +11 -6
  35. data/lib/scout_apm/instruments/net_http.rb +10 -6
  36. data/lib/scout_apm/instruments/percentile_sampler.rb +8 -6
  37. data/lib/scout_apm/instruments/process/process_cpu.rb +8 -4
  38. data/lib/scout_apm/instruments/process/process_memory.rb +15 -10
  39. data/lib/scout_apm/instruments/rails_router.rb +12 -6
  40. data/lib/scout_apm/instruments/redis.rb +10 -6
  41. data/lib/scout_apm/instruments/samplers.rb +11 -0
  42. data/lib/scout_apm/instruments/sinatra.rb +5 -4
  43. data/lib/scout_apm/layaway.rb +21 -20
  44. data/lib/scout_apm/layaway_file.rb +8 -3
  45. data/lib/scout_apm/layer.rb +3 -3
  46. data/lib/scout_apm/layer_converters/converter_base.rb +6 -7
  47. data/lib/scout_apm/layer_converters/database_converter.rb +1 -1
  48. data/lib/scout_apm/layer_converters/histograms.rb +2 -2
  49. data/lib/scout_apm/layer_converters/slow_job_converter.rb +4 -3
  50. data/lib/scout_apm/layer_converters/slow_request_converter.rb +5 -4
  51. data/lib/scout_apm/logger.rb +143 -0
  52. data/lib/scout_apm/middleware.rb +7 -9
  53. data/lib/scout_apm/periodic_work.rb +28 -0
  54. data/lib/scout_apm/reporter.rb +14 -8
  55. data/lib/scout_apm/reporting.rb +135 -0
  56. data/lib/scout_apm/request_manager.rb +4 -6
  57. data/lib/scout_apm/serializers/payload_serializer.rb +1 -1
  58. data/lib/scout_apm/slow_job_policy.rb +6 -2
  59. data/lib/scout_apm/slow_job_record.rb +5 -5
  60. data/lib/scout_apm/slow_request_policy.rb +6 -2
  61. data/lib/scout_apm/slow_transaction.rb +5 -5
  62. data/lib/scout_apm/store.rb +22 -16
  63. data/lib/scout_apm/synchronous_recorder.rb +7 -3
  64. data/lib/scout_apm/tasks/doctor.rb +75 -0
  65. data/lib/scout_apm/tasks/support.rb +22 -0
  66. data/lib/scout_apm/tracer.rb +5 -5
  67. data/lib/scout_apm/tracked_request.rb +43 -19
  68. data/lib/scout_apm/utils/active_record_metric_name.rb +66 -8
  69. data/lib/scout_apm/utils/backtrace_parser.rb +1 -1
  70. data/lib/scout_apm/utils/installed_gems.rb +7 -3
  71. data/lib/scout_apm/utils/klass_helper.rb +8 -2
  72. data/lib/scout_apm/utils/scm.rb +1 -1
  73. data/lib/scout_apm/utils/sql_sanitizer.rb +3 -3
  74. data/lib/scout_apm/version.rb +1 -1
  75. data/lib/tasks/doctor.rake +11 -0
  76. data/scout_apm.gemspec +1 -0
  77. data/test/test_helper.rb +17 -2
  78. data/test/unit/agent_test.rb +1 -54
  79. data/test/unit/config_test.rb +9 -5
  80. data/test/unit/context_test.rb +4 -4
  81. data/test/unit/db_query_metric_set_test.rb +11 -4
  82. data/test/unit/fake_store_test.rb +1 -1
  83. data/test/unit/git_revision_test.rb +3 -3
  84. data/test/unit/instruments/net_http_test.rb +2 -1
  85. data/test/unit/instruments/percentile_sampler_test.rb +5 -9
  86. data/test/unit/layaway_test.rb +10 -5
  87. data/test/unit/layer_converters/metric_converter_test.rb +2 -2
  88. data/test/unit/slow_request_policy_test.rb +7 -3
  89. data/test/unit/sql_sanitizer_test.rb +0 -6
  90. data/test/unit/store_test.rb +11 -8
  91. data/test/unit/utils/active_record_metric_name_test.rb +45 -7
  92. metadata +27 -5
  93. data/lib/scout_apm/agent/logging.rb +0 -74
  94. data/lib/scout_apm/agent/reporting.rb +0 -129
  95. data/lib/scout_apm/utils/null_logger.rb +0 -13
@@ -5,8 +5,10 @@ module ScoutApm
5
5
  def initialize(app)
6
6
  @app = app
7
7
  @attempts = 0
8
- @enabled = ScoutApm::Agent.instance.apm_enabled?
9
- @started = ScoutApm::Agent.instance.started? && ScoutApm::Agent.instance.background_worker_running?
8
+ # @enabled = ScoutApm::Agent.instance.context.apm_enabled?
9
+ # XXX: Figure out if this middleware should even know
10
+ @enabled = true
11
+ @started = ScoutApm::Agent.instance.context.started? && ScoutApm::Agent.instance.background_worker_running?
10
12
  end
11
13
 
12
14
  # If we get a web request in, then we know we're running in some sort of app server
@@ -21,14 +23,10 @@ module ScoutApm
21
23
 
22
24
  def attempt_to_start_agent
23
25
  @attempts += 1
24
- ScoutApm::Agent.instance.start(:skip_app_server_check => true)
25
- ScoutApm::Agent.instance.start_background_worker
26
- @started = ScoutApm::Agent.instance.started? && ScoutApm::Agent.instance.background_worker_running?
26
+ ScoutApm::Agent.instance.start
27
+ @started = ScoutApm::Agent.instance.context.started? && ScoutApm::Agent.instance.background_worker_running?
27
28
  rescue => e
28
- # Can't be sure of any logging here, so fall back to ENV var and STDOUT
29
- if ENV["SCOUT_LOG_LEVEL"] == "debug"
30
- STDOUT.puts "Failed to start via Middleware: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
31
- end
29
+ ScoutApm::Agent.instance.context.logger("Failed to start via Middleware: #{e.message}\n\t#{e.backtrace.join("\n\t")}")
32
30
  end
33
31
  end
34
32
  end
@@ -0,0 +1,28 @@
1
+ module ScoutApm
2
+ class PeriodicWork
3
+ attr_reader :context
4
+
5
+ def initialize(context)
6
+ @context = context
7
+ @reporting = ScoutApm::Reporting.new(context)
8
+ end
9
+
10
+ # Expected to be called many times over the life of the agent
11
+ def run
12
+ ScoutApm::Debug.instance.call_periodic_hooks
13
+ @reporting.process_metrics
14
+ clean_old_percentiles
15
+ end
16
+
17
+ private
18
+
19
+ # XXX: Move logic into a RequestHistogramsByTime class that can keep the timeout logic in it
20
+ def clean_old_percentiles
21
+ context.
22
+ request_histograms_by_time.
23
+ keys.
24
+ select {|timestamp| timestamp.age_in_seconds > 60 * 10 }.
25
+ each {|old_timestamp| context.request_histograms_by_time.delete(old_timestamp) }
26
+ end
27
+ end
28
+ end
@@ -5,18 +5,24 @@ module ScoutApm
5
5
  CA_FILE = File.join( File.dirname(__FILE__), *%w[.. .. data cacert.pem] )
6
6
  VERIFY_MODE = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
7
7
 
8
- attr_reader :config
9
- attr_reader :logger
10
8
  attr_reader :type
9
+ attr_reader :context
11
10
  attr_reader :instant_key
12
11
 
13
- def initialize(type = :checkin, config=Agent.instance.config, logger=Agent.instance.logger, instant_key=nil)
14
- @config = config
15
- @logger = logger
12
+ def initialize(context, type, instant_key=nil)
13
+ @context = context
16
14
  @type = type
17
15
  @instant_key = instant_key
18
16
  end
19
17
 
18
+ def config
19
+ context.config
20
+ end
21
+
22
+ def logger
23
+ context.logger
24
+ end
25
+
20
26
  def report(payload, headers = {})
21
27
  hosts = determine_hosts
22
28
 
@@ -27,14 +33,14 @@ module ScoutApm
27
33
  headers.merge!(compression_headers)
28
34
 
29
35
  compress_payload_size = payload.length
30
- ScoutApm::Agent.instance.logger.debug("Original Size: #{original_payload_size} Compressed Size: #{compress_payload_size}")
36
+ logger.debug("Original Size: #{original_payload_size} Compressed Size: #{compress_payload_size}")
31
37
  end
32
38
 
33
39
  post_payload(hosts, payload, headers)
34
40
  end
35
41
 
36
42
  def uri(host)
37
- encoded_app_name = CGI.escape(Environment.instance.application_name)
43
+ encoded_app_name = CGI.escape(context.environment.application_name)
38
44
  key = config.value('key')
39
45
 
40
46
  case type
@@ -100,7 +106,7 @@ module ScoutApm
100
106
 
101
107
  # Headers passed up with all API requests.
102
108
  def default_http_headers
103
- { "Agent-Hostname" => ScoutApm::Environment.instance.hostname,
109
+ { "Agent-Hostname" => context.environment.hostname,
104
110
  "Content-Type" => "application/octet-stream",
105
111
  "Agent-Version" => ScoutApm::VERSION,
106
112
  }
@@ -0,0 +1,135 @@
1
+ # Methods related to sending metrics to scoutapp.com.
2
+ module ScoutApm
3
+ class Reporting
4
+ attr_reader :context
5
+
6
+ def initialize(context)
7
+ @context = context
8
+ end
9
+
10
+ def logger
11
+ context.logger
12
+ end
13
+
14
+ def reporter
15
+ @reporter ||= ScoutApm::Reporter.new(context, :checkin)
16
+ end
17
+
18
+ # The data moves through a treadmill of reporting, coordinating several Rails processes by using an external file.
19
+ # * During the minute it is being recorded by the instruments, it gets
20
+ # recorded into the ram of each process (in the Store class).
21
+ # * The minute after, each process writes its own metrics to a shared LayawayFile
22
+ # * The minute after that, the first process to wake up pushes the combined
23
+ # data to the server, and wipes it. Next processes don't have anything to do.
24
+ #
25
+ # At any given point, there is data in each of those steps, moving its way through the process
26
+ def process_metrics
27
+ # Write the previous minute's data to the shared-across-process layaway file.
28
+ context.store.write_to_layaway(context.layaway)
29
+
30
+ # Attempt to send 2 minutes ago's data up to the server. This
31
+ # only acctually occurs if this process is the first to wake up this
32
+ # minute.
33
+ report_to_server
34
+ end
35
+
36
+ # In a running app, one process will get the period ready for delivery, the others will see 0.
37
+ def report_to_server
38
+ period_to_report = ScoutApm::StoreReportingPeriodTimestamp.minutes_ago(2)
39
+
40
+ logger.debug("Attempting to claim #{period_to_report.to_s}")
41
+
42
+ did_write = context.layaway.with_claim(period_to_report) do |rps|
43
+ logger.debug("Succeeded claiming #{period_to_report.to_s}")
44
+
45
+ begin
46
+ merged = rps.inject { |memo, rp| memo.merge(rp) }
47
+ logger.debug("Merged #{rps.length} reporting periods, delivering")
48
+ deliver_period(merged)
49
+ true
50
+ rescue => e
51
+ logger.debug("Error merging reporting periods #{e.message}")
52
+ logger.debug("Error merging reporting periods #{e.backtrace}")
53
+ false
54
+ end
55
+
56
+ end
57
+
58
+ if !did_write
59
+ logger.debug("Failed to obtain claim for #{period_to_report.to_s}")
60
+ end
61
+ end
62
+
63
+ def deliver_period(reporting_period)
64
+ metrics = reporting_period.metrics_payload
65
+ slow_transactions = reporting_period.slow_transactions_payload
66
+ jobs = reporting_period.jobs
67
+ slow_jobs = reporting_period.slow_jobs_payload
68
+ histograms = reporting_period.histograms
69
+ db_query_metrics = reporting_period.db_query_metrics_payload
70
+
71
+ metadata = {
72
+ :app_root => context.environment.root.to_s,
73
+ :unique_id => ScoutApm::Utils::UniqueId.simple,
74
+ :agent_version => ScoutApm::VERSION,
75
+ :agent_time => reporting_period.timestamp.to_s,
76
+ :agent_pid => Process.pid,
77
+ :platform => "ruby",
78
+ }
79
+
80
+ log_deliver(metrics, slow_transactions, metadata, slow_jobs, histograms)
81
+
82
+ payload = ScoutApm::Serializers::PayloadSerializer.serialize(metadata, metrics, slow_transactions, jobs, slow_jobs, histograms, db_query_metrics)
83
+ logger.debug("Sending payload w/ Headers: #{headers.inspect}")
84
+
85
+ reporter.report(payload, headers)
86
+ rescue => e
87
+ logger.warn "Error on checkin"
88
+ logger.info e.message
89
+ logger.debug e.backtrace
90
+ end
91
+
92
+ def log_deliver(metrics, slow_transactions, metadata, jobs_traces, histograms)
93
+ total_request_count = metrics.
94
+ select { |meta,stats| meta.metric_name =~ /\AController/ }.
95
+ inject(0) {|sum, (_, stat)| sum + stat.call_count }
96
+
97
+ memory = metrics.
98
+ find {|meta,stats| meta.metric_name =~ /\AMemory/ }
99
+ process_log_str = if memory
100
+ "Recorded from #{memory.last.call_count} processes"
101
+ else
102
+ "Recorded across (unknown) processes"
103
+ end
104
+
105
+ time_clause = "[#{Time.parse(metadata[:agent_time]).strftime("%H:%M")}]"
106
+ metrics_clause = "#{metrics.length} Metrics for #{total_request_count} requests"
107
+ slow_trans_clause = "#{slow_transactions.length} Slow Transaction Traces"
108
+ job_clause = "#{jobs_traces.length} Job Traces"
109
+ histogram_clause = "#{histograms.length} Histograms"
110
+
111
+ logger.info "#{time_clause} Delivering #{metrics_clause} and #{slow_trans_clause} and #{job_clause}, #{process_log_str}."
112
+ logger.debug("\n\nMetrics: #{metrics.pretty_inspect}\nSlowTrans: #{slow_transactions.pretty_inspect}\nMetadata: #{metadata.inspect.pretty_inspect}\n\n")
113
+ end
114
+
115
+ # TODO: Move this into PayloadSerializer?
116
+ # XXX: Remove non-json report format entirely
117
+ def headers
118
+ if ScoutApm::Agent.instance.context.config.value("report_format") == 'json'
119
+ headers = {'Content-Type' => 'application/json'}
120
+ else
121
+ headers = {}
122
+ end
123
+ end
124
+
125
+ # Before reporting, lookup metric_id for each MetricMeta. This speeds up
126
+ # reporting on the server-side.
127
+ def add_metric_ids(metrics)
128
+ metrics.each do |meta,stats|
129
+ if metric_id = metric_lookup[meta]
130
+ meta.metric_id = metric_id
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -19,13 +19,11 @@ module ScoutApm
19
19
  end
20
20
 
21
21
  # Create a new TrackedRequest object for this thread
22
+ # XXX: Figure out who is in charge of creating a `FakeStore` - previously was here
22
23
  def self.create
23
- store = if ScoutApm::Agent.instance.apm_enabled?
24
- ScoutApm::Agent.instance.store
25
- else
26
- ScoutApm::FakeStore.new
27
- end
28
- Thread.current[:scout_request] = TrackedRequest.new(store)
24
+ agent_context = ScoutApm::Agent.instance.context
25
+ store = agent_context.store
26
+ Thread.current[:scout_request] = TrackedRequest.new(agent_context, store)
29
27
  end
30
28
  end
31
29
  end
@@ -3,7 +3,7 @@ module ScoutApm
3
3
  module Serializers
4
4
  class PayloadSerializer
5
5
  def self.serialize(metadata, metrics, slow_transactions, jobs, slow_jobs, histograms, db_query_metrics)
6
- if ScoutApm::Agent.instance.config.value("report_format") == 'json'
6
+ if ScoutApm::Agent.instance.context.config.value("report_format") == 'json'
7
7
  ScoutApm::Serializers::PayloadSerializerToJson.serialize(metadata, metrics, slow_transactions, jobs, slow_jobs, histograms, db_query_metrics)
8
8
  else
9
9
  metadata = metadata.dup
@@ -24,8 +24,12 @@ module ScoutApm
24
24
  # has been running.
25
25
  attr_reader :last_seen
26
26
 
27
+ # The AgentContext we're running in
28
+ attr_reader :context
29
+
30
+ def initialize(context)
31
+ @context = context
27
32
 
28
- def initialize
29
33
  zero_time = Time.now
30
34
  @last_seen = Hash.new { |h, k| h[k] = zero_time }
31
35
  end
@@ -54,7 +58,7 @@ module ScoutApm
54
58
  age = Time.now - last_seen[unique_name]
55
59
 
56
60
  # What approximate percentile was this request?
57
- percentile = ScoutApm::Agent.instance.request_histograms.approximate_quantile_of_value(unique_name, total_time)
61
+ percentile = context.request_histograms.approximate_quantile_of_value(unique_name, total_time)
58
62
 
59
63
  return speed_points(total_time) + percentile_points(percentile) + age_points(age)
60
64
  end
@@ -23,7 +23,7 @@ module ScoutApm
23
23
  attr_reader :git_sha
24
24
  attr_reader :truncated_metrics
25
25
 
26
- def initialize(queue_name, job_name, time, total_time, exclusive_time, context, metrics, allocation_metrics, mem_delta, allocations, score, truncated_metrics)
26
+ def initialize(agent_context, queue_name, job_name, time, total_time, exclusive_time, context, metrics, allocation_metrics, mem_delta, allocations, score, truncated_metrics)
27
27
  @queue_name = queue_name
28
28
  @job_name = job_name
29
29
  @time = time
@@ -34,13 +34,13 @@ module ScoutApm
34
34
  @allocation_metrics = allocation_metrics
35
35
  @mem_delta = mem_delta
36
36
  @allocations = allocations
37
- @seconds_since_startup = (Time.now - ScoutApm::Agent.instance.process_start_time)
38
- @hostname = ScoutApm::Environment.instance.hostname
39
- @git_sha = ScoutApm::Environment.instance.git_revision.sha
37
+ @seconds_since_startup = (Time.now - agent_context.process_start_time)
38
+ @hostname = agent_context.environment.hostname
39
+ @git_sha = agent_context.environment.git_revision.sha
40
40
  @score = score
41
41
  @truncated_metrics = truncated_metrics
42
42
 
43
- ScoutApm::Agent.instance.logger.debug { "Slow Job [#{metric_name}] - Call Time: #{total_call_time} Mem Delta: #{mem_delta}"}
43
+ agent_context.logger.debug { "Slow Job [#{metric_name}] - Call Time: #{total_call_time} Mem Delta: #{mem_delta}"}
44
44
  end
45
45
 
46
46
  def metric_name
@@ -24,8 +24,12 @@ module ScoutApm
24
24
  # has been running.
25
25
  attr_reader :last_seen
26
26
 
27
+ # The AgentContext we're running in
28
+ attr_reader :context
29
+
30
+ def initialize(context)
31
+ @context = context
27
32
 
28
- def initialize
29
33
  zero_time = Time.now
30
34
  @last_seen = Hash.new { |h, k| h[k] = zero_time }
31
35
  end
@@ -54,7 +58,7 @@ module ScoutApm
54
58
  age = Time.now - last_seen[unique_name]
55
59
 
56
60
  # What approximate percentile was this request?
57
- percentile = ScoutApm::Agent.instance.request_histograms.approximate_quantile_of_value(unique_name, total_time)
61
+ percentile = context.request_histograms.approximate_quantile_of_value(unique_name, total_time)
58
62
 
59
63
  return speed_points(total_time) + percentile_points(percentile) + age_points(age)
60
64
  end
@@ -19,7 +19,7 @@ module ScoutApm
19
19
 
20
20
  attr_reader :truncated_metrics # True/False that says if we had to truncate the metrics of this trace
21
21
 
22
- def initialize(uri, metric_name, total_call_time, metrics, allocation_metrics, context, time, raw_stackprof, mem_delta, allocations, score, truncated_metrics)
22
+ def initialize(agent_context, uri, metric_name, total_call_time, metrics, allocation_metrics, context, time, raw_stackprof, mem_delta, allocations, score, truncated_metrics)
23
23
  @uri = uri
24
24
  @metric_name = metric_name
25
25
  @total_call_time = total_call_time
@@ -30,13 +30,13 @@ module ScoutApm
30
30
  @prof = []
31
31
  @mem_delta = mem_delta
32
32
  @allocations = allocations
33
- @seconds_since_startup = (Time.now - ScoutApm::Agent.instance.process_start_time)
34
- @hostname = ScoutApm::Environment.instance.hostname
33
+ @seconds_since_startup = (Time.now - agent_context.process_start_time)
34
+ @hostname = agent_context.environment.hostname
35
35
  @score = score
36
- @git_sha = ScoutApm::Environment.instance.git_revision.sha
36
+ @git_sha = agent_context.environment.git_revision.sha
37
37
  @truncated_metrics = truncated_metrics
38
38
 
39
- ScoutApm::Agent.instance.logger.debug { "Slow Request [#{uri}] - Call Time: #{total_call_time} Mem Delta: #{mem_delta} Score: #{score}"}
39
+ agent_context.logger.debug { "Slow Request [#{uri}] - Call Time: #{total_call_time} Mem Delta: #{mem_delta} Score: #{score}"}
40
40
  end
41
41
 
42
42
  # Used to remove metrics when the payload will be too large.
@@ -3,14 +3,15 @@
3
3
  # the layaway file for cross-process aggregation.
4
4
  module ScoutApm
5
5
  class Store
6
- def initialize
6
+ def initialize(context)
7
+ @context = context
7
8
  @mutex = Mutex.new
8
- @reporting_periods = Hash.new { |h,k| h[k] = StoreReportingPeriod.new(k) }
9
+ @reporting_periods = Hash.new { |h,k| h[k] = StoreReportingPeriod.new(k, @context) }
9
10
  @samplers = []
10
11
  end
11
12
 
12
13
  def current_timestamp
13
- StoreReportingPeriodTimestamp.new
14
+ StoreReportingPeriodTimestamp.new(Time.now)
14
15
  end
15
16
 
16
17
  def current_period
@@ -84,11 +85,11 @@ module ScoutApm
84
85
  # current-minute metrics. Useful when we are shutting down the agent
85
86
  # during a restart.
86
87
  def write_to_layaway(layaway, force=false)
87
- ScoutApm::Agent.instance.logger.debug("Writing to layaway#{" (Forced)" if force}")
88
+ logger.debug("Writing to layaway#{" (Forced)" if force}")
88
89
 
89
- @reporting_periods.select { |time, rp| force || (time.timestamp < current_timestamp.timestamp) }.
90
- each { |time, rp| collect_samplers(rp) }.
91
- each { |time, rp| write_reporting_period(layaway, time, rp) }
90
+ @reporting_periods.select { |time, rp| force || (time.timestamp < current_timestamp.timestamp) }.
91
+ each { |time, rp| collect_samplers(rp) }.
92
+ each { |time, rp| write_reporting_period(layaway, time, rp) }
92
93
  end
93
94
 
94
95
  def write_reporting_period(layaway, time, rp)
@@ -96,18 +97,18 @@ module ScoutApm
96
97
  layaway.write_reporting_period(rp)
97
98
  }
98
99
  rescue => e
99
- ScoutApm::Agent.instance.logger.warn("Failed writing data to layaway file: #{e.message} / #{e.backtrace}")
100
+ logger.warn("Failed writing data to layaway file: #{e.message} / #{e.backtrace}")
100
101
  ensure
101
- ScoutApm::Agent.instance.logger.debug("Before delete, reporting periods length: #{@reporting_periods.size}")
102
+ logger.debug("Before delete, reporting periods length: #{@reporting_periods.size}")
102
103
  deleted_items = @reporting_periods.delete(time)
103
- ScoutApm::Agent.instance.logger.debug("After delete, reporting periods length: #{@reporting_periods.size}. Did delete #{deleted_items}")
104
+ logger.debug("After delete, reporting periods length: #{@reporting_periods.size}. Did delete #{deleted_items}")
104
105
  end
105
106
  private :write_reporting_period
106
107
 
107
108
  ######################################
108
109
  # Sampler support
109
- def add_sampler(sampler)
110
- @samplers << sampler
110
+ def add_sampler(sampler_klass)
111
+ @samplers << sampler_klass.new(@context)
111
112
  end
112
113
 
113
114
  def collect_samplers(rp)
@@ -115,12 +116,17 @@ module ScoutApm
115
116
  begin
116
117
  sampler.metrics(rp.timestamp, self)
117
118
  rescue => e
118
- ScoutApm::Agent.instance.logger.info "Error reading #{sampler.human_name} for period: #{rp}"
119
- ScoutApm::Agent.instance.logger.debug "#{e.message}\n\t#{e.backtrace.join("\n\t")}"
119
+ logger.info "Error reading #{sampler.human_name} for period: #{rp}"
120
+ logger.debug "#{e.message}\n\t#{e.backtrace.join("\n\t")}"
120
121
  end
121
122
  end
122
123
  end
123
124
  private :collect_samplers
125
+
126
+ def logger
127
+ @context.logger
128
+ end
129
+ private :logger
124
130
  end
125
131
 
126
132
  # A timestamp, normalized to the beginning of a minute. Used as a hash key to
@@ -191,7 +197,7 @@ module ScoutApm
191
197
 
192
198
  attr_reader :db_query_metric_set
193
199
 
194
- def initialize(timestamp)
200
+ def initialize(timestamp, context)
195
201
  @timestamp = timestamp
196
202
 
197
203
  @request_traces = ScoredItemSet.new
@@ -200,7 +206,7 @@ module ScoutApm
200
206
  @histograms = []
201
207
 
202
208
  @metric_set = MetricSet.new
203
- @db_query_metric_set = DbQueryMetricSet.new
209
+ @db_query_metric_set = DbQueryMetricSet.new(context)
204
210
 
205
211
  @jobs = Hash.new
206
212
  end