У меня есть приложение Rails 5, использующее ворон-рубин для отправки исключений в Sentry, который затем отправляет предупреждения в наш Slack.
Raven.configure do |config|
config.dsn = ENV['SENTRY_DSN']
config.environments = %w[ production development ]
config.excluded_exceptions += []
config.async = lambda { |event|
SentryWorker.perform_async(event.to_hash)
}
end
class SentryWorker < ApplicationWorker
sidekiq_options queue: :default
def perform(event)
Raven.send_event(event)
end
end
Для наших заданий Sidekiq нормально генерировать исключения и повторять попытки. В основном это периодические ошибки API и тайм-ауты, которые устраняются сами по себе за несколько минут. Sentry послушно отправляет эти ложные сигналы в наш Slack.
Я уже добавил retry_count
в вакансии. Как я могу запретить Sentry отправлять исключения с retry_count <N в Slack, продолжая при этом предупреждать о других исключениях? Пример, о котором не следует предупреждать, будет иметь дополнительный контекст, подобный этому:
sidekiq: {
context: Job raised exception,
job: {
args: [{...}],
class: SomeWorker,
created_at: 1540590745.3296254,
enqueued_at: 1540607026.4979043,
error_class: HTTP::TimeoutError,
error_message: Timed out after using the allocated 13 seconds,
failed_at: 1540590758.4266324,
jid: b4c7a68c45b7aebcf7c2f577,
queue: default,
retried_at: 1540600397.5804272,
retry: True,
retry_count: 2
},
}
Каковы плюсы и минусы того, чтобы вообще не отправлять их в Sentry, а не отправлять их в Sentry, но не получать оповещения?
@MarkusUnterwaditzer Как часто это происходит в целом, поэтому я хочу продолжать отправлять их в Sentry, но не получать предупреждения. Я не могу контролировать, насколько ненадежны API. Я просто должен это компенсировать. Одна или две попытки выполнить задание - это нормально. В пять мы хотим провести расследование.
Я опубликовал два обходных пути для этого. Я не совсем уверен, хорошая ли это идея.
Возможный дубликат Количество повторных попыток Sidekiq в работе
Это не является частью рабочего класса намеренно: github.com/mperham/sidekiq/issues/845 Используйте промежуточное программное обеспечение клиента: stackoverflow.com/questions/23065578/sidekiq-retry-count-in- задание и medium.com/appaloosa-store-engineering/…
@LukasEklund Я уже добавил retry_count, спасибо. Проблема больше в Sentry, чем в Sidekiq.
Вы можете отфильтровать все событие, если retry_count <N (может быть выполнено внутри этого sidekiq worker, который вы разместили). Вы потеряете данные о том, как часто это происходит без предупреждения, но сами предупреждения не будут слишком шумными.
class SentryWorker < ApplicationWorker
sidekiq_options queue: :default
def perform(event)
retry_count = event.dig(:extra, :sidekiq, :job, retry_count)
if retry_count.nil? || retry_count > N
Raven.send_event(event)
end
end
end
Другая идея - установить другой отпечаток пальца в зависимости от того, повторная попытка или нет. Нравится:
class MyJobProcessor < Raven::Processor
def process(data)
retry_count = event.dig(:extra, :sidekiq, :job, retry_count)
if (retry_count || 0) < N
data["fingerprint"] = ["will-retry-again", "{{default}}"]
end
end
end
См. https://docs.sentry.io/learn/rollups/?platform=javascript#custom-grouping
Я не проверял это, но это должно разделить ваши проблемы на две, в зависимости от того, будет ли sidekiq повторять их. Затем вы можете игнорировать одну группу, но все равно можете просматривать ее, когда вам понадобятся данные.
Спасибо за Ваш ответ. Я понимаю, что делает процессор. Что мне делать на стороне Sentry?
@Schwern Я не понимаю вопроса. Вы просите разъяснений по последнему предложению?
Я понимаю, что он добавляет отпечаток пальца, хотя не совсем уверен, что он делает. Я не могу найти, как использовать этот отпечаток пальца для управления предупреждениями на Sentry. sentry.io/settings/<team>/<project>/alerts/rules/… У меня есть An event's tags match {key} {comparison} {value}
, так что, возможно, я могу добавить will-retry
в качестве тега.
Конечно, вы также можете добавить его как тег и использовать его для настройки оповещения. Думаю, это лучшая идея. С отпечатком пальца у вас будет отдельная проблема, которую вы можете просто отключить. Нет конфигурации предупреждений.
Думаю, теперь я понимаю. Большое спасибо!
Резюме
Вариант, который хорошо сработал для меня, - это настройка Часовой should_capture
вместе с sidekiq_retries_exhausted
Sidekiq с настраиваемым атрибутом исключения.
Подробности
1а. Добавить настраиваемый атрибут
К исключению можно добавить настраиваемый атрибут. Вы можете определить это для любого класса ошибки с помощью attr_accessor
:
class SomeError
attr_accessor :ignore
alias ignore? ignore
end
1b. Спасите ошибку, установите настраиваемый атрибут и повторно поднимите
def perform
# do something
rescue SomeError => e
e.ignore = true
raise e
end
should_capture
should_capture
позволяет фиксировать исключения, когда они соответствуют определенным критериям. Ему передается исключение, по которому вы можете получить доступ к настраиваемому атрибуту.
config.should_capture { |e| !e.ignore? }
В зависимости от используемой версии Sidekiq есть 2 способа определить поведение, которое должно произойти при завершении задания. Если вы хотите применить глобально и иметь sidekiq v5.1 +, вы можете использовать обработчик смерти. Если вы хотите обратиться к конкретному работнику или у вас версия ниже 5.1, вы можете использовать sidekiq_retries_exhausted
.
sidekiq_retries_exhausted { |_job, ex| ex.ignore = false }
У меня это не работает, потому что исключение не имеет метода ignore=
. Исключение NoMethodError: неопределенный метод ignore='
@Maros Я добавил пример кода и дополнительные пояснения к своему ответу. Вы можете установить attr_accessor
на свой класс ошибки (или на StandardError).
Но что, если ошибка определяется библиотекой? Я должен был исправить это как обезьяну
Более чистый подход, если вы пытаетесь игнорировать исключения, принадлежащие определенному классу, - это добавить их в свой файл конфигурации.
config.excluded_exceptions += ['ActionController::RoutingError', 'ActiveRecord::RecordNotFound']
В приведенном выше примере исключения, которые Rails использует для генерации ответов 404, будут подавлены.
Дополнительные параметры конфигурации см. В документации.
Спасибо, но речь идет об условном исключении исключений, а не целых классов исключений.
Я думаю, что вы хотите отслеживать, как часто эта ошибка возникает в целом, а не если она все еще возникает после n-й попытки.