Подключение Gotcha к Symfony: раздельный бэкенд и фронтенд

Gotcha принимает данные по протоколу приёма Sentry и по OTLP, поэтому подключение — это официальные Sentry SDK, нацеленные на ваш инстанс. Ничего специфичного для Gotcha в приложении не появляется: тот же SDK, что и с любым Sentry-совместимым приёмником, только DSN указывает на ваш сервер.

Разберём практический, а не «hello world» случай: приложение из двух частей — API-бэкенд на Symfony и отдельный фронтенд (SPA/классический JS), которые живут на разных доменах и общаются по API. Такая раскладка добавляет один нюанс — кросс-доменную отправку из браузера, — и его мы разберём отдельно.

Что будем подключать

СигналОткуда шлётсяЧто нужно
Ошибки (исключения)бэкенд Symfonyбандл sentry/sentry-symfony
Трейсинг (транзакции, спаны)бэкенд Symfonyтот же бандл, traces_sample_rate
Web Vitals, фронт-ошибкибраузер@sentry/browser
Метрикибэкенд (OTLP)HTTP-запрос на /v1/metrics
Аптаймсам Gotcha наружуHTTP-монитор, кода не требует
АлертыGotchaканал (Telegram/webhook/email) в UI

Ошибки и трейсинг с бэкенда, Web Vitals с фронта, аптайм — снаружи. Три независимых источника, каждый шлёт в один и тот же проект Gotcha по его DSN.

Где взять DSN

После создания проекта Gotcha перекидывает на страницу «Подключение» (/projects/<id>/setup); вернуться можно кнопкой «Подключение SDK». DSN выглядит так:

https://<public_key>@gotcha.example.com/<project_id>

Один и тот же DSN используют и бэкенд, и браузер — public_key в нём публичен по замыслу. Держите его в переменной окружения: переезд на другой инстанс (например, с локалки на VPS) сведётся к смене одной строки.

Бэкенд: Symfony

composer require sentry/sentry-symfony

Рецепт Flex по умолчанию включает бандл только в prod и без трейсинга. Для self-hosted-стенда удобнее держать его активным во всех окружениях, но по наличию SENTRY_DSN (пусто = SDK выключен, полный no-op), и включить трейсинг через env. config/packages/sentry.yaml:

sentry:
    dsn: '%env(SENTRY_DSN)%'
    options:
        # Ненулевой sample-rate включает трейсинг производительности.
        traces_sample_rate: '%env(float:SENTRY_TRACES_SAMPLE_RATE)%'
        environment: '%kernel.environment%'
        # 404/405 — обычный веб-шум (сканеры, битые ссылки), не ошибки приложения.
        ignore_exceptions:
            - 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'
            - 'Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException'

Регистрируем бандл во всех окружениях (config/bundles.php):

Sentry\SentryBundle\SentryBundle::class => ['all' => true],

И задаём переменные (.env / прод-окружение):

SENTRY_DSN=https://<public_key>@gotcha.example.com/<project_id>
SENTRY_TRACES_SAMPLE_RATE=0.2   # ошибки шлются всегда; трейсы — 20% запросов

Дальше бандл ловит необработанные исключения сам. Проверить можно временным роутом, который бросает исключение, или \Sentry\captureMessage('проверка') — событие появится в разделе «Проблемы».

Про ignore_exceptions. Без него NotFoundHttpException летит в Gotcha как ошибка, и каждый скан или битая ссылка засоряет issues. Игнор клиентских 404/405 оставляет в потоке только реальные ошибки приложения.

Фронтенд: отдельный домен и кросс-доменная отправка

Фронтенд — отдельное приложение на своём домене (скажем, app.example.com), а Gotcha на gotcha.example.com. Браузерный SDK будет слать телеметрию на чужой origin, и это ключевое отличие от бэкенда, который шлёт server-to-server без всяких CORS.

Если сборщика у фронта нет (классический JS), соберите самодостаточный бандл @sentry/browser любым бандлером, например esbuild:

npm i @sentry/browser
npx esbuild <(echo "export * from '@sentry/browser'") \
  --bundle --minify --format=iife --global-name=Sentry \
  --outfile=public/js/sentry.min.js

И инициализируйте (в <head> или в начале скриптов страницы):

<script src="/js/sentry.min.js"></script>
<script>
  Sentry.init({
    dsn: "https://<public_key>@gotcha.example.com/<project_id>",
    integrations: [Sentry.browserTracingIntegration()],
    tracesSampleRate: 0.2,
  });
</script>

browserTracingIntegration сам снимает Web Vitals (LCP, CLS, INP, FCP, TTFB) и привязывает их к транзакции загрузки страницы.

Про CORS. Браузер из app.example.com шлёт POST на gotcha.example.com — это кросс-доменный запрос. Приёмник Gotcha отвечает CORS-заголовками и обрабатывает preflight (OPTIONS), так что браузерный SDK шлёт напрямую, без прокси. DSN (public key) публичен, поэтому приёмник разрешает любой origin — как и облачный приёмник Sentry.

Если ваш приёмник по какой-то причине недоступен для браузера напрямую (строгий сетевой периметр, блокировки), Sentry SDK умеет слать через tunnel — POST на ваш же домен, а бэкенд форвардит в Gotcha. Для типовой установки это не нужно: прямая отправка проще и не грузит бэкенд.

Метрики (по желанию)

Бизнес-метрики шлются по OTLP: POST на /v1/metrics с заголовком Authorization: Bearer <public_key> и телом OTLP JSON. Из Symfony это разовая console-команда (можно повесить в cron) или любой HTTP-клиент. Подробнее — в документации по метрикам.

Аптайм: без единой строки в приложении

Аптайм не требует правок в коде — Gotcha сам ходит на публичный URL снаружи. В проекте: Аптайм → Новый монитор → HTTP, URL вашего сайта, интервал и пороги отказа/восстановления. Инциденты, SSL-алерты и публичная status-страница — из коробки. Подробнее — Аптайм.

Алерты

В разделе «Оповещения» правила (новый issue, регрессия, всплеск) уже включены; остаётся добавить канал доставки — Telegram, webhook или email (последний требует SMTP). Каналы привязываются и к аптайм-мониторам, чтобы падение сайта тоже прилетало в уведомление. Подробнее — Алерты.

Переезд на прод — смена одной переменной

Весь смысл env-driven конфигурации: и бэкенд, и браузер берут DSN из окружения. Поднимаете Gotcha на VPS с реальным доменом — меняете SENTRY_DSN (и, для фронта, строку в Sentry.init), больше ничего. Код приложения при этом не меняется вовсе.

Итог

Дальше — документация, установка и раздел подключения SDK.