Class: Aspera::RestErrorAnalyzer

Inherits:
Object
  • Object
show all
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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeRestErrorAnalyzer

the singleton object is registered with application specific handlers



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/aspera/rest_error_analyzer.rb', line 11

def initialize
  # list of handlers
  @error_handlers=[]
  @log_file=nil
  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

Instance Attribute Details

#log_fileObject

Returns the value of attribute log_file.



9
10
11
# File 'lib/aspera/rest_error_analyzer.rb', line 9

def log_file
  @log_file
end

Class Method Details

.add_error(context, type, msg) ⇒ Object

used by handler to add an error description to list of errors for logging and tracing : collect error descriptions (create file to activate)

Parameters:

  • context

    a Hash containing the result context, provided to handler

  • type

    a string describing type of exception, for logging purpose

  • msg

    one error message to add to list



88
89
90
91
92
93
94
95
96
97
# File 'lib/aspera/rest_error_analyzer.rb', line 88

def self.add_error(context,type,msg)
  context[:messages].push(msg)
  logfile=instance.log_file
  # log error for further analysis (file must exist to activate)
  if !logfile.nil? and File.exist?(logfile)
    File.open(logfile,'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

Instance Method Details

#add_handler(name, &block) ⇒ Object

add a new error handler (done at application initialisation) name is the one provided here context is built in method raiseOnError

Parameters:

  • name

    : name of error handler (for logs)

  • block

    : processing of response: takes two parameters: name, context



54
55
56
# File 'lib/aspera/rest_error_analyzer.rb', line 54

def add_handler(name,&block)
  @error_handlers.unshift({name: name, block: block})
end

#add_simple_handler(name, *args) ⇒ Object

add a simple error handler check that key exists and is string under specified path (hash) adds other keys as secondary information



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/aspera/rest_error_analyzer.rb', line 61

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

#raiseOnError(req, res) ⇒ 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



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/aspera/rest_error_analyzer.rb', line 26

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