Все записи
6 мин

Свой раздел «Ошибки» вместо Sentry: чтобы не сжигать рекламный бюджет вслепую

Building in Publicclaude codeкартара

Перед тем как лить платный трафик из Директа на Картару, я собрал в админке свой раздел «Ошибки», то есть self-hosted мониторинг того, на что натыкаются живые пользователи. Sentry не взял осознанно: проект в РФ, и принцип у меня простой — без облаков. Вся затея заняла один автономный цикл, спека-код-ревью, и сделал это Claude Code под моим управлением. Если совсем коротко, то я просто не хотел запускать рекламу в ситуации, когда баг на вебе виден только мне в docker-логах, а пользователю он виден как намертво сломанный экран, про который я узнаю в лучшем случае никогда.

Почему вообще зачесалось

Тут вот какая штука. Пока у тебя бесплатный трафик и десяток заходов в день, любой косяк ты в общем-то ловишь руками — сам тыкаешь, сам видишь, сам чинишь. А вот когда ты собираешься заплатить деньги за каждый клик, картинка меняется полностью, и меняется она неприятно. Представьте: человек кликнул по объявлению, зашёл, у него на каком-то шаге упал флоу, он закрыл и ушёл. В вашей аналитике это выглядит как «не сконвертился». То есть как будто продукт не зашёл, оффер слабый, цена не та, и вы начинаете крутить ручки маркетинга. А на самом деле там просто сломанная кнопка или эндпоинт вернул пятисотку, и вы платите за трафик, который физически не мог дойти до оплаты.

Вот это и есть та самая ловушка, ради которой я всё затеял. Молчаливый баг при платном трафике маскируется под «низкую конверсию», а не под «сломанный флоу». И ты сидишь, оптимизируешь воронку, которой нет, и сжигаешь бюджет вслепую. А деньги-то живые, не из воздуха.

Раньше у меня все ошибки жили только в docker-логах. Знаете, как это выглядит на практике? Чтобы понять, упало у кого-то что-то или нет, надо зайти на сервер, открыть логи нужного контейнера и глазами вычитывать поток. Когда заходов мало, ладно, переживёшь как-нибудь. А когда планируешь поток с рекламы, это просто не работает, ты физически не будешь сидеть в логах сутками. Нужна видимость прямо в админке, человеческая, чтобы открыл и сразу понял что происходит.

Почему не Sentry, хотя все берут Sentry

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

А ответ простой и упирается в две вещи. Первое — это РФ. С зарубежными облачными сервисами в нашей реальности постоянная история: то оплата не проходит, то доступ моргает, то завтра вообще отключат. И я не хочу строить видимость своих ошибок поверх инфраструктуры, которая в любой момент может стать недоступной по причинам, на которые я не влияю вообще никак. Второе — это мой давний принцип по всем проектам, без облаков там, где можно без облаков. Данные ошибок — это потенциально куски пользовательских данных, обрывки запросов, и гнать это куда-то наружу на чужие серверы мне не хочется. Пусть лежит у меня, в моей же базе, под моим же контролем.

Да, своё решение проще Sentry по фичам, тут я не спорю и не строю из себя что собрал убийцу Sentry. Мне и не нужен убийца. Мне нужна одна конкретная вещь — видеть ошибки, на которые натыкаются юзеры, прямо в админке, без походов в логи и без облаков. Такой же ход я уже делал, когда перенёс распознавание речи на self-host и завернул сырые ошибки в человеческий враппер. Как я сам сформулировал в тот момент: «Я просто не хочу чтобы ошибки на которые могут юзеры наткнуться были для нас невидимы». Вот и вся постановка задачи, ничего сверх.

Как это собиралось

Само по себе это не какая-то гигантская фича на неделю, и гнать тут я не буду. Это раздел в админке плюс механика записи ошибок в базу вместо одного только лога. Но я прогнал её полным циклом, как у меня заведено для всего, что трогает несколько слоёв сразу: сначала спека, что именно мы ловим и как показываем, потом код, потом параллельное ревью несколькими агентами. Claude Code написал реализацию, я оркестрировал процесс и принимал решения по спорным местам, а ревьюеры прошлись по безопасности и по логике. Мне важно было, чтобы в сам раздел ошибок случайно не утекли чувствительные данные пользователей, потому что одно дело видеть, что флоу упал, и совсем другое — тащить туда чьи-то персональные куски из тела запроса. Это как раз тот случай, когда self-hosted не отменяет аккуратности, а наоборот её требует, ведь теперь данные пишутся в новое место и за этим местом надо следить.

Если вам интересно, как у меня вообще устроен этот процесс «спека → код → ревью агентами», я про это уже отдельно писал на примере того, как за неделю докатил нумерологию в Картаре до прода, там та же механика, просто на другой фиче.

Маленькая деталь, которая меняет всё

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

Работает он ровно так, как вы и подумали. Появилась новая ошибка — рядом с пунктом меню зажёгся счётчик, и ты, как я сам же это описал, «сразу в меню видишь что есть уже что то там новое». Зашёл на страницу ошибок, посмотрел, счётчик сбросился. Никаких пушей, никакой почты, никаких внешних уведомлялок, которые опять же завязаны на чьи-то облака. Просто визуальный сигнал в интерфейсе, которым я и так пользуюсь каждый день. И вот эта мелочь превращает мёртвый раздел в живой инструмент, потому что теперь мне не надо помнить, что надо бы заглянуть в ошибки. Они сами говорят: эй, тут новое, посмотри.

Меня в этом подходе всегда подкупает, что хорошие приёмы переносятся между проектами почти бесплатно. Один раз придумал паттерн «бейдж с новым и сброс при заходе», и дальше он живёт у тебя во всех админках, ты его просто достаёшь из кармана. Это и есть нормальная окупаемость соло-разработки через ИИ — не делать каждый раз с нуля, а накапливать свои же решения и переиспользовать.

Что я из этого вынес

Главный вывод даже не технический, а про деньги и про честность с самим собой. Видимость ошибок — это не «функция для гиков, чтобы было красиво в логах», это прямая защита рекламного бюджета. Если вы собираетесь платить за трафик, вы обязаны сначала убедиться, что у вас нет невидимых дыр, в которые этот трафик утекает молча. Иначе вы платите за клики, оптимизируете воронку, которой нет, и в отчётах у вас будет ложь, красивая, аккуратная и совершенно бесполезная.

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

И третий, уже на выдохе. Эта штука, по сути, нужна была мне не чтобы что-то добавить в продукт, а чтобы перестать врать себе цифрами перед тем, как вложить деньги в рекламу. Я хотел открыть админку и за секунду понять: всё чисто или где-то юзеры спотыкаются. Теперь могу. А дальше уже можно и трафик лить, но хотя бы с открытыми глазами, а не вслепую.