scout_apm 2.3.5 → 2.4.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +0 -23
- data/lib/scout_apm.rb +21 -10
- data/lib/scout_apm/agent.rb +98 -336
- data/lib/scout_apm/agent/exit_handler.rb +64 -0
- data/lib/scout_apm/agent/preconditions.rb +69 -0
- data/lib/scout_apm/agent_context.rb +226 -0
- data/lib/scout_apm/app_server_load.rb +20 -18
- data/lib/scout_apm/background_job_integrations/resque.rb +7 -8
- data/lib/scout_apm/background_job_integrations/sidekiq.rb +2 -8
- data/lib/scout_apm/background_recorder.rb +8 -3
- data/lib/scout_apm/background_worker.rb +14 -7
- data/lib/scout_apm/config.rb +35 -29
- data/lib/scout_apm/context.rb +11 -4
- data/lib/scout_apm/db_query_metric_set.rb +17 -5
- data/lib/scout_apm/debug.rb +1 -1
- data/lib/scout_apm/environment.rb +10 -14
- data/lib/scout_apm/framework_integrations/sinatra.rb +1 -1
- data/lib/scout_apm/git_revision.rb +13 -8
- data/lib/scout_apm/histogram.rb +1 -1
- data/lib/scout_apm/instant/middleware.rb +7 -7
- data/lib/scout_apm/instant_reporting.rb +7 -7
- data/lib/scout_apm/instrument_manager.rb +87 -0
- data/lib/scout_apm/instruments/action_controller_rails_2.rb +12 -7
- data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +16 -11
- data/lib/scout_apm/instruments/action_view.rb +11 -7
- data/lib/scout_apm/instruments/active_record.rb +28 -51
- data/lib/scout_apm/instruments/elasticsearch.rb +10 -6
- data/lib/scout_apm/instruments/grape.rb +12 -8
- data/lib/scout_apm/instruments/http_client.rb +11 -10
- data/lib/scout_apm/instruments/influxdb.rb +10 -6
- data/lib/scout_apm/instruments/middleware_detailed.rb +11 -5
- data/lib/scout_apm/instruments/middleware_summary.rb +11 -5
- data/lib/scout_apm/instruments/mongoid.rb +10 -5
- data/lib/scout_apm/instruments/moped.rb +11 -6
- data/lib/scout_apm/instruments/net_http.rb +11 -9
- data/lib/scout_apm/instruments/percentile_sampler.rb +8 -6
- data/lib/scout_apm/instruments/process/process_cpu.rb +8 -4
- data/lib/scout_apm/instruments/process/process_memory.rb +15 -10
- data/lib/scout_apm/instruments/rails_router.rb +12 -6
- data/lib/scout_apm/instruments/redis.rb +10 -6
- data/lib/scout_apm/instruments/samplers.rb +11 -0
- data/lib/scout_apm/instruments/sinatra.rb +5 -4
- data/lib/scout_apm/layaway.rb +26 -39
- data/lib/scout_apm/layaway_file.rb +8 -3
- data/lib/scout_apm/layer.rb +1 -1
- data/lib/scout_apm/layer_converters/converter_base.rb +4 -2
- data/lib/scout_apm/layer_converters/database_converter.rb +1 -1
- data/lib/scout_apm/layer_converters/histograms.rb +2 -2
- data/lib/scout_apm/layer_converters/slow_job_converter.rb +4 -3
- data/lib/scout_apm/layer_converters/slow_request_converter.rb +5 -4
- data/lib/scout_apm/logger.rb +143 -0
- data/lib/scout_apm/middleware.rb +7 -9
- data/lib/scout_apm/periodic_work.rb +28 -0
- data/lib/scout_apm/remote/server.rb +0 -2
- data/lib/scout_apm/reporter.rb +14 -8
- data/lib/scout_apm/reporting.rb +135 -0
- data/lib/scout_apm/request_manager.rb +4 -7
- data/lib/scout_apm/serializers/payload_serializer.rb +1 -1
- data/lib/scout_apm/slow_job_policy.rb +6 -2
- data/lib/scout_apm/slow_job_record.rb +5 -5
- data/lib/scout_apm/slow_request_policy.rb +6 -2
- data/lib/scout_apm/slow_transaction.rb +5 -5
- data/lib/scout_apm/store.rb +22 -16
- data/lib/scout_apm/synchronous_recorder.rb +7 -3
- data/lib/scout_apm/tasks/doctor.rb +75 -0
- data/lib/scout_apm/tasks/support.rb +22 -0
- data/lib/scout_apm/tracer.rb +5 -5
- data/lib/scout_apm/tracked_request.rb +23 -35
- data/lib/scout_apm/utils/backtrace_parser.rb +1 -1
- data/lib/scout_apm/utils/installed_gems.rb +7 -3
- data/lib/scout_apm/utils/klass_helper.rb +8 -2
- data/lib/scout_apm/utils/scm.rb +1 -1
- data/lib/scout_apm/utils/sql_sanitizer.rb +4 -6
- data/lib/scout_apm/version.rb +1 -1
- data/lib/tasks/doctor.rake +11 -0
- data/test/test_helper.rb +15 -2
- data/test/unit/agent_test.rb +1 -54
- data/test/unit/config_test.rb +9 -5
- data/test/unit/context_test.rb +4 -4
- data/test/unit/db_query_metric_set_test.rb +11 -4
- data/test/unit/fake_store_test.rb +1 -1
- data/test/unit/git_revision_test.rb +3 -3
- data/test/unit/instruments/net_http_test.rb +2 -1
- data/test/unit/instruments/percentile_sampler_test.rb +5 -9
- data/test/unit/layaway_test.rb +10 -5
- data/test/unit/layer_converters/metric_converter_test.rb +2 -2
- data/test/unit/slow_request_policy_test.rb +7 -3
- data/test/unit/sql_sanitizer_test.rb +0 -6
- data/test/unit/store_test.rb +11 -8
- metadata +15 -7
- data/lib/scout_apm/agent/logging.rb +0 -74
- data/lib/scout_apm/agent/reporting.rb +0 -129
- data/lib/scout_apm/utils/null_logger.rb +0 -13
data/lib/scout_apm/middleware.rb
CHANGED
@@ -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
|
-
|
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
|
25
|
-
ScoutApm::Agent.instance.
|
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
|
-
|
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
|
data/lib/scout_apm/reporter.rb
CHANGED
@@ -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(
|
14
|
-
@
|
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
|
-
|
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(
|
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" =>
|
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,14 +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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
ScoutApm::FakeStore.new
|
27
|
-
end
|
28
|
-
|
29
|
-
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)
|
30
27
|
end
|
31
28
|
end
|
32
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 =
|
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 -
|
38
|
-
@hostname =
|
39
|
-
@git_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
|
-
|
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 =
|
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 -
|
34
|
-
@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 =
|
36
|
+
@git_sha = agent_context.environment.git_revision.sha
|
37
37
|
@truncated_metrics = truncated_metrics
|
38
38
|
|
39
|
-
|
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.
|
data/lib/scout_apm/store.rb
CHANGED
@@ -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
|
-
|
88
|
+
logger.debug("Writing to layaway#{" (Forced)" if force}")
|
88
89
|
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
100
|
+
logger.warn("Failed writing data to layaway file: #{e.message} / #{e.backtrace}")
|
100
101
|
ensure
|
101
|
-
|
102
|
+
logger.debug("Before delete, reporting periods length: #{@reporting_periods.size}")
|
102
103
|
deleted_items = @reporting_periods.delete(time)
|
103
|
-
|
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(
|
110
|
-
@samplers <<
|
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
|
-
|
119
|
-
|
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
|