Тысяча и одна ошибка



— Не будь как Шазерезада - экономь квоту —

TL;DR

Одна ошибка может случиться тысячу раз, но в Bugsnag достаточно сообщить о ней один раз за 15 минут.
Кто о чём, а вшивый о багах.

Подключил я намедни проект Laravel к Bugsnag для сбора ошибок в коде, дабы не проспать чего апокалиптического. Но апокалипсис устроил сам... 😈

Проект ворочает довольно приличными объёмами данных и в случае катаклизма Bugsnag быстро бы оброс репортами.

Сказано - сделано!

Буквально за ночь доступные квоты были израсходованы! Источник проблем оказался внешний, но лимиты от этого не увеличились. 🤔

Чтобы решить подобную проблему на будущее было решено немного притормозить отправку репортов.

Основные требования к решению:
— Единый механизм дросселирования для любых типов исключений;
— Легкое добавление нового типа репорта без изменения существующей логики;
— Возможность самостоятельно определять, какие ошибки считать одинаковыми;
— Единая точка настройки ограничений, без размазывания логики по всему проекту;
— Максимально использовать штатные возможности Laravel и избнжать вендорлок сервиса мониторинга;
— Ограничение частоты репортов не должно влиять на выполнение бизнес-логики или обработку самих исключений;

1. Готовим максимально простой интерфейс


interface ThrottledReport
{
public const int THROTTLE_MINUTES = 15;
public function throttleKey(): string;
public function throttleMinutes(): int;
}

Основная идея - это throttleKey. Именно он определяет, какие ошибки считать одинаковыми. А throttleMinutes - определяет на сколько притормозить отправку повторяющихся репортов.

2. Добавляем trait с реализацией таймера по умолчанию


trait HasReportThrottle
{
public function throttleMinutes(): int
{
return static::THROTTLE_MINUTES;
}
}

3. Далее подключаем обработку эксепшена в bootstrap


->withExceptions(function (Exceptions $exceptions): void {
$exceptions->throttle(function (Throwable $e) {
if ($e instanceof ThrottledReport) {
return Limit::perMinutes($e->throttleMinutes(), 1)
->by($e::class . ':' . $e->throttleKey());
}

return null; // остальные исключения без ограничений
});
})

Тут есть важный нюанс: троттлинг работает на уровне Laravel Exception Handler, поэтому подавленные репорты не попадут не только в Bugsnag, но и в стандартные логи приложения. Но для моего решения — это приемлемо.

И ещё момент — важно учесть, что лимит хранится в кэше, поэтому важно иметь настроенный механизм кэширования. Например, redis.

4. Создаём своё исключение

final class DoNotSpamException extends RuntimeException implements ThrottledReport
{
use HasReportThrottle;

public const int THROTTLE_MINUTES = 60;

public function throttleKey(): string
{
return 'my-unique-key-for-error';
}
}



5. И используем
report(new DoNotSpamException('Something went wrong'));

‼️ Но тут важно помнить — это решение уменьшает частоту сообщений об ошибках, а не частоту возникновения самих ошибок. О количестве и качестве ошибок заботимся сами! ☕️

#php #laravel #exception #throttling #backend #web #разработка
Views: 10
Open in MAX Report an inaccuracy

Report an inaccuracy

Describe what needs fixing. If you have a source, add a link.

You are leaving datool.ru

The link leads to an external website. datool.ru is not responsible for its content — check the address before entering passwords or payment details.

Redirecting in 10 s

Go