From 63fcd8f8feed58af4b1e1ff0e5fdaa09791c9596 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 8 Mar 2012 15:23:43 +0000 Subject: improved integration of error reports, call stack added as errorDetails --- lib/error.rb | 147 ++++++++++++++++++----------------------------------------- 1 file changed, 44 insertions(+), 103 deletions(-) (limited to 'lib/error.rb') diff --git a/lib/error.rb b/lib/error.rb index 2033c1e..0ab2c73 100644 --- a/lib/error.rb +++ b/lib/error.rb @@ -1,24 +1,27 @@ require 'open4' -# adding additional fields to Exception class to format errors according to OT-API +# add additional fields to Exception class to format errors according to OT-API class RuntimeError - attr_accessor :report, :http_code - def initialize message + attr_accessor :http_code, :uri + def initialize message, uri=nil super message - self.set_backtrace message.backtrace if message.is_a? Exception + @uri = uri @http_code ||= 500 - puts self.class - @report = OpenTox::ErrorReport.create self - $logger.error "\n"+@report.to_turtle + $logger.error "\n"+self.report.to_turtle + end + + def report + # TODO: remove kludge for old task services + OpenTox::ErrorReport.new(@http_code, self) end end module OpenTox class Error < RuntimeError - def initialize code, message + def initialize code, message, uri=nil @http_code = code - super message + super message, uri end end @@ -35,15 +38,16 @@ module OpenTox }.each do |klass,code| # create error classes c = Class.new Error do - define_method :initialize do |message| - super code, message + define_method :initialize do |message, uri=nil| + super code, message, uri end end OpenTox.const_set klass,c # define global methods for raising errors, eg. bad_request_error Object.send(:define_method, klass.underscore.to_sym) do |message| - raise c.new message + defined?(@uri) ? uri = @uri : uri=nil + raise c, message, uri end end @@ -53,61 +57,41 @@ module OpenTox def initialize request, response, message @request = request @response = response - super 502, message + super 502, message, request.url end end + # TODO: create reports directly from errors, requires modified task service class ErrorReport - - attr_accessor :rdf # RDF Graph - attr_accessor :http_code # TODO: remove when task service is fixed - - def initialize - @rdf = RDF::Graph.new - end - - # creates a error report object, from an ruby-exception object - # @param [Exception] error - def self.create error - report = ErrorReport.new - subject = RDF::Node.new - report.rdf << [subject, RDF.type, RDF::OT.ErrorReport] - message = error.message - errorDetails = "" - if error.respond_to? :request - report.rdf << [subject, RDF::OT.actor, error.request.url ] - errorDetails += "REST paramenters:\n#{error.request.args.inspect}" - end - error.respond_to?(:http_code) ? statusCode = error.http_code : statusCode = 500 - puts error.inspect - if error.respond_to? :response - statusCode = error.response.code if error.response - message = error.response.body - end - statusCode = error.http_code if error.respond_to? :http_code - report.rdf << [subject, RDF::OT.statusCode, statusCode ] - report.rdf << [subject, RDF::OT.errorCode, error.class.to_s ] - # TODO: remove kludge for old task services - report.http_code = statusCode - report.rdf << [subject, RDF::OT.message , message ] - errorDetails += "\nBacktrace:\n" + error.backtrace.short_backtrace if error.respond_to?(:backtrace) and error.backtrace - report.rdf << [subject, RDF::OT.errorDetails, errorDetails ] - # TODO Error cause - #report.rdf << [subject, OT.errorCause, error.report] if error.respond_to?(:report) and !error.report.empty? - report + def initialize http_code, error + @http_code = http_code + #@report = report#.to_yaml + @report = {} + @report[RDF::OT.actor] = error.uri + @report[RDF::OT.message] = error.message + @report[RDF::OT.statusCode] = @http_code + @report[RDF::OT.errorCode] = error.class.to_s + @report[RDF::OT.errorDetails] = caller.collect{|line| line unless line =~ /#{File.dirname(__FILE__)}/}.compact.join("\n") + @report[RDF::OT.errorDetails] += "REST paramenters:\n#{error.request.args.inspect}" if defined? error.request + @report[RDF::OT.message] += "\n" + error.response.body if defined? error.response + # TODO fix Error cause + #report[RDF::OT.errorCause] = @report if defined?(@report) end - def actor=(uri) - # TODO: test actor assignement (in opentox-server) - subject = RDF::Query.execute(@rdf) do - pattern [:subject, RDF.type, RDF::OT.ErrorReport] - end.limit(1).select(:subject) - @rdf << [subject, RDF::OT.actor, uri] - end - # define to_ and self.from_ methods for various rdf formats - [:rdfxml,:ntriples,:turtle].each do |format| + RDF_FORMATS.each do |format| + + send :define_method, "to_#{format}".to_sym do + rdf = RDF::Writer.for(format).buffer do |writer| + subject = RDF::Node.new + @report.each do |predicate,object| + writer << [subject, predicate, object] if object + end + end + rdf + end +=begin define_singleton_method "from_#{format}".to_sym do |rdf| report = ErrorReport.new RDF::Reader.for(format).new(rdf) do |reader| @@ -115,50 +99,7 @@ module OpenTox end report end - - send :define_method, "to_#{format}".to_sym do - rdfxml = RDF::Writer.for(format).buffer do |writer| - @rdf.each{|statement| writer << statement} - end - rdfxml - end - end - - end -end - -# overwrite backtick operator to catch system errors -module Kernel - - # Override raises an error if _cmd_ returns a non-zero exit status. - # Returns stdout if _cmd_ succeeds. Note that these are simply concatenated; STDERR is not inline. - def ` cmd - stdout, stderr = '' - status = Open4::popen4(cmd) do |pid, stdin_stream, stdout_stream, stderr_stream| - stdout = stdout_stream.read - stderr = stderr_stream.read - end - raise stderr.strip if !status.success? - return stdout - rescue Exception - internal_server_error $! - end - - alias_method :system!, :system - - def system cmd - `#{cmd}` - return true - end -end - -class Array - def short_backtrace - short = [] - each do |c| - break if c =~ /sinatra\/base/ - short << c +=end end - short.join("\n") end end -- cgit v1.2.3