Class: Aspera::RestErrorAnalyzer
- Inherits:
-
Object
- Object
- Aspera::RestErrorAnalyzer
- Includes:
- Singleton
- Defined in:
- lib/aspera/rest_error_analyzer.rb
Overview
analyze error codes returned by REST calls and raise ruby exception
Instance Attribute Summary collapse
-
#log_file ⇒ Object
Returns the value of attribute log_file.
Class Method Summary collapse
-
.add_error(context, type, message) ⇒ Object
Used by handler to add an error description to list of errors For logging and tracing : collect error descriptions (create file to activate).
-
.instance ⇒ RestErrorAnalyzer
Returns the singleton instance of RestErrorAnalyzer.
Instance Method Summary collapse
-
#add_handler(name, &block) ⇒ Object
Add a new error handler (done at application initialization) name is the one provided here context is built in method raise_on_error.
-
#add_simple_handler(name:, always: false, path:) ⇒ Object
Add a simple error handler Check that key exists and is string under specified path (hash) Adds other keys as secondary information.
-
#initialize ⇒ RestErrorAnalyzer
constructor
the singleton object is registered with application specific handlers.
-
#raise_on_error(req, data, http) ⇒ Object
Use this method to analyze a EST result and raise an exception Analyzes REST call response and raises a RestCallError exception if HTTP result code is not 2XX.
Constructor Details
#initialize ⇒ RestErrorAnalyzer
the singleton object is registered with application specific handlers
20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/aspera/rest_error_analyzer.rb', line 20 def initialize # list of handlers @error_handlers = [] @log_file = nil add_handler('Type Generic') do |type, context| if !context[:response].code.start_with?('2') # add generic information RestErrorAnalyzer.add_error(context, type, "#{context[:request]['host']} #{context[:response].code} #{context[:response].}") end end end |
Instance Attribute Details
#log_file ⇒ Object
Returns the value of attribute log_file.
17 18 19 |
# File 'lib/aspera/rest_error_analyzer.rb', line 17 def log_file @log_file end |
Class Method Details
.add_error(context, type, message) ⇒ Object
Used by handler to add an error description to list of errors For logging and tracing : collect error descriptions (create file to activate)
98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/aspera/rest_error_analyzer.rb', line 98 def add_error(context, type, ) context[:messages].push() Log.log.trace1{"Found error: #{type}: #{}"} log_file = instance.log_file # log error for further analysis (file must exist to activate) return if log_file.nil? || !File.exist?(log_file) File.open(log_file, 'a+') do |f| f.write("\n=#{type}=====\n#{context[:request].method} #{context[:request].path}\n#{context[:response].code}\n" \ "#{JSON.generate(context[:data])}\n#{context[:messages].join("\n")}") end end |
.instance ⇒ RestErrorAnalyzer
Returns the singleton instance of RestErrorAnalyzer
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 65 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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/aspera/rest_error_analyzer.rb', line 14 class RestErrorAnalyzer include Singleton attr_accessor :log_file # the singleton object is registered with application specific handlers def initialize # list of handlers @error_handlers = [] @log_file = nil add_handler('Type Generic') do |type, context| if !context[:response].code.start_with?('2') # add generic information RestErrorAnalyzer.add_error(context, type, "#{context[:request]['host']} #{context[:response].code} #{context[:response].}") end end end # Use this method to analyze a EST result and raise an exception # Analyzes REST call response and raises a RestCallError exception # if HTTP result code is not 2XX # @param req [Net::HTTPRequest] # @param data [Object] # @param http [Net::HTTPResponse] def raise_on_error(req, data, http) Log.log.debug{"raise_on_error #{req.method} #{req.path} #{http.code}"} context = { messages: [], request: req, response: http, data: data } # multiple error messages can be found # analyze errors from provided handlers # note that there can be an error even if code is 2XX @error_handlers.each do |handler| handler[:block].call(handler[:name], context) rescue StandardError => e Log.log.error{"ERROR in handler:\n#{e.}\n#{e.backtrace}"} end raise RestCallError, context unless context[:messages].empty? end # Add a new error handler (done at application initialization) # @param name [String] name of error handler (for logs) # @param block [Proc] processing of response: takes two parameters: `name`, `context` # name is the one provided here # context is built in method raise_on_error def add_handler(name, &block) @error_handlers.unshift({name: name, block: block}) nil end # Add a simple error handler # Check that key exists and is string under specified path (hash) # Adds other keys as secondary information # @param name [String] name of error handler (for logs) # @param always [Boolean] if true, always add error message, even if response code is 2XX # @param path [Array] path to error message in response def add_simple_handler(name:, always: false, path:) path.freeze add_handler(name) do |type, context| if context[:data].is_a?(Hash) && (!context[:response].code.start_with?('2') || always) # Log.log.debug{"simple_handler: #{type} #{path} #{path.last}"} # dig and find hash containing error message error_struct = path.length.eql?(1) ? context[:data] : context[:data].dig(*path[0..-2]) # Log.log.debug{"found: #{error_struct.class} #{error_struct}"} if error_struct.is_a?(Hash) && error_struct[path.last].is_a?(String) RestErrorAnalyzer.add_error(context, type, error_struct[path.last]) error_struct.each do |k, v| next if k.eql?(path.last) RestErrorAnalyzer.add_error(context, "#{type}(sub)", "#{k}: #{v}") if [String, Integer].include?(v.class) end end end end end class << self # Used by handler to add an error description to list of errors # For logging and tracing : collect error descriptions (create file to activate) # @param context [Hash] the result context, provided to handler # @param type [String] type of exception, for logging purpose # @param message [String] one error message to add to list def add_error(context, type, ) context[:messages].push() Log.log.trace1{"Found error: #{type}: #{}"} log_file = instance.log_file # log error for further analysis (file must exist to activate) return if log_file.nil? || !File.exist?(log_file) File.open(log_file, 'a+') do |f| f.write("\n=#{type}=====\n#{context[:request].method} #{context[:request].path}\n#{context[:response].code}\n" \ "#{JSON.generate(context[:data])}\n#{context[:messages].join("\n")}") end end end end |
Instance Method Details
#add_handler(name, &block) ⇒ Object
Add a new error handler (done at application initialization) name is the one provided here context is built in method raise_on_error
62 63 64 65 |
# File 'lib/aspera/rest_error_analyzer.rb', line 62 def add_handler(name, &block) @error_handlers.unshift({name: name, block: block}) nil end |
#add_simple_handler(name:, always: false, path:) ⇒ Object
Add a simple error handler Check that key exists and is string under specified path (hash) Adds other keys as secondary information
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/aspera/rest_error_analyzer.rb', line 73 def add_simple_handler(name:, always: false, path:) path.freeze add_handler(name) do |type, context| if context[:data].is_a?(Hash) && (!context[:response].code.start_with?('2') || always) # Log.log.debug{"simple_handler: #{type} #{path} #{path.last}"} # dig and find hash containing error message error_struct = path.length.eql?(1) ? context[:data] : context[:data].dig(*path[0..-2]) # Log.log.debug{"found: #{error_struct.class} #{error_struct}"} if error_struct.is_a?(Hash) && error_struct[path.last].is_a?(String) RestErrorAnalyzer.add_error(context, type, error_struct[path.last]) error_struct.each do |k, v| next if k.eql?(path.last) RestErrorAnalyzer.add_error(context, "#{type}(sub)", "#{k}: #{v}") if [String, Integer].include?(v.class) end end end end end |
#raise_on_error(req, data, http) ⇒ Object
Use this method to analyze a EST result and raise an exception Analyzes REST call response and raises a RestCallError exception if HTTP result code is not 2XX
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/aspera/rest_error_analyzer.rb', line 38 def raise_on_error(req, data, http) Log.log.debug{"raise_on_error #{req.method} #{req.path} #{http.code}"} context = { messages: [], request: req, response: http, data: data } # multiple error messages can be found # analyze errors from provided handlers # note that there can be an error even if code is 2XX @error_handlers.each do |handler| handler[:block].call(handler[:name], context) rescue StandardError => e Log.log.error{"ERROR in handler:\n#{e.}\n#{e.backtrace}"} end raise RestCallError, context unless context[:messages].empty? end |