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



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/aspera/rest_error_analyzer.rb', line 16

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].message}")
    end
  end
end

Instance Attribute Details

#log_fileObject

Returns the value of attribute log_file.



13
14
15
# File 'lib/aspera/rest_error_analyzer.rb', line 13

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)

Parameters:

  • the result context, provided to handler

  • type of exception, for logging purpose

  • one error message to add to list



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/aspera/rest_error_analyzer.rb', line 94

def add_error(context, type, message)
  context[:messages].push(message)
  Log.log.trace1{"Found error: #{type}: #{message}"}
  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 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

Parameters:

  • name of error handler (for logs)

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



58
59
60
61
# File 'lib/aspera/rest_error_analyzer.rb', line 58

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

Parameters:

  • name of error handler (for logs)

  • (defaults to: false)

    if true, always add error message, even if response code is 2XX

  • path to error message in response



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/aspera/rest_error_analyzer.rb', line 69

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

Parameters:

Raises:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/aspera/rest_error_analyzer.rb', line 34

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.message}\n#{e.backtrace}"}
  end
  raise RestCallError, context unless context[:messages].empty?
end