scout_apm 3.0.0.pre13 → 3.0.0.pre14

Sign up to get free protection for your applications and to get access to all the features.
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