class Asperalm::RestErrorAnalyzer
builds a meaningful error message from known formats in Aspera products TODO: probably too monolithic..
Public Class Methods
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 a Hash
containing the result context, provided to handler @param type a string describing type of exception, for logging purpose @param msg one error message to add to list
# File lib/asperalm/rest_error_analyzer.rb, line 85 def self.add_error(context,type,msg) context[:messages].push(msg) # log error for further analysis (file must exist to activate) exc_log_file=File.join(Fasp::Installation.instance.config_folder,'exceptions.log') if File.exist?(exc_log_file) File.open(exc_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
# File lib/asperalm/rest_error_analyzer.rb, line 10 def initialize # list of handlers @error_handlers=[] self.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].message}") end end end
Public Instance Methods
add a new error handler @param name : name of error handler (for logs) @param block : processing of response: takes two parameters: name, context name is the one provided here context is built in method raiseOnError
# File lib/asperalm/rest_error_analyzer.rb, line 51 def add_handler(name,&block) @error_handlers.unshift({name: name, block: block}) end
add a simple error handler check that key exists and is string under specified path (hash) adds other keys as secondary information
# File lib/asperalm/rest_error_analyzer.rb, line 58 def add_simple_handler(name,*args) add_handler(name) do |type,context| # need to clone because we modify and same array is used subsequently path=args.clone Log.log.debug("path=#{path}") # if last in path is boolean it tells if the error is only with http error code or always always=[true, false].include?(path.last) ? path.pop : false if context[:data].is_a?(Hash) and (!context[:response].code.start_with?('2') or always) msg_key=path.pop # dig and find sub entry corresponding to path in deep hash error_struct=path.inject(context[:data]) { |subhash, key| subhash.respond_to?(:keys) ? subhash[key] : nil } if error_struct.is_a?(Hash) and error_struct[msg_key].is_a?(String) RestErrorAnalyzer.add_error(context,type,error_struct[msg_key]) error_struct.each do |k,v| next if k.eql?(msg_key) RestErrorAnalyzer.add_error(context,"#{type}(sub)","#{k}: #{v}") if [String,Integer].include?(v.class) end end end end end
Analyzes REST call response and raises a RestCallError
exception if HTTP result code is not 2XX
# File lib/asperalm/rest_error_analyzer.rb, line 23 def raiseOnError(req,res) context={ messages: [], request: req, response: res[:http], data: res[: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| begin Log.log.debug("test exception: #{handler[:name]}") handler[:block].call(handler[:name],context) rescue => e Log.log.error("ERROR in handler:\n#{e.message}\n#{e.backtrace}") end end unless context[:messages].empty? raise RestCallError.new(context[:request],context[:response],context[:messages].join("\n")) end end