# monitoring-error-tracking > Production monitoring навык для Telegram Mini App (SvelteKit + Express). Покрывает Sentry error tracking, custom metrics, performance monitoring, uptime checks, Telegram alerting, structured logging с pino, Grafana dashboards. Используется для observability и быстрого реагирования на проблемы в production. - Author: MyAppButik Dev - Repository: simvol2030/project-kliee - Version: 20260125182846 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/simvol2030/project-kliee - Web: https://mule.run/skillshub/@@simvol2030/project-kliee~monitoring-error-tracking:20260125182846 --- --- name: monitoring-error-tracking description: Production monitoring навык для Telegram Mini App (SvelteKit + Express). Покрывает Sentry error tracking, custom metrics, performance monitoring, uptime checks, Telegram alerting, structured logging с pino, Grafana dashboards. Используется для observability и быстрого реагирования на проблемы в production. --- # Навык: Monitoring & Error Tracking ## Описание Экспертный навык для настройки production monitoring и error tracking для Telegram Mini App с покрытием: - Sentry integration для error tracking (frontend + backend) - Custom metrics с Prometheus format - Performance monitoring (Web Vitals, API latency) - Uptime monitoring с health checks - Telegram alerting для критичных ошибок - Structured logging с pino - Grafana dashboards для визуализации метрик - Request tracing для debugging Используется для observability в production, быстрого обнаружения и устранения проблем, мониторинга SLA. --- ## Когда использовать - Production deployment Telegram Mini App - Настройка error tracking (Sentry, Rollbar) - Мониторинг метрик производительности - Alerting при критичных ошибках - Uptime monitoring - Performance optimization (Web Vitals) - Debugging production issues - SLA compliance tracking - Cost optimization (мониторинг usage) --- ## Основные возможности ### 1. Настроить Sentry для error tracking Интегрировать Sentry для автоматического отслеживания ошибок в frontend и backend. **Технологии**: @sentry/sveltekit, @sentry/node **Установка**: ```bash # Frontend (SvelteKit) npm install @sentry/sveltekit # Backend (Express) npm install @sentry/node @sentry/profiling-node ``` **Frontend integration (SvelteKit)**: ```typescript // src/hooks.client.ts import * as Sentry from '@sentry/sveltekit'; Sentry.init({ dsn: 'https://your-dsn@sentry.io/project-id', // Environment environment: import.meta.env.MODE, // Release tracking release: import.meta.env.VITE_APP_VERSION, // Sample rate (100% в dev, 10% в prod для экономии quota) tracesSampleRate: import.meta.env.DEV ? 1.0 : 0.1, // Replay sessions для debugging replaysSessionSampleRate: 0.1, replaysOnErrorSampleRate: 1.0, // Integrations integrations: [ new Sentry.BrowserTracing(), new Sentry.Replay({ maskAllText: false, blockAllMedia: false }) ], // Filter out specific errors ignoreErrors: [ 'ResizeObserver loop limit exceeded', 'Non-Error promise rejection captured' ], // Add user context beforeSend(event, hint) { // Telegram user info const telegramUser = window.Telegram?.WebApp?.initDataUnsafe?.user; if (telegramUser) { event.user = { id: telegramUser.id.toString(), username: telegramUser.username, ip_address: '{{auto}}' }; } return event; } }); ``` **Backend integration (Express)**: ```typescript // src/index.ts import * as Sentry from '@sentry/node'; import { nodeProfilingIntegration } from '@sentry/profiling-node'; Sentry.init({ dsn: process.env.SENTRY_DSN, environment: process.env.NODE_ENV, release: process.env.APP_VERSION, tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0, profilesSampleRate: 0.1, integrations: [ new Sentry.Integrations.Http({ tracing: true }), new Sentry.Integrations.Express({ app }), nodeProfilingIntegration() ], beforeSend(event, hint) { // Add user context from JWT if (event.request?.headers?.authorization) { // Parse JWT and add user info } return event; } }); // Request handler (must be first) app.use(Sentry.Handlers.requestHandler()); // Tracing handler app.use(Sentry.Handlers.tracingHandler()); // Routes app.use('/api', routes); // Error handler (must be last) app.use(Sentry.Handlers.errorHandler()); ``` **Использование** - см. scripts/sentry-init.ts для полного setup. **Best Practices**: - Используйте низкий sample rate в production (10%) для экономии quota - Добавляйте user context (Telegram user ID) - Фильтруйте benign errors (`ignoreErrors`) - Используйте Session Replay для критичных ошибок - Группируйте ошибки по release version - Настройте alerting в Sentry dashboard --- ### 2. Собирать custom metrics Собирать и экспортировать custom metrics для мониторинга бизнес-логики. **Технологии**: prom-client (Prometheus format) **Установка**: ```bash npm install prom-client ``` **Metrics setup**: ```typescript // src/monitoring/metrics.ts import { Registry, Counter, Histogram, Gauge } from 'prom-client'; // Registry export const register = new Registry(); // Default metrics (CPU, memory, etc) import { collectDefaultMetrics } from 'prom-client'; collectDefaultMetrics({ register }); // Custom metrics // Counter: монотонно растущее значение export const transactionsTotal = new Counter({ name: 'loyalty_transactions_total', help: 'Total number of transactions', labelNames: ['type', 'status', 'store_id'], registers: [register] }); // Histogram: распределение значений export const transactionAmount = new Histogram({ name: 'loyalty_transaction_amount', help: 'Transaction amount distribution', buckets: [100, 500, 1000, 5000, 10000, 50000], labelNames: ['store_id'], registers: [register] }); export const apiLatency = new Histogram({ name: 'http_request_duration_seconds', help: 'HTTP request latency', buckets: [0.1, 0.5, 1, 2, 5], labelNames: ['method', 'route', 'status_code'], registers: [register] }); // Gauge: значение которое может расти и падать export const activeConnections = new Gauge({ name: 'active_websocket_connections', help: 'Number of active WebSocket connections', registers: [register] }); export const queueSize = new Gauge({ name: 'offline_sync_queue_size', help: 'Number of pending offline transactions', labelNames: ['store_id'], registers: [register] }); ``` **Middleware для API latency**: ```typescript // src/middleware/metrics.ts import { Request, Response, NextFunction } from 'express'; import { apiLatency } from '../monitoring/metrics'; export const metricsMiddleware = (req: Request, res: Response, next: NextFunction) => { const start = Date.now(); res.on('finish', () => { const duration = (Date.now() - start) / 1000; // seconds apiLatency .labels(req.method, req.route?.path || req.path, res.statusCode.toString()) .observe(duration); }); next(); }; ``` **Metrics endpoint**: ```typescript // src/routes/metrics.ts import { Router } from 'express'; import { register } from '../monitoring/metrics'; const router = Router(); router.get('/metrics', async (req, res) => { res.set('Content-Type', register.contentType); res.end(await register.metrics()); }); export default router; ``` **Использование в бизнес-логике**: ```typescript import { transactionsTotal, transactionAmount } from '../monitoring/metrics'; async function createTransaction(params) { const result = await db.transaction(async (tx) => { // ... transaction logic }); // Record metrics transactionsTotal .labels(params.type, 'success', params.storeId) .inc(); transactionAmount .labels(params.storeId) .observe(params.amount); return result; } ``` **Best Practices**: - Используйте Counter для монотонно растущих значений (total transactions) - Используйте Histogram для распределений (latency, amount) - Используйте Gauge для текущих значений (queue size, connections) - Добавляйте labels для группировки (store_id, type, status) - Не создавайте слишком много unique label combinations (cardinality explosion) - Экспортируйте metrics на `/metrics` endpoint для Prometheus --- ### 3. Мониторить performance Отслеживать Web Vitals на frontend и API latency на backend. **Технологии**: web-vitals **Frontend (Web Vitals)**: ```typescript // src/lib/monitoring/webVitals.ts import { onCLS, onFID, onFCP, onLCP, onTTFB } from 'web-vitals'; import * as Sentry from '@sentry/sveltekit'; interface Metric { name: string; value: number; rating: 'good' | 'needs-improvement' | 'poor'; } function sendToAnalytics(metric: Metric) { // Send to Sentry Sentry.metrics.distribution(metric.name, metric.value, { tags: { rating: metric.rating } }); // Send to custom backend fetch('/api/analytics/web-vitals', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ metric: metric.name, value: metric.value, rating: metric.rating, url: window.location.pathname, userAgent: navigator.userAgent }) }).catch(console.error); } // Track Web Vitals export function initWebVitals() { onCLS(sendToAnalytics); // Cumulative Layout Shift onFID(sendToAnalytics); // First Input Delay onFCP(sendToAnalytics); // First Contentful Paint onLCP(sendToAnalytics); // Largest Contentful Paint onTTFB(sendToAnalytics); // Time to First Byte } ``` **Использование**: ```typescript // src/routes/+layout.svelte ``` **Backend (API Performance)**: ```typescript // Уже покрыто через apiLatency histogram в capability #2 // Дополнительно можно логировать slow requests: import { logger } from '../utils/logger'; export const slowRequestLogger = (req: Request, res: Response, next: NextFunction) => { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; // Log slow requests (>2 seconds) if (duration > 2000) { logger.warn({ duration, method: req.method, path: req.path, statusCode: res.statusCode }, 'Slow request detected'); } }); next(); }; ``` **Best Practices**: - Мониторьте все Core Web Vitals (CLS, FID, FCP, LCP, TTFB) - Отправляйте метрики в Sentry и custom backend - Логируйте slow requests (>2s) - Группируйте по URL path для анализа - Настройте alerting на degradation --- ### 4. Настроить uptime monitoring Health checks для мониторинга доступности приложения. **Health check endpoint** (уже создан в sveltekit-telegram-deployment skill): ```typescript // src/routes/health/+server.ts import type { RequestHandler } from './$types'; import { json } from '@sveltejs/kit'; import { db } from '$lib/server/db'; export const GET: RequestHandler = async () => { const health = { status: 'ok', timestamp: new Date().toISOString(), uptime: process.uptime(), checks: { database: false, redis: false } }; // Database check try { await db.execute(sql`SELECT 1`); health.checks.database = true; } catch (error) { health.status = 'degraded'; } // Redis check (if used) try { await redis.ping(); health.checks.redis = true; } catch (error) { health.status = 'degraded'; } const status = health.status === 'ok' ? 200 : 503; return json(health, { status }); }; ``` **External monitoring services**: 1. **UptimeRobot** (бесплатный): - URL: `https://yourdomain.com/health` - Interval: 5 минут - Alert: Email/Telegram при downtime 2. **Better Uptime** (платный): - Advanced health checks - Multi-region monitoring - Incident management 3. **Custom monitoring script**: ```typescript // scripts/uptime-monitor.ts import fetch from 'node-fetch'; import { sendTelegramAlert } from './telegram'; const HEALTH_URL = 'https://yourdomain.com/health'; const CHECK_INTERVAL = 60000; // 1 минута let consecutiveFailures = 0; async function checkHealth() { try { const response = await fetch(HEALTH_URL, { timeout: 5000 }); if (response.ok) { const data = await response.json(); if (data.status !== 'ok') { throw new Error(`Health check degraded: ${JSON.stringify(data.checks)}`); } consecutiveFailures = 0; console.log('Health check passed'); } else { throw new Error(`Health check failed: HTTP ${response.status}`); } } catch (error) { consecutiveFailures++; console.error('Health check error:', error); // Alert after 3 consecutive failures if (consecutiveFailures >= 3) { await sendTelegramAlert( `🚨 Service DOWN!\n\nConsecutive failures: ${consecutiveFailures}\nError: ${error.message}` ); } } } // Run check every minute setInterval(checkHealth, CHECK_INTERVAL); checkHealth(); // Initial check ``` **Best Practices**: - Health check должен проверять все критичные зависимости (DB, Redis) - Используйте external monitoring (не на том же сервере) - Настройте alerting после N consecutive failures (не первой ошибки) - Мониторьте не только HTTP 200, но и response content - Добавьте timeout для health check (5 секунд) --- ### 5. Настроить Telegram alerting Отправка уведомлений в Telegram при критичных ошибках. **Telegram bot setup**: ```typescript // src/monitoring/telegram.ts interface TelegramAlertConfig { botToken: string; chatId: string; } const config: TelegramAlertConfig = { botToken: process.env.TELEGRAM_ALERT_BOT_TOKEN!, chatId: process.env.TELEGRAM_ALERT_CHAT_ID! }; export async function sendTelegramAlert(message: string) { const url = `https://api.telegram.org/bot${config.botToken}/sendMessage`; try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: config.chatId, text: message, parse_mode: 'HTML', disable_web_page_preview: true }) }); if (!response.ok) { console.error('Telegram alert failed:', await response.text()); } } catch (error) { console.error('Telegram alert error:', error); } } // Alert templates export function formatErrorAlert(error: Error, context?: any) { return ` 🚨 Production Error Error: ${error.message} Stack: ${error.stack?.split('\n').slice(0, 5).join('\n')} Context: ${JSON.stringify(context, null, 2)} Time: ${new Date().toISOString()} `.trim(); } export function formatMetricAlert(metric: string, value: number, threshold: number) { return ` ⚠️ Metric Alert Metric: ${metric} Current: ${value} Threshold: ${threshold} Time: ${new Date().toISOString()} `.trim(); } ``` **Integration с error handler**: ```typescript // src/middleware/errorHandler.ts import { sendTelegramAlert, formatErrorAlert } from '../monitoring/telegram'; export const errorHandler = async (err: Error, req: Request, res: Response, next: NextFunction) => { // Log error logger.error({ err }, 'Request error'); // Send alert для критичных ошибок if (shouldAlert(err)) { await sendTelegramAlert(formatErrorAlert(err, { method: req.method, path: req.path, userId: req.user?.userId })); } // Response res.status(500).json({ error: 'Internal server error' }); }; function shouldAlert(err: Error): boolean { // Alert только для критичных ошибок const criticalErrors = [ 'DatabaseError', 'PaymentError', 'AuthenticationError' ]; return criticalErrors.some(type => err.name.includes(type)); } ``` **Metrics alerting**: ```typescript // src/monitoring/alerts.ts import { sendTelegramAlert, formatMetricAlert } from './telegram'; import { queueSize } from './metrics'; // Check metrics periodically setInterval(async () => { const metrics = await register.getMetricsAsJSON(); // Check offline queue size const queueMetric = metrics.find(m => m.name === 'offline_sync_queue_size'); if (queueMetric) { const maxValue = Math.max(...queueMetric.values.map(v => v.value)); if (maxValue > 100) { await sendTelegramAlert( formatMetricAlert('offline_sync_queue_size', maxValue, 100) ); } } // Check error rate // ... }, 5 * 60 * 1000); // Every 5 minutes ``` **Best Practices**: - Создайте отдельный bot для alerting - Используйте private Telegram channel для alerts - Фильтруйте alerts (только критичные ошибки) - Добавляйте context в alerts (user, endpoint, time) - Группируйте похожие alerts (rate limiting) - Используйте HTML formatting для читаемости --- ### 6. Настроить structured logging Structured logging с pino для удобного парсинга и анализа. **Logger setup** (уже создан в express-security-hardening skill): ```typescript // src/utils/logger.ts import pino from 'pino'; export const logger = pino({ level: process.env.LOG_LEVEL || 'info', formatters: { level: (label) => ({ level: label }) }, timestamp: pino.stdTimeFunctions.isoTime, redact: { paths: [ 'req.headers.authorization', 'req.body.password', 'req.body.cardNumber' ], censor: '***REDACTED***' } }); ``` **Request logging**: ```typescript // src/middleware/requestLogger.ts import { Request, Response, NextFunction } from 'express'; import { logger } from '../utils/logger'; export const requestLogger = (req: Request, res: Response, next: NextFunction) => { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; logger.info({ req: { method: req.method, url: req.url, headers: req.headers, remoteAddress: req.ip }, res: { statusCode: res.statusCode }, duration, userId: req.user?.userId }, 'HTTP request'); }); next(); }; ``` **Contextual logging**: ```typescript // Add request ID для трассировки import { randomUUID } from 'crypto'; export const requestIdMiddleware = (req: Request, res: Response, next: NextFunction) => { req.id = randomUUID(); res.setHeader('X-Request-Id', req.id); next(); }; // Use request ID в логах logger.info({ requestId: req.id, userId }, 'Processing transaction'); ``` **Log levels**: ```typescript // Fatal - процесс должен завершиться logger.fatal({ err }, 'Database connection lost'); // Error - ошибка обработана, но требует внимания logger.error({ err, userId }, 'Payment failed'); // Warn - потенциальная проблема logger.warn({ duration }, 'Slow query detected'); // Info - важная информация logger.info({ userId, amount }, 'Transaction created'); // Debug - детали для debugging logger.debug({ query }, 'Database query executed'); // Trace - очень детальная информация logger.trace({ headers }, 'Request headers'); ``` **Best Practices**: - Используйте JSON format для structured logs - Добавляйте request ID для трассировки - Редактируйте чувствительные данные (пароли, карты) - Используйте правильные log levels - Добавляйте context (userId, requestId, duration) - Используйте child loggers для модулей --- ### 7. Создать Grafana dashboards Визуализация метрик с Grafana для мониторинга в реальном времени. **Grafana setup**: 1. Install Grafana 2. Add Prometheus data source (URL: http://localhost:9090) 3. Import dashboard JSON (см. assets/grafana-dashboard.json) **Key panels для Telegram Mini App**: 1. **Transactions Overview**: - Query: `rate(loyalty_transactions_total[5m])` - Type: Graph - Panel: Transactions per second (grouped by type) 2. **Transaction Amount Distribution**: - Query: `histogram_quantile(0.95, loyalty_transaction_amount)` - Type: Stat - Panel: 95th percentile transaction amount 3. **API Latency**: - Query: `histogram_quantile(0.95, http_request_duration_seconds_bucket)` - Type: Heatmap - Panel: Request latency by endpoint 4. **Error Rate**: - Query: `rate(loyalty_transactions_total{status="error"}[5m])` - Type: Graph - Panel: Errors per second 5. **Offline Queue Size**: - Query: `offline_sync_queue_size` - Type: Gauge - Panel: Current queue size by store 6. **System Resources**: - Query: `process_cpu_percent`, `process_memory_usage_bytes` - Type: Graph - Panel: CPU/Memory usage **Alert rules**: ```yaml # grafana-alerts.yaml groups: - name: loyalty-app interval: 1m rules: - alert: HighErrorRate expr: rate(loyalty_transactions_total{status="error"}[5m]) > 0.1 for: 5m labels: severity: critical annotations: summary: High error rate detected - alert: HighAPILatency expr: histogram_quantile(0.95, http_request_duration_seconds_bucket) > 2 for: 5m labels: severity: warning annotations: summary: High API latency (p95 > 2s) - alert: LargeOfflineQueue expr: offline_sync_queue_size > 100 for: 10m labels: severity: warning annotations: summary: Large offline sync queue ``` **Best Practices**: - Группируйте панели по функциональности (Transactions, API, System) - Используйте правильные visualizations (Graph, Gauge, Heatmap) - Настройте alerts для критичных метрик - Добавляйте annotations для deployments - Используйте template variables для filtering (store_id) --- ## Monitoring Checklist ### Error Tracking - [ ] Sentry настроен (frontend + backend) - [ ] User context добавлен - [ ] Sample rate настроен (10% в production) - [ ] Session Replay включен для критичных ошибок - [ ] Alerting настроен в Sentry ### Metrics - [ ] Custom metrics определены - [ ] Metrics endpoint (/metrics) создан - [ ] Prometheus scraping настроен - [ ] Labels используются правильно (без cardinality explosion) ### Performance - [ ] Web Vitals отслеживаются - [ ] API latency мониторится - [ ] Slow requests логируются ### Uptime - [ ] Health check endpoint создан - [ ] External monitoring настроен (UptimeRobot) - [ ] Alerting при downtime настроен ### Alerting - [ ] Telegram bot создан - [ ] Critical errors отправляют alerts - [ ] Metric alerts настроены - [ ] Alert grouping настроен ### Logging - [ ] Structured logging (JSON) используется - [ ] Request ID добавлен - [ ] Sensitive data редактируется - [ ] Log levels используются правильно ### Dashboards - [ ] Grafana настроена - [ ] Dashboard создан - [ ] Alert rules настроены - [ ] Annotations для deployments добавлены --- **Версия навыка**: 1.0.0 **Последнее обновление**: 2025-10-24