---
title: "Моніторинг та Аналітика"
description: "Health чек, перша сторона аналітика (включаючи personal_page_view), Web Vitals, структуроване логування і опціональний Docker Prometheus"
locale: "uk"
---
# Моніторинг та аналітика

> **Info**
> Відфільтруйте по **Засновник**/**Розробник** у боковому меню документації. Джерела моніторингу — `app/api/health`, `app/api/analytics/*`, `lib/logger.ts`, `public/scripts/analytics.js` + `RingAnalyticsBeacon`, і аналітичний UI адміністратора. Окремої сторінки `features/analytics` немає — ця стаття дає огляд аналітики по всій платформі Ring.

Ring Platform збирає **першу сторону телеметрії** у таблиці PostgreSQL JSONB, має **health endpoint для контейнерів**, та **структуровані серверні логи**. Зовнішній APM (Sentry, Vercel Analytics) інтегрується через змінні середовища, але не обов’язковий для основної роботи.

## Шари моніторингу (реалізовано фактично)

| Рівень | Механізм | Основний сигнал |
|--------|----------|----------------|
| **Liveness** | `GET /api/health` (+ `HEAD`) | Процес живий, попередження щодо оточення, пам’ять |
| **UX продуктивність** | `WebVitalsProvider` → `POST /api/analytics/web-vitals` | LCP, CLS, INP, TTFB, FCP |
| **Події продукту** | `analytics.js` + `RingAnalyticsBeacon` → `POST /api/analytics/app` | Сесії, завантаження сторінок, кастомні події (`analytics_events`) |
| **Персональні сторінки** | `recordPersonalPageView` → `personal_page_view` | Унікальні відвідування 24г/7д за ролями на `/{username}` |
| **Клієнтські помилки** | `POST /api/analytics/errors` | Stack trace, компонента, рівень серйозності |
| **Панель адміністратора** | `/admin/analytics` | `getPlatformAnalytics()` включно з `personalPages` |
| **Realtime підключення** | `/api/tunnel/ping`, `/api/tunnel/heartbeat` | Затримка тунелю / здоров'я сесії |
| **Серверні логи** | `lib/logger.ts` | JSON-рядки у stdout (`LOG_LEVEL`) |
| **Опціональна інфраструктура** | Docker-профіль `monitoring` | Prometheus + Grafana (локальний dev) |

### For founders

## Чому операторам важливо моніторити

Ring-клон поєднує **авторизацію**, **ринкові дані**, **платежі** і **сповіщення в реальному часі**. Баг часто проявляється як “сайт відкривається, але замовлення не синхронізуються”, а не як червона помилка. Унікальні відвідування персональної сторінки дозволяють зрозуміти, чи отримують власники довіру — при цьому власник сам не накручує собі лічильник.

### На що дивитися, не читаючи код

  
- **[Health endpoint](/docs/deployment/docker.md)** — Використовуйте `GET /api/health` у балансувальнику навантаження чи онлайн-чекері — якщо `503`, це деградація (часто бракує `AUTH_SECRET`).

  
- **[Адмін-аналітика](/docs/features/admin.md)** — **Admin → Analytics**: кількість користувачів, медіани Web Vitals, останні клієнтські помилки і personalPages (топові профілі, розподіл по ролях).

  
- **[Публічні профілі](/docs/features/public-profile.md)** — Власники бачать у віджеті на персональній сторінці унікальні відвідування за 24г/7д.

  
- **[Кореляція зі збереженням резервних копій](/docs/deployment/backup.md)** — Моніторинг покаже *коли* щось зламалось; резервні — *що* можна відновити.

### Типові сценарії тривог

- **Health → `degraded`** — після деплою втрачені важливі змінні; перевірте секрети до postgres.
- **Web Vitals з “poor” ростуть** — проблема з CDN, вагою зображень чи SSR; шукайте реліз-тег (`BUILD_DATE` / `GIT_COMMIT` у health JSON якщо вказано).
- **Стрибок у `analytics_errors`** — зламався клієнтський бандл або сторонній скрипт; можна подивитись у адмін-панелі.
- **Багато роз'єднань тунелю** — дивіться [Realtime transport](/docs/architecture/real-time.md); часто це edge/WSS або проксі, не база.

> **Tip**
> Визначте, **кому приходять тривоги** (оператор чи розробник) і **що в клоні вважається “падінням”**. Ring OSS не має готової інтеграції з PagerDuty; ви самі підключаєте health чек до свого провайдера.

### For developers

## Архітектура

```mermaid
flowchart LR
  Browser[Браузер / PWA]
  WV[WebVitalsProvider]
  Beacon[RingAnalyticsBeacon]
  Script["/scripts/analytics.js"]
  Profile["recordPersonalPageView"]
  API["/api/analytics/*"]
  ADB[analytics-db.ts]
  PG[(PostgreSQL JSONB)]

  Browser --> WV --> API
  Browser --> Beacon --> Script --> API
  Profile --> ADB
  API --> ADB --> PG
  Admin["/admin/analytics"] --> ADB
```

### Health check — `app/api/health/route.ts`

Повертає JSON: `status` (`healthy` | `degraded` | `unhealthy`), аптайм, пам’ять, статус `services.database` (`postgresql` чи `firebase`), Docker-блок якщо є. Якщо бракує `AUTH_SECRET` → `degraded` + HTTP **503**.

{`curl -sS https://your-clone.example/api/health | jq .

curl -I https://your-clone.example/api/health   # HEAD — 200 якщо працює`}

### Клієнтський маяк (перевірено)

| Компонент | Шлях |
|-----------|------|
| Скрипт | `public/scripts/analytics.js` — батчить у `POST /api/analytics/app` через `sendBeacon`/fetch; `window.ringAnalytics` |
| App Router glue | `components/providers/ring-analytics-beacon.tsx` — підключає скрипт; викликає `pageView` при зміні pathname/searchParams (недостатньо просто “hard load”) |
| Mount | `components/providers/app-client-shell.tsx` |

Легасі-скрипт `public/scripts/app-analytics.js` є в репозиторії, але **НЕ** використовується як SSOT — не документуйте його як живий.

### Поверхня API для аналітики

| Маршрут | Метод | Авторизація | Таблиця/Дані |
|---------|-------|-------------|--------------|
| `/api/analytics/web-vitals` | POST | Опціональна сесія | `web_vitals` |
| `/api/analytics/web-vitals` | GET | Адмін | Запит `web_vitals` або сумарно `?scope=platform` |
| `/api/analytics/app` | POST | Опціональна сесія | `analytics_events` |
| `/api/analytics/errors` | POST | Опціональна сесія | `analytics_errors` |
| `/api/analytics/errors` | GET | Адмін | Список помилок |
| `/api/analytics/device` | POST | Потрібна сесія | `user_device_telemetry` |
| `/api/analytics/platform-stats` | GET | Адмін | Лічильники: users, entities, opportunities |
| `/api/analytics/navigation` | POST | Опціональна сесія | Заглушка — `{ ok: true }`, без збереження |

Реалізація: `features/analytics/lib/analytics-db.ts` (`insertAnalyticsEventBatch`, `insertWebVitalsRecord`, `insertAnalyticsErrors`). Клієнтські Web Vitals: `components/providers/web-vitals-provider.tsx` — `useReportWebVitals` з `next/web-vitals` буферизує CLS, FCP, LCP, TTFB, INP в один POST із debounce (~1.5с, INP замість FID).

### Події персональної сторінки

| Компонент | Шлях |
|-----------|------|
| Тип події | `personal_page_view` |
| Записувач | `features/analytics/lib/personal-page-analytics.ts` → `recordPersonalPageView` |
| Сайт виклику | `app/[locale]/[username]/page.tsx` — пропускає власника |
| Віджет власника | `getPersonalPageViewStats` (`features/auth/services/personal-page-stats.ts`) |
| Адмін | `getPersonalPagePlatformStats` → `PlatformAnalyticsSummary.personalPages` |
| Ангажування | `personal_page_view` агрегується з `page_view` / `app_load` / `docs_page_view` у адмін-UI |

Алгоритм унікальних візитів: [Public Profile Pages](/docs/features/public-profile.md).

### Таблиці бази даних

Прописані у `data/schema.sql` та міграції `017_ring_analytics_schema.sql`:

- `analytics_events` — батчі клієнтської телеметрії **та** серверні `personal_page_view`
- `web_vitals` — пакети Core Web Vitals
- `analytics_errors` — клієнтський лог помилок

### Вимкнення збереження (конфіденційність/навантаження)

{`ANALYTICS_DISABLE_STORAGE=true`}

При цьому інгест-роути **приймають** дані, але ігнорують `DatabaseService` (`isAnalyticsStorageDisabled()`). Особисті візити також no-op.

### Структуроване логування

{`import { logger } from '@/lib/logger'

logger.info('Subscription created', { userId })

logger.warn('syncDiscovery: tunnel publish failed', { channel, error })

logger.error('Failed to create subscription', { userId, error })`}

Середовище: `LOG_LEVEL` (`debug` | `info` | `warn` | `error`; типово `info` у проді, `warn` у dev), `LOG_SILENT=true` для тиші. Вивід — JSON-рядки у stdout; у dev не пише очікувані помилки JWT/SSE.

### Опціональний зовнішній APM

Закоментовано в `env.local.template` / `docker.env.template`:

- `SENTRY_DSN` — інтеграція з Sentry Next.js (не увімкнено за умовчанням)
- `NEXT_PUBLIC_ANALYTICS_ID`, `VERCEL_ANALYTICS_ID` — тільки для Vercel-хостингу

### Realtime-проби

| Маршрут | Призначення |
|---------|-------------|
| `POST /api/tunnel/ping` | Аутентифікований pong + timestamp |
| `POST /api/tunnel/heartbeat` | keep-alive з'єднання |

Див. [Tunnel protocol](/docs/features/tunnel-protocol.md).

### Моніторинг cron/потоків

Маршрути cron (`/api/cron/*`) не працюють без `CRON_SECRET`. Наприклад: `GET /api/cron/email-analytics` запускає pipeline `email-analytics`.

### Опціональні Docker Prometheus + Grafana

{`docker compose --profile monitoring up -d`}

Сервіси: `ring-prometheus` (:9090), `ring-grafana` (:3001). Налаштування: `docker/prometheus/prometheus.yml`.

  Стандартний Prometheus-джоб у конфігу дивиться на `/api/metrics`, але **такий маршрут не реалізовано** — фактично скрапить `/api/health` як JSON (не у форматі Prometheus). Використовуйте цей профіль як стартовий шаблон.

### Точка входу для admin UI

Серверна сторінка: `app/[locale]/admin/analytics/page.tsx` — потребує `isPlatformAdmin`, вантажить `getPlatformAnalytics('7d')`, включаючи `personalPages`.

## Дотична документація

  
- [features/public-profile](/docs/features/public-profile.md) — Той самий workflow: персональна статистика переглядів і пропуск власника.

  
- [deployment/backup](/docs/deployment/backup.md) — Наступний крок: відновлення після інцидентів, що помітно через моніторинг.

  
- [deployment/performance](/docs/deployment/performance.md) — Див. також: налаштування Web Vitals та performance-операції.

  
- [deployment/environment](/docs/deployment/environment.md) — Залежить від: CRON_SECRET, LOG_LEVEL, ANALYTICS_DISABLE_STORAGE, опційний Sentry.

  
- [architecture/real-time](/docs/architecture/real-time.md) — Деталі: tunnel-протоколи і heartbeat поведінка.

  
- [features/admin](/docs/features/admin.md) — Наступний крок: точка входу в адмін-консоль /admin/analytics.
