summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormguetlein <martin.guetlein@gmail.com>2013-08-08 16:40:54 +0200
committermguetlein <martin.guetlein@gmail.com>2013-08-08 16:40:54 +0200
commitb4c39cd8c4dfcc40bdabc9db205bd347c2c0d826 (patch)
tree66a743c71cc6a89840933174fcf6e4dacd41c358 /lib
parent8df7c351733c56b22a638244b88feeca833e196f (diff)
error handling rewrite: making sure to pass backtrace
Diffstat (limited to 'lib')
-rw-r--r--lib/error.rb43
-rw-r--r--lib/overwrite.rb16
-rw-r--r--lib/rest-client-wrapper.rb23
-rw-r--r--lib/task.rb26
4 files changed, 54 insertions, 54 deletions
diff --git a/lib/error.rb b/lib/error.rb
index 85ce35d..23e738d 100644
--- a/lib/error.rb
+++ b/lib/error.rb
@@ -2,8 +2,11 @@ require 'open4'
# add additional fields to Exception class to format errors according to OT-API
module OpenToxError
- attr_accessor :http_code, :uri
- def initialize message, uri=nil
+ attr_accessor :http_code, :uri, :error_cause
+ def initialize(message, uri=nil, cause=nil)
+ message.gsub!(/\A"|"\Z/, '') # remove quotes
+ @error_cause = cause ? OpenToxError::cut_backtrace(cause) : short_backtrace
+
super message
#unless self.is_a? Errno::EAGAIN # avoid "Resource temporarily unavailable" errors
@uri = uri.to_s.sub(%r{//.*:.*@},'//') # remove credentials from uri
@@ -12,21 +15,29 @@ module OpenToxError
subject = RDF::Node.new
@rdf << [subject, RDF.type, RDF::OT.ErrorReport]
@rdf << [subject, RDF::OT.actor, @uri]
- @rdf << [subject, RDF::OT.message, message.sub(/^"/,'').sub(/"$/,'')]
+ @rdf << [subject, RDF::OT.message, message]
@rdf << [subject, RDF::OT.statusCode, @http_code]
@rdf << [subject, RDF::OT.errorCode, self.class.to_s]
- @rdf << [subject, RDF::OT.errorCause, short_backtrace]
+ @rdf << [subject, RDF::OT.errorCause, @error_cause]
$logger.error("\n"+self.to_turtle)
#end
end
-
+
+ def self.cut_backtrace(trace)
+ if trace.is_a?(Array)
+ cut_index = trace.find_index{|line| line.match(/sinatra|minitest/)}
+ cut_index ||= trace.size
+ cut_index -= 1
+ cut_index = trace.size-1 if cut_index < 0
+ trace[0..cut_index].join("\n")
+ else
+ trace
+ end
+ end
+
def short_backtrace
backtrace = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact
- cut_index = backtrace.find_index{|line| line.match /sinatra|minitest/}
- cut_index ||= backtrace.size
- cut_index -= 1
- cut_index = backtrace.size-1 if cut_index < 0
- backtrace[0..cut_index].join("\n")
+ OpenToxError::cut_backtrace(backtrace)
end
RDF_FORMATS.each do |format|
@@ -63,9 +74,9 @@ module OpenTox
class Error < RuntimeError
include OpenToxError
- def initialize code, message, uri=nil
+ def initialize(code, message, uri=nil, cause=nil)
@http_code = code
- super message, uri
+ super message, uri, cause
end
end
@@ -73,15 +84,15 @@ module OpenTox
RestClientWrapper.known_errors.each do |error|
# create error classes
c = Class.new Error do
- define_method :initialize do |message, uri=nil|
- super error[:code], message, uri
+ define_method :initialize do |message, uri=nil, cause=nil|
+ super error[:code], message, uri, cause
end
end
OpenTox.const_set error[:class],c
# define global methods for raising errors, eg. bad_request_error
- Object.send(:define_method, error[:method]) do |message,uri=nil|
- raise c.new(message.inspect, uri)
+ Object.send(:define_method, error[:method]) do |message,uri=nil,cause=nil|
+ raise c.new(message.inspect, uri, cause)
end
end
diff --git a/lib/overwrite.rb b/lib/overwrite.rb
index ff43347..0830490 100644
--- a/lib/overwrite.rb
+++ b/lib/overwrite.rb
@@ -155,16 +155,12 @@ module Kernel
t = OpenTox::Task.new uri
t.wait
unless t.completed?
- begin # handle known (i.e. OpenTox) errors
- error = OpenTox::RestClientWrapper.known_errors.select{|error| error[:code] == t.code}.first
- error ? error_method = error[:method] : error_method = :internal_server_error
- report = t.error_report
- report ? error_message = report[RDF::OT.message] : error_message = $!.message
- Object.send(error_method,error_message,t.uri)
- rescue
- internal_server_error "#{$!.message}", t.uri
- #internal_server_error "#{$!.message}\n#{$!.backtrace}", t.uri
- end
+ error = OpenTox::RestClientWrapper.known_errors.select{|error| error[:code] == t.code}.first
+ error_method = error ? error[:method] : :internal_server_error
+ report = t.error_report
+ error_message = report ? report[RDF::OT.message] : $!.message
+ error_cause = report ? report[RDF::OT.errorCause] : nil
+ Object.send(error_method,error_message,t.uri,error_cause)
end
uri = t.resultURI
end
diff --git a/lib/rest-client-wrapper.rb b/lib/rest-client-wrapper.rb
index 134dd32..3ed41ad 100644
--- a/lib/rest-client-wrapper.rb
+++ b/lib/rest-client-wrapper.rb
@@ -53,13 +53,24 @@ module OpenTox
if [301, 302, 307].include? response.code and request.method == :get
response.follow_redirection(request, result)
elsif response.code >= 400 and !URI.task?(uri)
- message = response.to_s
- parameters = request.args
- parameters[:headers][:subjectid] = "REMOVED" if parameters[:headers] and parameters[:headers][:subjectid]
- parameters[:url] = parameters[:url].gsub(/(http|https|)\:\/\/[a-zA-Z0-9\-]+\:[a-zA-Z0-9]+\@/, "REMOVED@") if parameters[:url]
- message += "\nREST parameters:\n#{parameters.inspect}"
+ #TODO add parameters to error-report
+ #parameters = request.args
+ #parameters[:headers][:subjectid] = "REMOVED" if parameters[:headers] and parameters[:headers][:subjectid]
+ #parameters[:url] = parameters[:url].gsub(/(http|https|)\:\/\/[a-zA-Z0-9\-]+\:[a-zA-Z0-9]+\@/, "REMOVED@") if parameters[:url]
+ #message += "\nREST parameters:\n#{parameters.inspect}"
error = known_errors.collect{|e| e if e[:code] == response.code}.compact.first
- Object.method(error[:method]).call message, uri # call error method
+ begin # errors are returned as error reports in turtle, try to parse
+ content = {}
+ RDF::Reader.for(:turtle).new(response.to_s) do |reader|
+ reader.each_triple{|triple| content[triple[1]] = triple[2]}
+ end
+ msg = content[RDF::OT.message].to_s
+ cause = content[RDF::OT.errorCause].to_s
+ rescue # parsing error failed, use complete content as message
+ msg = response.to_s
+ cause = nil
+ end
+ Object.method(error[:method]).call msg, uri, cause # call error method
else
response
end
diff --git a/lib/task.rb b/lib/task.rb
index 07efc0f..6d6a3a7 100644
--- a/lib/task.rb
+++ b/lib/task.rb
@@ -21,28 +21,10 @@ module OpenTox
pid = fork do
begin
task.completed yield
- rescue
- if $!.respond_to? :to_ntriples
- RestClientWrapper.put(File.join(task.uri,'Error'),{:errorReport => $!.to_ntriples},{:content_type => 'text/plain'})
- else
- cut_index = $!.backtrace.find_index{|line| line.match /gems\/sinatra/}
- cut_index = -1 unless cut_index
- @rdf = RDF::Graph.new
- subject = RDF::Node.new
- @rdf << [subject, RDF.type, RDF::OT.ErrorReport]
- @rdf << [subject, RDF::OT.message, $!.message]
- @rdf << [subject, RDF::OT.errorCode, $!.class.to_s]
- @rdf << [subject, RDF::OT.errorCause, $!.backtrace[0..cut_index].join("\n")]
- prefixes = {:rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#", :ot => RDF::OT.to_s}
- turtle = RDF::Turtle::Writer.for(:turtle).buffer(:prefixes => prefixes) do |writer|
- @rdf.each{|statement| writer << statement}
- end
- $logger.error turtle
- nt = RDF::Writer.for(:ntriples).buffer do |writer|
- @rdf.each{|statement| writer << statement}
- end
- RestClientWrapper.put(File.join(task.uri,'Error'),{:errorReport => nt},{:content_type => 'text/plain'})
- end
+ rescue => e
+ # wrap non-opentox-errors first
+ e = OpenTox::Error.new(500,e.message,nil,e.backtrace) unless e.is_a?(OpenTox::Error)
+ RestClientWrapper.put(File.join(task.uri,'Error'),{:errorReport => e.to_ntriples},{:content_type => 'text/plain'})
task.kill
end
end