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_REMOVE =
Deletes params from env
These are not configurable, and will leak PII info up to Scout if allowed through. Things like specific parameters can be exposed with the ScoutApm::Context interface.
[ "rack.request.form_hash", "rack.request.form_vars", "async.callback", # Security related items "action_dispatch.secret_key_base", "action_dispatch.http_auth_salt", "action_dispatch.signed_cookie_salt", "action_dispatch.encrypted_cookie_salt", "action_dispatch.encrypted_signed_cookie_salt", "action_dispatch.authenticated_encrypted_cookie_salt", # Raw data from the URL & parameters. Would bypass our normal params filtering "QUERY_STRING", "REQUEST_URI", "REQUEST_PATH", "ORIGINAL_FULLPATH", "action_dispatch.request.query_parameters", "action_dispatch.request.parameters", "rack.request.query_string", "rack.request.query_hash", ]
Instance Attribute Summary collapse
-
#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.
-
#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_session ⇒ Object
readonly
Returns the value of attribute request_session.
-
#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.
-
#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
- #session_data(env) ⇒ Object
- #strip_env(env) ⇒ Object
Constructor Details
#initialize(agent_context, exception, env, context = nil) ⇒ ErrorRecord
Returns a new instance of ErrorRecord.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/scout_apm/error_service/error_record.rb', line 16 def initialize(agent_context, exception, env, context=nil) @agent_context = agent_context @context = if context context.to_hash else {} end @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"]) @request_session = clean_params(session_data(env)) @environment = clean_params(strip_env(env)) @trace = clean_backtrace(exception.backtrace) @request_components = components(env) end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
14 15 16 |
# File 'lib/scout_apm/error_service/error_record.rb', line 14 def context @context end |
#environment ⇒ Object (readonly)
Returns the value of attribute environment.
11 12 13 |
# File 'lib/scout_apm/error_service/error_record.rb', line 11 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 |
#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.
13 14 15 |
# File 'lib/scout_apm/error_service/error_record.rb', line 13 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_session ⇒ Object (readonly)
Returns the value of attribute request_session.
10 11 12 |
# File 'lib/scout_apm/error_service/error_record.rb', line 10 def request_session @request_session 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.
12 13 14 |
# File 'lib/scout_apm/error_service/error_record.rb', line 12 def trace @trace end |
Instance Method Details
#clean_backtrace(backtrace) ⇒ Object
TODO: When was backtrace_cleaner introduced?
83 84 85 86 87 88 89 |
# File 'lib/scout_apm/error_service/error_record.rb', line 83 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
75 76 77 78 79 80 |
# File 'lib/scout_apm/error_service/error_record.rb', line 75 def clean_params(params) return if params.nil? normalized = normalize_data(params) filter_params(normalized) end |
#components(env) ⇒ Object
TODO: This is rails specific
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/scout_apm/error_service/error_record.rb', line 36 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 end |
#filter_key?(key) ⇒ Boolean
Check, if a key should be filtered
173 174 175 176 177 |
# File 'lib/scout_apm/error_service/error_record.rb', line 173 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
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/scout_apm/error_service/error_record.rb', line 158 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?
185 186 187 |
# File 'lib/scout_apm/error_service/error_record.rb', line 185 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?
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/scout_apm/error_service/error_record.rb', line 135 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
179 180 181 |
# File 'lib/scout_apm/error_service/error_record.rb', line 179 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?
52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/scout_apm/error_service/error_record.rb', line 52 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
64 65 66 67 68 69 70 71 72 |
# File 'lib/scout_apm/error_service/error_record.rb', line 64 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
189 190 191 192 193 194 |
# File 'lib/scout_apm/error_service/error_record.rb', line 189 def rails_filtered_params return [] unless defined?(Rails) Rails.configuration.filter_parameters rescue [] end |
#session_data(env) ⇒ Object
123 124 125 126 127 128 129 130 131 132 |
# File 'lib/scout_apm/error_service/error_record.rb', line 123 def session_data(env) session = env["action_dispatch.request.session"] return if session.nil? if session.respond_to?(:to_hash) session.to_hash else session.data end end |
#strip_env(env) ⇒ Object
119 120 121 |
# File 'lib/scout_apm/error_service/error_record.rb', line 119 def strip_env(env) env.reject { |k, v| KEYS_TO_REMOVE.include?(k) } end |