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



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

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.



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

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)



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

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



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

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



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

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, 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

Raises:



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

def raise_on_error(req, res)
  Log.log.debug{"raise_on_error #{req.method} #{req.path} #{res[:http].code}"}
  call_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 # 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[:messages].join("\n"), call_context[:request], call_context[:response]) unless call_context[:messages].empty?
end