Class: ScoutApm::ErrorService::ErrorRecord
- Inherits:
-
Object
- Object
- ScoutApm::ErrorService::ErrorRecord
- Defined in:
- lib/scout_apm/error_service/error_record.rb
Overview
Converts the raw error data captured into the captured data, and holds it until it’s ready to be reported.
Defined Under Namespace
Classes: LengthLimit
Constant Summary collapse
- KEYS_TO_KEEP =
Capture params from env
[ "REQUEST_METHOD", "HTTP_USER_AGENT", "HTTP_REFERER", "HTTP_ACCEPT_ENCODING", "HTTP_ORIGIN", ]
Instance Attribute Summary collapse
-
#agent_time ⇒ Object
readonly
Returns the value of attribute agent_time.
-
#context ⇒ Object
readonly
Returns the value of attribute context.
-
#environment ⇒ Object
readonly
Returns the value of attribute environment.
-
#exception_class ⇒ Object
readonly
Returns the value of attribute exception_class.
-
#git_sha ⇒ Object
readonly
Returns the value of attribute git_sha.
-
#message ⇒ Object
readonly
Returns the value of attribute message.
-
#request_components ⇒ Object
readonly
Returns the value of attribute request_components.
-
#request_params ⇒ Object
readonly
Returns the value of attribute request_params.
-
#request_uri ⇒ Object
readonly
Returns the value of attribute request_uri.
-
#trace ⇒ Object
readonly
Returns the value of attribute trace.
Instance Method Summary collapse
-
#clean_backtrace(backtrace) ⇒ Object
TODO: When was backtrace_cleaner introduced?.
-
#clean_params(params) ⇒ Object
TODO: This name is too vague.
-
#components(env) ⇒ Object
TODO: This is rails specific.
- #env_captured(env) ⇒ Object
-
#filter_key?(key) ⇒ Boolean
Check, if a key should be filtered.
-
#filter_params(params) ⇒ Object
Replaces parameter values with a string / set in config file.
-
#filtered_params_config ⇒ Object
Accessor for the filtered params config value.
-
#initialize(agent_context, exception, env, context = nil) ⇒ ErrorRecord
constructor
A new instance of ErrorRecord.
-
#normalize_data(hash) ⇒ Object
TODO: Rename and make this clearer.
- #params_to_filter ⇒ Object
-
#rack_request_url(env) ⇒ Object
TODO: Can I use the same thing we use in traces?.
- #rack_scheme(env) ⇒ Object
- #rails_filtered_params ⇒ Object
Constructor Details
#initialize(agent_context, exception, env, context = nil) ⇒ ErrorRecord
Returns a new instance of ErrorRecord.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/scout_apm/error_service/error_record.rb', line 17 def initialize(agent_context, exception, env, context=nil) @agent_context = agent_context @context = if context context.to_flat_hash else {} end # Add the transaction_id, as it won't be added to the context normally until the request has been recorded. @context[:transaction_id] ||= RequestManager.lookup.transaction_id @exception_class = LengthLimit.new(exception.class.name).to_s @message = LengthLimit.new(exception., 100).to_s @request_uri = LengthLimit.new(rack_request_url(env), 200).to_s @request_params = clean_params(env["action_dispatch.request.parameters"]) @environment = clean_params(env_captured(env)) @trace = clean_backtrace(exception.backtrace) @request_components = components(env) @agent_time = Time.now.iso8601 @git_sha = @agent_context.environment.git_revision.sha.to_s end |
Instance Attribute Details
#agent_time ⇒ Object (readonly)
Returns the value of attribute agent_time.
14 15 16 |
# File 'lib/scout_apm/error_service/error_record.rb', line 14 def agent_time @agent_time end |
#context ⇒ Object (readonly)
Returns the value of attribute context.
13 14 15 |
# File 'lib/scout_apm/error_service/error_record.rb', line 13 def context @context end |
#environment ⇒ Object (readonly)
Returns the value of attribute environment.
10 11 12 |
# File 'lib/scout_apm/error_service/error_record.rb', line 10 def environment @environment end |
#exception_class ⇒ Object (readonly)
Returns the value of attribute exception_class.
6 7 8 |
# File 'lib/scout_apm/error_service/error_record.rb', line 6 def exception_class @exception_class end |
#git_sha ⇒ Object (readonly)
Returns the value of attribute git_sha.
15 16 17 |
# File 'lib/scout_apm/error_service/error_record.rb', line 15 def git_sha @git_sha end |
#message ⇒ Object (readonly)
Returns the value of attribute message.
7 8 9 |
# File 'lib/scout_apm/error_service/error_record.rb', line 7 def @message end |
#request_components ⇒ Object (readonly)
Returns the value of attribute request_components.
12 13 14 |
# File 'lib/scout_apm/error_service/error_record.rb', line 12 def request_components @request_components end |
#request_params ⇒ Object (readonly)
Returns the value of attribute request_params.
9 10 11 |
# File 'lib/scout_apm/error_service/error_record.rb', line 9 def request_params @request_params end |
#request_uri ⇒ Object (readonly)
Returns the value of attribute request_uri.
8 9 10 |
# File 'lib/scout_apm/error_service/error_record.rb', line 8 def request_uri @request_uri end |
#trace ⇒ Object (readonly)
Returns the value of attribute trace.
11 12 13 |
# File 'lib/scout_apm/error_service/error_record.rb', line 11 def trace @trace end |
Instance Method Details
#clean_backtrace(backtrace) ⇒ Object
TODO: When was backtrace_cleaner introduced?
88 89 90 91 92 93 94 |
# File 'lib/scout_apm/error_service/error_record.rb', line 88 def clean_backtrace(backtrace) if defined?(Rails) && Rails.respond_to?(:backtrace_cleaner) Rails.backtrace_cleaner.send(:filter, backtrace) else backtrace end end |
#clean_params(params) ⇒ Object
TODO: This name is too vague
80 81 82 83 84 85 |
# File 'lib/scout_apm/error_service/error_record.rb', line 80 def clean_params(params) return if params.nil? normalized = normalize_data(params) filter_params(normalized) end |
#components(env) ⇒ Object
TODO: This is rails specific
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/scout_apm/error_service/error_record.rb', line 40 def components(env) components = {} unless env["action_dispatch.request.parameters"].nil? components[:controller] = env["action_dispatch.request.parameters"][:controller] || nil components[:action] = env["action_dispatch.request.parameters"][:action] || nil components[:module] = env["action_dispatch.request.parameters"][:module] || nil end # For background workers like sidekiq # TODO: extract data creation for background jobs components[:controller] ||= env[:custom_controller] components[:action] ||= env[:custom_action] components end |
#env_captured(env) ⇒ Object
104 105 106 107 108 109 110 111 112 |
# File 'lib/scout_apm/error_service/error_record.rb', line 104 def env_captured(env) env.select { |k, v| KEYS_TO_KEEP.include?(k) }.tap do |filtered_env| filtered_env["HTTP_X_FORWARDED_FOR"] = env["HTTP_X_FORWARDED_FOR"] if @agent_context.config.value('collect_remote_ip') && env["HTTP_X_FORWARDED_FOR"] @agent_context.config.value('errors_env_capture').each do |key| filtered_env[key] = env[key] if env[key] end end end |
#filter_key?(key) ⇒ Boolean
Check, if a key should be filtered
153 154 155 156 157 |
# File 'lib/scout_apm/error_service/error_record.rb', line 153 def filter_key?(key) params_to_filter.any? do |filter| key.to_s == filter.to_s # key.to_s.include?(filter.to_s) end end |
#filter_params(params) ⇒ Object
Replaces parameter values with a string / set in config file
138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/scout_apm/error_service/error_record.rb', line 138 def filter_params(params) return params unless filtered_params_config params.each do |k, v| if filter_key?(k) params[k] = "[FILTERED]" elsif v.respond_to?(:to_hash) filter_params(params[k]) end end params end |
#filtered_params_config ⇒ Object
Accessor for the filtered params config value. Will be removed as we refactor and clean up this code. TODO: Flip this over to use a new class like filtered exceptions?
165 166 167 |
# File 'lib/scout_apm/error_service/error_record.rb', line 165 def filtered_params_config @agent_context.config.value("errors_filtered_params") end |
#normalize_data(hash) ⇒ Object
TODO: Rename and make this clearer. I think it maps over the whole tree of a hash, and to_s each leaf node?
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/scout_apm/error_service/error_record.rb', line 115 def normalize_data(hash) new_hash = {} hash.each do |key, value| if value.respond_to?(:to_hash) begin new_hash[key] = normalize_data(value.to_hash) rescue new_hash[key] = LengthLimit.new(value.to_s).to_s end else new_hash[key] = LengthLimit.new(value.to_s).to_s end end new_hash end |
#params_to_filter ⇒ Object
159 160 161 |
# File 'lib/scout_apm/error_service/error_record.rb', line 159 def params_to_filter @params_to_filter ||= filtered_params_config + rails_filtered_params end |
#rack_request_url(env) ⇒ Object
TODO: Can I use the same thing we use in traces?
57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/scout_apm/error_service/error_record.rb', line 57 def rack_request_url(env) protocol = rack_scheme(env) protocol = protocol.nil? ? "" : "#{protocol}://" host = env["SERVER_NAME"] || "" path = env["REQUEST_URI"] || "" port = env["SERVER_PORT"] || "80" port = ["80", "443"].include?(port.to_s) ? "" : ":#{port}" protocol.to_s + host.to_s + port.to_s + path.to_s end |
#rack_scheme(env) ⇒ Object
69 70 71 72 73 74 75 76 77 |
# File 'lib/scout_apm/error_service/error_record.rb', line 69 def rack_scheme(env) if env["HTTPS"] == "on" "https" elsif env["HTTP_X_FORWARDED_PROTO"] env["HTTP_X_FORWARDED_PROTO"].split(",")[0] else env["rack.url_scheme"] end end |
#rails_filtered_params ⇒ Object
169 170 171 172 173 174 |
# File 'lib/scout_apm/error_service/error_record.rb', line 169 def rails_filtered_params return [] unless defined?(Rails) Rails.configuration.filter_parameters rescue [] end |