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



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

def initialize
  # list of handlers
  @error_handlers = []
  @log_file = nil
  add_handler('Type Generic') do |type, call_context|
    if !call_context[:response].code.start_with?('2')
      # add generic information
      RestErrorAnalyzer.add_error(call_context, type, "#{call_context[:request]['host']} #{call_context[:response].code} #{call_context[:response].message}")
    end
  end
end

Instance Attribute Details

#log_fileObject

Returns the value of attribute log_file.



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

def log_file
  @log_file
end

Class Method Details

.add_error(call_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)



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

def add_error(call_context, type, msg)
  call_context[:messages].push(msg)
  Log.log.trace1{"Found error: #{type}: #{msg}"}
  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#{call_context[:request].method} #{call_context[:request].path}\n#{call_context[:response].code}\n" \
      "#{JSON.generate(call_context[:data])}\n#{call_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 call_context is built in method raise_on_error



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

def add_handler(name, &block)
  @error_handlers.unshift({name: name, block: block})
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



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

def add_simple_handler(name:, always: false, path:)
  path.freeze
  add_handler(name) do |type, call_context|
    if call_context[:data].is_a?(Hash) && (!call_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) ? call_context[:data] : call_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(call_context, type, error_struct[path.last])
        error_struct.each do |k, v|
          next if k.eql?(path.last)
          RestErrorAnalyzer.add_error(call_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

Raises:



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

def raise_on_error(req, data, http)
  Log.log.debug{"raise_on_error #{req.method} #{req.path} #{http.code}"}
  call_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|
    begin # rubocop:disable Style/RedundantBegin
      # Log.log.debug{"test exception: #{handler[:name]}"}
      handler[:block].call(handler[:name], call_context)
    rescue StandardError => e
      Log.log.error{"ERROR in handler:\n#{e.message}\n#{e.backtrace}"}
    end
  end
  raise RestCallError.new(call_context) unless call_context[:messages].empty?
end