Исключение Ruby reraising w/дополнительный аргумент строки
Вот ситуация. Я хочу, чтобы все исключения в doStuff() выливались через код, чтобы они обрабатывались на более высоком уровне.
Я также хотел бы записать, как часто любые исключения выполняются в doStuff() на более высоком уровне, и я в настоящее время делаю это:
begin
doStuff()
rescue Exception =>
raise e, "specific error to log in a db"
Код doStuff генерирует десятки исключений, и я хочу зафиксировать каждое из этих событий, чтобы положить в db. Существует doStuff2(), который также может передавать идентичные инструкции, и я хочу знать, из какой функции они пришли.
Добавление дополнительной строки, кажется, изменяет само исключение, и я теряю все хорошие данные о форматировании и трассировке, которые были в исходном исключении.
Любые предложения о том, как я могу сделать ререйз оригинального исключения, но также отслеживать все исключения, которые происходят в doStuff()?
Ответы
Ответ 1
Если вы вызываете raise
без передачи какого-либо аргумента, Ruby будет повторно поднимать последнее исключение.
begin
doStuff()
rescue => e
log_exception(e)
raise # This will re-raise the last exception.
end
В качестве дополнительной заметки я хотел бы рассказать вам о лучших практиках Ruby.
-
doStuff()
метод не соответствует соглашениям об именах Ruby. Вы должны использовать подчеркивание для методов. Используйте do_stuff
. Кроме того, нет необходимости использовать ()
, если нет аргументов.
- Никогда не спасайте Exception, вместо этого спасайте самый низкоуровневый класс, который вам нужно спасти. В большинстве случаев вам может понадобиться спасти все типы StandardError или RuntimeError. Фактически, если вы используете спасение без передачи типа ошибки, Ruby автоматически спасет любой подкласс StandardError.
Exception
класс очень низкий, и он также будет улавливать синтаксические ошибки и несколько других проблем компилятора. Возможно, вы захотите, чтобы приложение вышло из строя в этом случае, чтобы вы не развертывали сломанное приложение.
Ответ 2
Вы можете сохранить обратную трассировку и сообщение первого исключения и создать новое исключение для повышения
begin
rescue Exception => e
new_ex = Exception.new("Error while executing ...:#{e.message}")
new_ex.set_backtrace(e.backtrace)
raise new_ex
end
Ответ 3
Вы не можете создать новое исключение и сохранить предыдущее исключение и его стек из таблицы. Вложенные исключения из Java-мира, к сожалению, недоступны. Он будет доступен в Ruby 2.1. Это довольно горячая тема. https://bugs.ruby-lang.org/issues/8257
Вы можете использовать nesty
gem для его использования. Вам нужно только include Nesty::NestedError
в ваших классах исключений. Больше информации здесь: https://github.com/skorks/nesty/