Skip to content

Логирование и Алертинг

Обзор системы мониторинга

Система мониторинга использует Unified Trace ID для отслеживания запросов через все сервисы:

typescript
// Gateway пробрасывает trace_id
app.use("*", async (c, next) => {
	const traceId = c.req.header("x-trace-id") || crypto.randomUUID();
	c.header("x-trace-id", traceId);
	await next();
});

// Service Binding получает trace_id из headers
const request = new Request(c.req.raw);
request.headers.set("x-trace-id", traceId);
const response = await sofa.fetch(request);

Это позволяет отследить запрос от Gateway через все интеграции и сервисы.


Просмотр логов в Cloudflare Dashboard

Открытие логов

  1. Перейти в Cloudflare Dashboard
  2. Выбрать Workers and Pages (слева в меню)
  3. Выбрать интеграцию (например, integ-sofa-dev)
  4. Нажать вкладку Logs (справа)

Должны увидеть список логов в реальном времени.

Фильтрация логов

Все логи выводятся в JSON формате, что позволяет их искать и фильтровать:

Поиск по уровню ошибки:

"level":"error"

Поиск по контексту:

"context":"webhook"

Поиск по Trace ID:

"traceId":"550e8400-e29b-41d4-a716-446655440000"

Поиск по сообщению об ошибке:

"message":"Rate limit exceeded"

Поиск по действию:

"action":"init"

Поиск HTTP ошибок:

"httpStatus":400

Поиск ошибок конкретного внешнего API:

"httpUrl":"api.nethunt.com"

Примеры поиска в логах

Найти все ошибки в интеграции:

"level":"error"

Найти все ошибки конкретного обработчика:

"level":"error" "context":"webhook"

Найти все события по одному трассе (для дебага):

"traceId":"550e8400-e29b-41d4-a716-446655440000"

Найти все события по одному действию:

"action":"init"

Найти HTTP ошибки по статус коду:

"httpStatus":400

Найти ошибки при запросах к внешнему API:

"httpStatus":500 "httpUrl":"api.nethunt.com"

Структура логов

LOG_LEVEL

Уровень логирования настраивается через переменную LOG_LEVEL в wrangler.toml ([vars]):

LOG_LEVELВидимые уровниКогда
debugdebug, info, warn, errorpnpm debug <target> — локальная отладка
infoinfo, warn, errorpnpm start <target> (по умолчанию), CF prod
warnwarn, errorМинимальный вывод
errorerrorТолько ошибки

Два источника логов

1. Trace-система (@happ-integ/trace) — для handlers:

  • Используется через ctx.log, step.run(), ctx
  • Автоматически добавляет traceId, handler name, span timing
  • LOG_LEVEL фильтрует step :input/:output (debug) и другие события

2. Logger (@happ-integ/logger) — для packages и gateway:

  • Используется через new Logger("service-name")
  • Формат зависит от режима: JSON (prod) или pretty console (local)

Формат логов (prod / CF Observability)

Все логи в production выводятся в JSON формате:

json
{
	"level": "debug|info|warn|error",
	"handler": "handler_name",
	"message": "описание события",
	"traceId": "tr_m1abc123_xyz789",
	"timestamp": "2024-01-01T00:00:00.000Z",
	"durationMs": 145,
	"error": "error message (только для ошибок)",
	"stack": "stack trace (только для ошибок)",
	"httpStatus": 400,
	"httpUrl": "https://api.example.com/endpoint",
	"httpMethod": "POST",
	"httpResponseBody": "{\"error\":\"Invalid request\"}",
	"httpRequestBody": {"field": "value"},
	"...additional_data": "любые дополнительные поля"
}

Логи из Logger (packages) имеют поле service вместо handler:

json
{
	"level": "error",
	"service": "redis",
	"message": "get: Failed to get key \"user:123\"",
	"timestamp": "2024-01-01T00:00:00.000Z",
	"error": "Connection refused",
	"stack": "Error: Connection refused..."
}

Ключевые поля:

ПолеОписание
levelУровень: debug, info, warn, error
handler / serviceИмя обработчика (trace) или сервиса (Logger)
messageОписание события
traceIdУникальный идентификатор запроса для корреляции
timestampISO время события
durationMsВремя выполнения (для timing логов)
errorТекст ошибки (только для ошибок)
stackStack trace ошибки (только для ошибок)
httpStatusHTTP статус код (только для HTTP ошибок)
httpUrlURL запроса (только для HTTP ошибок)
httpMethodHTTP метод: GET, POST, PUT, DELETE (только для HTTP ошибок)
httpResponseBodyТело ответа от сервера (только для HTTP ошибок, до 1000 символов)
httpRequestBodyТело запроса (только для HTTP ошибок)

Используемые функции логирования

В обработчиках используйте ctx.log из контекста (автоматически включает traceId):

typescript
// В handler доступен ctx.log с автоматическим traceId
export const myHandler = defineHandler<IMyPayload, IMyResponse>({
	name: "my-handler",
	endpoint: "POST /my-endpoint",
	handler: async (ctx) => {
		// Информационное сообщение
		ctx.log.info("Starting processing", { userId: ctx.payload.userId });

		// Ошибки
		ctx.log.error("Something failed", error, { additionalData: "value" });

		// Измерение времени выполнения
		const operationStart = Date.now();
		await someOperation();
		ctx.log.duration("operation_completed", operationStart, { operationType: "db_query" });

		return { success: true };
	},
});

Структура логов:

json
{
	"level": "info",
	"handler": "my-handler",
	"message": "Starting processing",
	"traceId": "tr_m1abc123_xyz789",
	"timestamp": "2024-01-01T12:00:00.000Z",
	"userId": "123"
}

Формат traceId: tr_{timestamp_base36}_{random_8chars} — генерируется автоматически если не передан в заголовке x-trace-id.

Примеры использования логирования

В обработчике (рекомендуемый способ):

typescript
export const initHandler = defineHandler<IInitPayload, IInitResponse>({
	name: "init",
	endpoint: "POST /init",
	handler: async (ctx) => {
		// ctx.log автоматически содержит traceId и имя handler
		ctx.log.info("Starting initialization", { companyId: ctx.payload.companyId });

		if (!ctx.payload.companyId) {
			throw new Error("companyId is required");
		}

		// Измерение времени операций
		const dbStart = Date.now();
		await ctx.db.init();
		ctx.log.duration("db_init_completed", dbStart);

		ctx.log.info("Initialization completed successfully", {
			companyId: ctx.payload.companyId,
		});

		return { success: true };
	},
});

Автоматические логи:

Фреймворк автоматически логирует:

  • webhook_received — при получении webhook
  • webhook_accepted — после успешной обработки webhook (с durationMs)
  • handler_completed — после выполнения handler (с durationMs и status)

Пример автоматического лога:

json
{
	"level": "info",
	"handler": "init",
	"message": "handler_completed",
	"durationMs": 145,
	"traceId": "tr_m1abc123_xyz789",
	"timestamp": "2024-01-01T12:00:00.145Z",
	"status": "success"
}

Алерты и уведомления

Какие алерты настроены

В текущей настройке активен Workers Error Alert:

  • Тип: Workers Error
  • Триггер: Любая необработанная ошибка в Worker
  • Назначение: Slack канал #alerts-integ
  • Формат сообщения: Автоматически от Cloudflare

Пример сообщения в Slack:

⚠️ Workers Error Alert
━━━━━━━━━━━━━━━━━━━━━━━━━
Worker: integ-sofa-dev
Error: phone_number is required
Stack: Error: phone_number is required
    at handler (integrations/sofa/src/handlers/webinar-call-originate.ts:41:10)
    at processRequest (integrations/sofa/src/index.ts:12:15)
Timestamp: 2024-01-01 12:00:00 UTC

Как реагировать на алерты

Когда приходит алерт в Slack:

  1. Прочитать сообщение об ошибке — обычно оно содержит:

    • Название Worker (например, integ-sofa-dev)
    • Текст ошибки
    • Stack trace
    • Время ошибки
  2. Открыть логи в Cloudflare Dashboard:

    • Перейти в Workers and Pagesinteg-sofa-devLogs
    • Поискать по времени из алерта или по тексту ошибки
  3. Найти полный контекст:

    • В логах найти JSON логи с более подробной информацией
    • Использовать traceId если есть для отслеживания всего запроса
  4. Проверить код обработчика:

    • Проверить handler, который упоминается в ошибке
    • Убедиться что все входные параметры валидны
  5. Отправить фикс:

    • Исправить код
    • Задеплоить интеграцию
    • Убедиться что ошибка больше не появляется

Дополнительные алерты (опционально)

Можно добавить алерты на другие события:

  • Rate Limiting — часто превышается лимит запросов
  • High Error Rate — > 5% ошибок за 5 минут
  • Slow Requests — > 3 сек за 5 минут

Смотрите раздел Настройка алертов в SETUP.md


Дебаг по Trace ID

Как работает Trace ID

Каждый запрос получает уникальный Trace ID:

1. Запрос → Gateway (генерирует traceId или берет из x-trace-id header)
2. Gateway пробрасывает traceId через x-trace-id header в Service Bindings
3. Интеграция извлекает traceId из header или генерирует новый
4. Интеграция логирует traceId со всеми событиями
5. Handler execution содержит traceId для продолжения трассировки
6. Результат: все логи одного запроса имеют один traceId

Формат traceId: tr_{timestamp_base36}_{random_8chars}

Пример: tr_m1abc123_xyz789

Поиск запроса по Trace ID

В Cloudflare Dashboard:

  1. Открыть логи интеграции: Workersinteg-sofa-devLogs
  2. В поле поиска ввести: "traceId":"tr_m1abc123_xyz789"
  3. Должны увидеть все логи этого запроса

Пример JSON лога с traceId:

json
{
	"level": "error",
	"handler": "init",
	"traceId": "tr_m1abc123_xyz789",
	"message": "handler_failed",
	"error": "companyId is required",
	"timestamp": "2024-01-01T12:00:00.000Z",
	"stack": "Error: companyId is required..."
}

Пример лога HTTP ошибки (при обращении к внешнему API):

json
{
	"level": "error",
	"handler": "sync-contacts",
	"traceId": "tr_m1abc123_xyz789",
	"message": "nethunt.updateRecord:end",
	"error": "HTTP 400: {\"error\":\"Field not found\"}",
	"timestamp": "2024-01-01T12:00:00.000Z",
	"httpStatus": 400,
	"httpUrl": "https://nethunt.com/api/v1/zapier/record/123",
	"httpMethod": "POST",
	"httpResponseBody": "{\"error\":\"Field not found\"}",
	"httpRequestBody": {"fieldActions": {"Комментарій": {"add": "..."}}}
}

Это позволяет видеть полный контекст HTTP ошибки: какой URL, какой метод, что отправляли и что получили в ответ.

Связь логов Gateway и интеграций

Когда вы видите ошибку в интеграции, её traceId позволяет найти соответствующие логи в Gateway:

Запрос поступает:
  POST /sofa/webhook/webinar-call-originate

  Gateway логирует с traceId="xyz"

  Gateway вызывает интеграцию через Service Binding

  Интеграция логирует с тем же traceId="xyz"

  Результат: оба сервиса имеют логи с одинаковым traceId

Для отслеживания полной цепочки:

  1. Найти логи в интеграции с нужным traceId
  2. Пойти в Gateway логи
  3. Искать там тот же traceId
  4. Видеть полный путь запроса

Logpush - архивирование логов

Настройте Logpush для отправки логов в R2 bucket или другое хранилище:

bash
# Создать R2 bucket
wrangler r2 bucket create integ-logs-archive

# Настроить Logpush через Cloudflare API
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/logpush/jobs" \
  -H "Authorization: Bearer {api_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "{account_id}",
    "enabled": true,
    "frequency": "low",
    "dataset": "workers_trace_events",
    "destination_conf": "s3://r2-bucket-endpoint/integ-logs",
    "ownership_challenge": "challenge"
  }'

Логи архивируются ежедневно в R2 для долгосрочного хранения.


Метрики для отслеживания

Error Rate

Alert: > 5% за 5 минут → Slack

Query: (count(errors) / count(total_requests)) * 100

Как проверить вручную:

  1. Cloudflare Dashboard → Workers → Logs
  2. Посчитать количество логов с "level":"error"
  3. Поделить на общее количество логов

Latency P99

Alert: > 3 сек за 5 минут → Slack

Target: < 1 сек для обычных запросов

Отслеживание: Смотреть duration в логах интеграции

Integration Health

Alert: Service Down → Slack

Check: /health endpoint каждые 30 сек

bash
# Проверить здоровье Gateway
curl https://integ.happ.tools/health

# Проверить здоровье интеграции через Gateway
curl -H "x-access-token: TOKEN" https://integ.happ.tools/sofa/health

Grafana Dashboards (опционально)

Dashboard 1: Overview

  • Total requests per integration
  • Error rate trend
  • Average latency
  • Integration health status

Dashboard 2: Per-Integration Details

  • Sofa-specific metrics
  • Request breakdown by handler
  • Error distribution

Dashboard 3: Errors & Alerts

  • Error log viewer (searchable by traceId)
  • Error rate timeline
  • Top error types
  • Failed requests with stack traces

Быстрый старт мониторинга

1. Первое деплоение

bash
cd integrations/sofa
pnpm build
pnpm deploy:dev

2. Проверить логи

  • Dashboard → Workers → integ-sofa-dev → Logs
  • Должны видеть JSON логи в реальном времени

3. Проверить алерты

  • Отправить запрос с ошибкой
  • Должно придти уведомление в Slack

4. Регулярный мониторинг

  • Ежедневно: проверять наличие ошибок в логах
  • По алертам: реагировать на сообщения в Slack
  • Еженедельно: смотреть тренд ошибок и latency

Полезные ссылки