class AppsignalReport::BaseReport
Report base class, defines the general flow and helper methods used by the specific report classes.
Attributes
api_token[R]
app_id[R]
app_name[R]
report[R]
Public Class Methods
new(api_token:, app_id:, app_name: nil)
click to toggle source
@param [String] api_token
API token, find it here:
<https://appsignal.com/users/edit>
@param [String] app_id
Application ID, visible in the URL when your
application is opened on Appsignal.com
@param [String] app_name
Application Name, used for the report title
# File lib/appsignal_report/base_report.rb, line 14 def initialize(api_token:, app_id:, app_name: nil) @api_token = api_token @app_id = app_id @app_name = app_name @report = {} end
Public Instance Methods
generate()
click to toggle source
To be defined by subclass, should set the instance var @report. @return [Hash]
# File lib/appsignal_report/base_report.rb, line 23 def generate raise NotImplementedError end
title()
click to toggle source
@return [String]
# File lib/appsignal_report/base_report.rb, line 28 def title [ 'AppSignal', self.class.name.split('::').last.split(/(?=[A-Z])/).join(' '), !app_name.nil? ? "(#{app_name})" : nil ].compact.join(' ') end
Private Instance Methods
abs_diff(key)
click to toggle source
# File lib/appsignal_report/base_report.rb, line 101 def abs_diff(key) report[:after][key] - report[:before][key] end
balance_samples(samples)
click to toggle source
# File lib/appsignal_report/base_report.rb, line 121 def balance_samples(samples) sample_size = [samples[:before].size, samples[:after].size].min samples[:before] = samples[:before].last(sample_size) samples[:after] = samples[:after].first(sample_size) samples end
base_uri()
click to toggle source
@return [String]
# File lib/appsignal_report/base_report.rb, line 137 def base_uri "https://appsignal.com/api/#{app_id}" end
gather_samples(samples)
click to toggle source
# File lib/appsignal_report/base_report.rb, line 109 def gather_samples(samples) split_timestamp = report_split_time.to_time.to_i samples.each_with_object(before: [], after: []) do |row, hash| next if timestamp_in_grace_period?(row[:timestamp]) if row[:timestamp] < split_timestamp hash[:before] << row else hash[:after] << row end end end
generate_diff()
click to toggle source
# File lib/appsignal_report/base_report.rb, line 90 def generate_diff { error_rate: abs_diff(:error_rate), error_rate_pct: pct_diff(:error_rate), response_time: abs_diff(:response_time), response_time_pct: pct_diff(:response_time), throughput: abs_diff(:throughput), throughput_pct: pct_diff(:throughput), } end
generate_messages()
click to toggle source
# File lib/appsignal_report/base_report.rb, line 59 def generate_messages { info: info_message, error_rate: metric_message(:error_rate, '%'), response_time: metric_message(:response_time, 'ms'), throughput: metric_message(:throughput, " req/#{@report[:resolution][0]}"), } end
get_average(data, field)
click to toggle source
@param [Array] data @param [Symbol] field @return [Float]
# File lib/appsignal_report/base_report.rb, line 85 def get_average(data, field) values = data.map { |row| row[field] } values.inject(0, :+).fdiv(values.size) end
info_message()
click to toggle source
# File lib/appsignal_report/base_report.rb, line 69 def info_message; end
metric_message(field, unit = '')
click to toggle source
# File lib/appsignal_report/base_report.rb, line 71 def metric_message(field, unit = '') <<-txt.split.join(' ') The #{field.to_s.sub('_', ' ')} #{report[:diff][field].positive? ? 'increased' : 'decreased'} by #{report[:diff][field].abs.round(2)}#{unit} (from #{report[:before][field].round(2)}#{unit} to #{report[:after][field].round(2)}#{unit}, that is a change of #{(report[:diff][:"#{field}_pct"] * 100).round(2)}%). txt end
metrics_uri()
click to toggle source
@return [URI]
# File lib/appsignal_report/base_report.rb, line 142 def metrics_uri raise NotImplementedError end
pct_diff(key)
click to toggle source
# File lib/appsignal_report/base_report.rb, line 105 def pct_diff(key) abs_diff(key).fdiv(report[:before][key]) end
perform_api_request(uri)
click to toggle source
@return [Hash]
# File lib/appsignal_report/base_report.rb, line 147 def perform_api_request(uri) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true response = http.request( Net::HTTP::Get.new(uri, 'Content-Type' => 'application/json') ) if response.is_a? Net::HTTPSuccess JSON.parse(response.body, symbolize_names: true) else raise StandardError, "[API ERROR] #{response.code} - #{response.message}" end end
process_metrics()
click to toggle source
# File lib/appsignal_report/base_report.rb, line 38 def process_metrics api_response = perform_api_request(metrics_uri) @report[:resolution] = api_response[:resolution] data = balance_samples(gather_samples(api_response[:data])) %i(before after).each do |key| @report[key] = { data_points: data[key].size, error_rate: get_average(data[key], :ex_rate), response_time: get_average(data[key], :mean), throughput: get_average(data[key], :count), } end @report.merge!( data_samples_from: Time.at(data[:before].first[:timestamp]).utc, data_samples_to: Time.at(data[:after].last[:timestamp]).utc, diff: generate_diff, ) @report[:messages] = generate_messages report end
report_split_time()
click to toggle source
# File lib/appsignal_report/base_report.rb, line 128 def report_split_time raise NotImplementedError end
timestamp_in_grace_period?(_)
click to toggle source
# File lib/appsignal_report/base_report.rb, line 132 def timestamp_in_grace_period?(_) false end