Мониторинг системы
Комплексное руководство по мониторингу платформы маркетплейсов.
Обзор мониторинга
Ключевые метрики
- Производительность: время отклика, пропускная способность
- Доступность: uptime, health checks
- Ресурсы: CPU, память, диск, сеть
- Бизнес-метрики: количество заказов, конверсия, доходы
- Безопасность: попытки атак, аномальная активность
Prometheus + Grafana
Установка Prometheus
# docker-compose.monitoring.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
grafana:
image: grafana/grafana:latest
ports:
- "3001:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
node-exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
volumes:
prometheus_data:
grafana_data:
Конфигурация Prometheus
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'marketplace-app'
static_configs:
- targets: ['app:3000']
metrics_path: '/metrics'
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
- job_name: 'redis'
static_configs:
- targets: ['redis-exporter:9121']
Метрики приложения
Express.js метрики
const prometheus = require('prom-client');
// Создание метрик
const httpRequestDuration = new prometheus.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10]
});
const httpRequestsTotal = new prometheus.Counter({
name: 'http_requests_total',
help: 'Total number of HTTP requests',
labelNames: ['method', 'route', 'status_code']
});
const activeConnections = new prometheus.Gauge({
name: 'active_connections',
help: 'Number of active connections'
});
// Middleware для сбора метрик
const metricsMiddleware = (req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = (Date.now() - start) / 1000;
const route = req.route ? req.route.path : req.path;
httpRequestDuration
.labels(req.method, route, res.statusCode)
.observe(duration);
httpRequestsTotal
.labels(req.method, route, res.statusCode)
.inc();
});
next();
};
app.use(metricsMiddleware);
// Endpoint для метрик
app.get('/metrics', (req, res) => {
res.set('Content-Type', prometheus.register.contentType);
res.end(prometheus.register.metrics());
});
Бизнес-метрики
// Метрики заказов
const ordersTotal = new prometheus.Counter({
name: 'orders_total',
help: 'Total number of orders',
labelNames: ['marketplace_id', 'status']
});
const orderValue = new prometheus.Histogram({
name: 'order_value_amount',
help: 'Order value distribution',
labelNames: ['marketplace_id', 'currency'],
buckets: [10, 50, 100, 500, 1000, 5000, 10000]
});
const activeMarketplaces = new prometheus.Gauge({
name: 'active_marketplaces_total',
help: 'Number of active marketplaces'
});
// Использование в коде
app.post('/api/orders', async (req, res) => {
try {
const order = await createOrder(req.body);
// Обновление метрик
ordersTotal.labels(order.marketplaceId, 'created').inc();
orderValue.labels(order.marketplaceId, order.currency).observe(order.amount);
res.json(order);
} catch (error) {
ordersTotal.labels(req.body.marketplaceId, 'failed').inc();
res.status(500).json({ error: error.message });
}
});
Dashboards Grafana
Dashboard производительности
{
"dashboard": {
"title": "Marketplace Platform Performance",
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total[5m])",
"legendFormat": "{{method}} {{route}}"
}
]
},
{
"title": "Response Time",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
"legendFormat": "95th percentile"
},
{
"expr": "histogram_quantile(0.50, rate(http_request_duration_seconds_bucket[5m]))",
"legendFormat": "50th percentile"
}
]
},
{
"title": "Error Rate",
"type": "singlestat",
"targets": [
{
"expr": "rate(http_requests_total{status_code=~\"5..\"}[5m]) / rate(http_requests_total[5m]) * 100"
}
]
}
]
}
}
Dashboard бизнес-метрик
{
"dashboard": {
"title": "Business Metrics",
"panels": [
{
"title": "Orders per Hour",
"type": "graph",
"targets": [
{
"expr": "rate(orders_total[1h])",
"legendFormat": "{{marketplace_id}}"
}
]
},
{
"title": "Revenue",
"type": "graph",
"targets": [
{
"expr": "rate(order_value_amount_sum[1h])",
"legendFormat": "{{marketplace_id}} {{currency}}"
}
]
},
{
"title": "Active Marketplaces",
"type": "singlestat",
"targets": [
{
"expr": "active_marketplaces_total"
}
]
}
]
}
}