Class: ScoutApm::Reporting
- Inherits:
-
Object
- Object
- ScoutApm::Reporting
- Defined in:
- lib/scout_apm/reporting.rb
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Instance Method Summary collapse
-
#add_metric_ids(metrics) ⇒ Object
Before reporting, lookup metric_id for each MetricMeta.
- #deliver_period(reporting_period) ⇒ Object
-
#headers ⇒ Object
TODO: Move this into PayloadSerializer? XXX: Remove non-json report format entirely.
-
#initialize(context) ⇒ Reporting
constructor
A new instance of Reporting.
- #log_deliver(metrics, slow_transactions, metadata, jobs_traces, histograms) ⇒ Object
- #logger ⇒ Object
-
#process_metrics ⇒ Object
The data moves through a treadmill of reporting, coordinating several Rails processes by using an external file.
-
#report_to_server ⇒ Object
In a running app, one process will get the period ready for delivery, the others will see 0.
- #reporter ⇒ Object
Constructor Details
#initialize(context) ⇒ Reporting
Returns a new instance of Reporting.
6 7 8 |
# File 'lib/scout_apm/reporting.rb', line 6 def initialize(context) @context = context end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
4 5 6 |
# File 'lib/scout_apm/reporting.rb', line 4 def context @context end |
Instance Method Details
#add_metric_ids(metrics) ⇒ Object
Before reporting, lookup metric_id for each MetricMeta. This speeds up reporting on the server-side.
130 131 132 133 134 135 136 |
# File 'lib/scout_apm/reporting.rb', line 130 def add_metric_ids(metrics) metrics.each do |,stats| if metric_id = metric_lookup[] .metric_id = metric_id end end end |
#deliver_period(reporting_period) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/scout_apm/reporting.rb', line 66 def deliver_period(reporting_period) metrics = reporting_period.metrics_payload slow_transactions = reporting_period.slow_transactions_payload jobs = reporting_period.jobs slow_jobs = reporting_period.slow_jobs_payload histograms = reporting_period.histograms db_query_metrics = reporting_period.db_query_metrics_payload = { :app_root => context.environment.root.to_s, :unique_id => ScoutApm::Utils::UniqueId.simple, :agent_version => ScoutApm::VERSION, :agent_time => reporting_period..to_s, :agent_pid => Process.pid, :platform => "ruby", } log_deliver(metrics, slow_transactions, , slow_jobs, histograms) payload = ScoutApm::Serializers::PayloadSerializer.serialize(, metrics, slow_transactions, jobs, slow_jobs, histograms, db_query_metrics) logger.debug("Sending payload w/ Headers: #{headers.inspect}") reporter.report(payload, headers) rescue => e logger.warn "Error on checkin" logger.info e. logger.debug e.backtrace end |
#headers ⇒ Object
TODO: Move this into PayloadSerializer? XXX: Remove non-json report format entirely
120 121 122 123 124 125 126 |
# File 'lib/scout_apm/reporting.rb', line 120 def headers if ScoutApm::Agent.instance.context.config.value("report_format") == 'json' headers = {'Content-Type' => 'application/json'} else headers = {} end end |
#log_deliver(metrics, slow_transactions, metadata, jobs_traces, histograms) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/scout_apm/reporting.rb', line 95 def log_deliver(metrics, slow_transactions, , jobs_traces, histograms) total_request_count = metrics. select { |,stats| .metric_name =~ /\AController/ }. inject(0) {|sum, (_, stat)| sum + stat.call_count } memory = metrics. find {|,stats| .metric_name =~ /\AMemory/ } process_log_str = if memory "Recorded from #{memory.last.call_count} processes" else "Recorded across (unknown) processes" end time_clause = "[#{Time.parse([:agent_time]).strftime("%H:%M")}]" metrics_clause = "#{metrics.length} Metrics for #{total_request_count} requests" slow_trans_clause = "#{slow_transactions.length} Slow Transaction Traces" job_clause = "#{jobs_traces.length} Job Traces" histogram_clause = "#{histograms.length} Histograms" logger.info "#{time_clause} Delivering #{metrics_clause} and #{slow_trans_clause} and #{job_clause}, #{process_log_str}." logger.debug("\n\nMetrics: #{metrics.pretty_inspect}\nSlowTrans: #{slow_transactions.pretty_inspect}\nMetadata: #{.inspect.pretty_inspect}\n\n") end |
#logger ⇒ Object
10 11 12 |
# File 'lib/scout_apm/reporting.rb', line 10 def logger context.logger end |
#process_metrics ⇒ Object
The data moves through a treadmill of reporting, coordinating several Rails processes by using an external file.
-
During the minute it is being recorded by the instruments, it gets recorded into the ram of each process (in the Store class).
-
The minute after, each process writes its own metrics to a shared LayawayFile
-
The minute after that, the first process to wake up pushes the combined data to the server, and wipes it. Next processes don’t have anything to do.
At any given point, there is data in each of those steps, moving its way through the process
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/scout_apm/reporting.rb', line 26 def process_metrics # Do any per-minute work necessary for the store context.store.tick! # Write the previous minute's data to the shared-across-process layaway file. context.store.write_to_layaway(context.layaway) # Attempt to send 2 minutes ago's data up to the server. This # only acctually occurs if this process is the first to wake up this # minute. report_to_server end |
#report_to_server ⇒ Object
In a running app, one process will get the period ready for delivery, the others will see 0.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/scout_apm/reporting.rb', line 40 def report_to_server period_to_report = ScoutApm::StoreReportingPeriodTimestamp.minutes_ago(2) logger.debug("Attempting to claim #{period_to_report.to_s}") did_write = context.layaway.with_claim(period_to_report) do |rps| logger.debug("Succeeded claiming #{period_to_report.to_s}") begin merged = rps.inject { |memo, rp| memo.merge(rp) } logger.debug("Merged #{rps.length} reporting periods, delivering") deliver_period(merged) true rescue => e logger.debug("Error merging reporting periods #{e.}") logger.debug("Error merging reporting periods #{e.backtrace}") false end end if !did_write logger.debug("Failed to obtain claim for #{period_to_report.to_s}") end end |