Рубрики
Uncategorized

Улучшите свою жизнь с длинными сообщениями об ошибках

Неведомо полезно быстро обнаружить, когда клиент встречает ошибку и где ошибка … Теги с DevOps, Codequality.

Невероятно полезно быстро обнаружить, когда клиент столкнулся с ошибкой и где произошла ошибка из исходного кода. К счастью, вот где многие интерпретированные языки сияют. Они всегда включают полную задницу — путь, в котором был сделан вызов, что вызвало повышенную ошибку (или бросить).

В Appsignal любое предупреждение об ошибке приведет вас к странице с деталями инцидента, которая показывает вам, что backtrace. С Github или Gitlab Integration вы можете немедленно перейти от ошибки к месту для ее решения.

Кроме того, однако, мы можем сделать наши ошибки более полезными — с небольшим количеством прозы.

Три основных вопроса сообщения об ошибке должны ответить

Люди, которые достаточно взросли, скорее всего вспомнит этот экран со дня старого (Pre-Unix) Macos:

Это сказали нам только одно: ваша работа закончилась, пришло время перезагрузить машину. Но мне потребовалось некоторое время, чтобы выяснить, почему эта ошибка была настолько особенно расстраивающими — это не ответило бы никаких «больших трех» вопросов, которые я полагаю, что ошибка должна удовлетворять:

  • Что случилось?

Не «катастрофический провал», но что именно произошло? Флюс конденсатор переполнен инсигатор частиц? Был определенным параметром выше (или ниже) приемлемого значения? Был ли часть неверного пользовательского ввода для вины? Ошибка должна объяснить что случилось.

  • Где это произошло?

Был ли он QuickTime Player, который разбил свою машину? Это был этот новый драйвер USB Mouse, который я только что установил?

Ошибка должна объяснить где Это возникло. Не там, где это произошло именно в коде — задний корпус обычно охватывает эту часть — но какой компонент высокого уровня он проистекает. Если ваш Windowserver Сбивает в MacOS, не так ужеливать, что ваш UI разбился потому что Windowserver это процесс, который владеет и управляет всем на экране. Но какое приложение вызвало Windowserver сбой?

  • Что я могу сделать, чтобы ошибка уйти?

Неправильный ввод причиняет это? Может быть, мы пытаемся получить доступ к некоторым данным, например, больше не доступны, и мы могли бы поймать эту попытку доступа на более высоком уровне стека? Или, может быть, у нас есть клиент, который отправляет неверный ввод и всегда приводит к этой ошибке? Ошибка должна сделать все возможное, чтобы сказать нам Как помешать ему снова произойти.

Пункт 4 в этом списке будет «автоматическое восстановление», и он становится актуальным, когда несколько систем знают о той же семантике ошибки и пытаются восстановить из них распределенным образом. Это может быть отличная тема для будущей статьи.

Оптимизация вашей ошибки для читателя

Посмотрите на эту ошибку, как вы увидите его в Appsignal:

Он поднимается популярным Ruby Gem называется СГРАВКА Отказ Этот драгоценный камень реализует знаменитый Автоматический выключатель Узор в Руби.

Краткое описание того, какие автоматические выключатели делают:

  • Если вы вызываете внешнюю службу (API веб-службы, база данных или облачную систему хранения), ваш вызов может потерпеть неудачу. Если сервис, которую вы звоните в течение долгого времени, все ваши звонки будут потерпят неудачу, и вы будете бомбардировать эту услугу с помощью звонков и попытках подключения.
  • Чтобы позволить вашему приложению продолжить независимо от того, и избежать сервиса, вы вызываете, из перегрузки — так называемый «автоматический выключатель» вставлен между вашим приложением (вызывающим абонентом) и службой ваших приложений (CALLEE).
  • Должны N последовательные вызовы от вызывающего абонента к Callee Fail, автоматический выключатель будет «открывать» и запрещает проходить последующие вызовы, быстро вызовы их вызовы.
  • Через некоторое время автоматический выключатель попытается «закрыть» и разрешить звонки. Если Callee восстановился к тому времени, нормальная операция возобновится.

После начнете использования нескольких услуг, с автоматическим выключателем становится абсолютной необходимостью. Иногда вам нужны несколько автоматических выключателей — один для каждой службы, который вы звоните (или для каждого хоста, который вы звоните, в зависимости от ситуации). Особый сервис, который вы звоните, могут быть отзывчивыми, в то время как другой может иметь плохое время.

Съемка предоставляет такую обертку, и когда сервис вы звоните, не работает (в течение некоторого времени), автоматический выключатель открыт. GEM поднимает исключение, чтобы указать, что звонок не может пройти.

Давайте рассмотрим эту ошибку против «больших трех» вопросов, которые я упомянул выше:

  • Что случилось?

Ну, звонок на сервис споргил автоматический выключатель — некоторые Автоматический выключатель. Можно сказать, что это удовлетворяет Какой? Вопрос, хотя для меня было бы конструктивно знать, что была возникающая ошибка. Эта ошибка — происходит (или обертка , если вы будете). Оказается поднятие некогда какая-то другая ошибка (тот, который вызывает исходный отказ службы), происходит в течение некоторого времени. Это ошибка, которую я бы ожидал увидеть в сообщении.

  • Где это произошло?

Ошибка имеет обратную корзину, и если мы следим за этим внимательно, мы находим некоторые подсказки для где Это возникло. Приложение, которое было поднято, из данной ошибки производит обратный транспорт 34 уровня, а точку, где выключатель выключателя находится на уровне 4.

Это не говорит нам, какую услугу мы звонили или как долго обслуживание неработоспособна. Так что это, безусловно, не выполняет где Часть и делает расследование сложнее. Что поможет для ошибки, чтобы сказать нам, в которой оказание услуг Это произошло — что мы звонили, когда это произошло?

  • Что я могу сделать, чтобы ошибка уйти?

Эта ошибка не говорит нам, что мы можем сделать, чтобы восстановить операцию. На первый взгляд, казалось бы, что он никогда не может — удаленный сервис не отвечает, никто не знает, когда оно может восстановиться. Итак, Предотвращение этого снова происходит Похоже, сошло со стола.

Но подумайте еще раз: мы могли бы знать, например, что сервис не ответил на 30 секунд, или что он был в четыре раза за последние 24 часа — что позволит нам связаться с владельцами услуг и спросить их о . их SLOS Отказ

Что еще более важно, в этом конкретном случае ошибка привела к разработчику, пытаясь сделать неверную ошибку исправления. Это довольно реальная опасность для ошибок, которые кажутся серьезными, но не отвечают на три основных вопроса. Помните, когда вы обрабатываете ошибки, вы часто будете находиться в стрессовой ситуации. Возможно, ваше приложение перегружено, и вам нужно быстро исправить. Или это может быть, что ваш бизнес зависит от этой транзакции, происходящего, а автоматический выключатель находится в горячей траектории транзакции.

В нашей конкретной ситуации инженер пытался захватить все вызовы и запрещать исходящие HTTP-запросы к определенному имени хоста, потому что они предполагали, что вызовы автоматического выключателя в все Хозяева обрабатываются кодовым путем. Они не знали, что имя сервиса для автоматического выключателя было специфичным для имени хоста, которое мы вызывали, и что автоматический выключатель споткнулся для внешнего сервиса А не означало, что он также споткнулся на услугу B. Это цена сообщений об ошибках, которые недостаточно информативны.

Итак, хотя автоматический выключатель практичен, это сообщение об ошибке может использовать некоторые TLC. Посмотрим, где мы можем сделать улучшения.

Добавление большего контекста к ошибке с heredocs

Первое и простые — изменение, которое мы можем сделать, это объяснить значение этой ошибки. Начнем с имени класса. Это может быть очень описательным — например, ActiveReCord:: Rechoodnotfobound это достаточно описательное имя класса для исключения. СУМКА:: CICHOPEN в этом отношении довольно хорош — он передает нам состояние ошибки.

Следующая часть, чтобы посмотреть, — это сообщение об ошибке. Когда вы инициализируете объект, который подклассы Исключение В Ruby вы можете передавать строку данных, чтобы включить в качестве сообщения об ошибке. Сообщение тогда доступно под Исключение # Сообщение Метод:

raise ServiceUnavailable, "The service you were trying to call was unavailable"`

Давайте применим эти шаблоны в наше сообщение с открытым цепи:

raise CircuitOpen, <<~EOM
  The circuit breaker is open. This means that the service you are calling has been unavailable or has been timing out
  for some time, and the circuit breaker has opened to prevent your application from slowing down and to protect the
  service you are calling from the thundering herd of requests once it recovers.
EOM

Это приближает нас к исполнению вопроса 1 — рассказывать что случилось. Теперь ошибка будет понятна для тех, кто не знает, что СГРАВКА GEM делает или какие различные исключения означают. Это ускоряет отладку. Но мы все еще можем взять это дальше!

Принимая его нашут в дальнейшем с динамическими данными

Для некоторого вдохновения мы можем посмотреть на ActiveReCord:: Rechoodnotfobound сообщение об ошибке:

Couldn't find Batch with 'id'=14082

Это сообщение об ошибке связывает несколько решающих битов информации, а именно:

  • Какая модель мы пытались найти (в этом случае, Пакет Несомненно
  • Какой ряд мы искали (в этом случае, ряд с ID 14082 )

Это приближает нас к выполнению второго и третьего вопросов. Это говорит нам, где это произошло (где-то, где мы искали пакет с ID 14082 ), но и в той степени, что мы можем сделать, чтобы предотвратить его снова Отказ Нам нужно найти, где код, аналогичный этому, выполняется в одном из наших линий задних условий или близко к ним:

Batch.find(id)

Но если мы посмотрим на другие примеры из рельсов, мы можем увидеть там несколько полезных сообщений об ошибках. Например, знаменитое расширение «Wiby Nil» говорит вам, когда вы ошибочно пытаетесь получить ID из Ниль стоимость:

Called id for nil, which would mistakenly be 4 -- if you really wanted
the id of nil, use object_id

Мы не ограничиваются уточнением сообщений об ошибках с однострочными строками, мы также можем использовать Heredocs — многослойная строка, предварительно обработанная с разрывами линии. В то время как довольно несколько человек используют Heredocs в Ruby, в них есть одна особенность, которая часто забывается, а именно, Heredocs поддерживает ту же строковую шаблону, так как двойные цитируемые строки! Так что, как мы можем сделать это:

raise CircuitOpen, "Service #{@service} was unresponsive"

Мы можем сделать то же самое в более длинном куске текста с Heredoc:

raise CircuitOpen, <<~EOM
  The circuit breaker for the service #{@service.inspect} is open.

  This means that the service you are calling has been unavailable or has been timing out
  for some time, and the circuit breaker has opened to prevent your application from slowing down, as well as to protect the
  service you are calling from the thundering herd of requests once it recovers.
EOM

Обратите внимание, как я использую проверять Для шаблонов строки, так что буквальное значение переменной автоматически отображается в кавычках и визуально разделена (разграничена) от остальной части сообщения. Это облегчает отличить динамически сгенерированную часть сообщения от письменной прозы.

Усиление дисплея со структурированными данными

Часто ошибки вызваны определенным пользовательским входом. Поскольку мы можем включать произвольные программные строки в наших сообщениях об ошибках, ничто не мешает нам иметь соответствующий пользовательский ввод в сообщение об ошибке (если мы знаем, что вход может быть полезен). Мы можем сделать этот вход подходить для потребления человеком, используя что-то вроде Json.pretty_generate :

raise MyError, <<~EOM
  Fields were provided for validation which didn't match the schema. The input was:

  #{JSON.pretty_generate(params[:transaction_details]}
EOM

Например, в одном из приложений WERTANSFER у нас есть известное состояние сбоя, которое создает определенную картину недействительного ввода. Поскольку мы знаем, что эта ошибка возникает только перед лицом этого ввода, мы вводим его в сообщение об ошибке. Вот что это сообщение об ошибке в Appsignal, как выглядит:

Будьте осторожны с этим шаблоном, хотя: данные внутри вашего сообщения исключения подлежат законам защиты данных, как и любая другая личная информация.

Если вы делаете шаблон вашего ввода в сообщения об ошибках, вам может потребоваться убедиться, что вам разрешено отправлять его на такие услуги, как AppSignal. Поскольку данные находятся внутри сообщения об ошибке, он больше не может быть автоматически анонимным или смущим.

Вывод: то, что, Где и почему ошибок

Вы хотите, чтобы ваши ошибки сообщили вам Что происходит, где и почему они случаются в форме, которая требует как можно меньше расследования.

Долгое сообщение об ошибках — отличный способ добиться этого и предоставить вам значительные преимущества при небольшой стоимости UP-Front. Просто напишите это сообщение об ошибке!

Джулик Тарханов Является ли художник VFX Rogue и Ruby. Днем и ночью он притуивает рожок на WETRANSFER OSS REPOS, как Ziptricks. .

WETRANSFER является одним из наших долговременных пользователей. Узнайте больше о умных способах, которые они использовали Appsignal в нашем тематическом исследовании .

Оригинал: «https://dev.to/appsignal/improve-your-life-with-long-error-messages-eon»