Files
quoter/docs/monitoring.md
Untone ea92a376ed
Some checks failed
CI / test (push) Failing after 4m0s
CI / lint (push) Failing after 4s
CI / deploy (push) Has been skipped
docs
2025-08-02 00:18:09 +03:00

341 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Мониторинг
## Обзор
Мониторинг Quoter включает в себя логирование, метрики производительности и отслеживание состояния системы.
## Логирование
### Уровни логирования
Quoter использует библиотеку `log` с различными уровнями:
- **error** - Критические ошибки, требующие немедленного внимания
- **warn** - Предупреждения, которые могут указывать на проблемы
- **info** - Информационные сообщения о нормальной работе
- **debug** - Отладочная информация для разработчиков
- **trace** - Максимальная детализация для глубокой отладки
### Настройка логирования
```bash
# Только ошибки
RUST_LOG=error cargo run
# Предупреждения и ошибки
RUST_LOG=warn cargo run
# Информационные сообщения (рекомендуется для продакшена)
RUST_LOG=info cargo run
# Отладка
RUST_LOG=debug cargo run
# Максимальная детализация
RUST_LOG=trace cargo run
```
### Структура логов
#### Загрузка файла
```
[INFO] Started
[WARN] file abc123.jpg uploaded to storj, incrementing quota by 1048576 bytes
[WARN] New quota for user user123: 2097152 bytes
```
#### Получение файла
```
[WARN] >>> GET image_300.jpg [START]
[WARN] detected file extension: jpg
[WARN] base_filename: image
[WARN] requested width: 300
[WARN] Found stored path in DB: production/image/image.jpg
[WARN] File exists in Storj: production/image/image.jpg
[WARN] Processing image file with width: 300
[WARN] Calculated closest width: 300 for requested: 300
[WARN] serve existed thumb file: image_300.jpg
```
#### Ошибки
```
[ERROR] Failed to upload to Storj: image.jpg - Error: Network error
[ERROR] Database error while getting path: image.jpg - Full error: Connection timeout
[ERROR] unsupported file format
```
## Метрики
### Основные метрики для мониторинга
#### Производительность
- **Requests per second (RPS)** - количество запросов в секунду
- **Response time** - время ответа API
- **Error rate** - процент ошибок
- **Upload success rate** - процент успешных загрузок
#### Ресурсы
- **Memory usage** - использование памяти
- **CPU usage** - использование процессора
- **Disk I/O** - операции с диском
- **Network I/O** - сетевой трафик
#### Бизнес-метрики
- **Files uploaded** - количество загруженных файлов
- **Quota usage** - использование квот пользователями
- **Thumbnail generation** - количество сгенерированных миниатюр
- **Storage usage** - использование хранилища
### Prometheus метрики
Добавьте в `Cargo.toml`:
```toml
[dependencies]
prometheus = "0.13"
actix-web-prom = "0.6"
```
Настройте в `main.rs`:
```rust
use actix_web_prom::{PrometheusMetrics, PrometheusMetricsBuilder};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let prometheus = PrometheusMetricsBuilder::new("quoter")
.endpoint("/metrics")
.build()
.unwrap();
HttpServer::new(move || {
App::new()
.wrap(prometheus.clone())
// ... остальные настройки
})
.bind(addr)?
.run()
.await
}
```
### Кастомные метрики
```rust
use prometheus::{Counter, Histogram, Registry};
lazy_static! {
pub static ref UPLOAD_COUNTER: Counter = Counter::new(
"quoter_uploads_total",
"Total number of file uploads"
).unwrap();
pub static ref UPLOAD_SIZE: Histogram = Histogram::new(
"quoter_upload_size_bytes",
"File upload size in bytes"
).unwrap();
pub static ref QUOTA_USAGE: Histogram = Histogram::new(
"quoter_quota_usage_bytes",
"User quota usage in bytes"
).unwrap();
}
```
## Алерты
### Критические алерты
- **Service down** - сервис недоступен
- **High error rate** - высокий процент ошибок (>5%)
- **High response time** - медленные ответы (>2s)
- **Memory usage high** - высокое использование памяти (>80%)
- **Redis connection failed** - потеря соединения с Redis
### Предупреждения
- **Quota usage high** - пользователи приближаются к лимиту квоты
- **Storage usage high** - высокое использование хранилища
- **Thumbnail generation slow** - медленная генерация миниатюр
### Настройка алертов в Prometheus
```yaml
groups:
- name: quoter
rules:
- alert: QuoterServiceDown
expr: up{job="quoter"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Quoter service is down"
- alert: HighErrorRate
expr: rate(http_requests_total{job="quoter",status=~"5.."}[5m]) > 0.05
for: 2m
labels:
severity: warning
annotations:
summary: "High error rate detected"
- alert: HighResponseTime
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{job="quoter"}[5m])) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "High response time detected"
```
## Дашборды
### Grafana дашборд
Создайте дашборд с панелями:
#### Обзор системы
- Статус сервиса (up/down)
- Количество запросов в секунду
- Время ответа (p50, p95, p99)
- Процент ошибок
#### Загрузка файлов
- Количество загрузок в час/день
- Размер загружаемых файлов
- Успешность загрузок
- Использование квот
#### Ресурсы
- Использование CPU и памяти
- Сетевой трафик
- Операции с диском
- Соединения с Redis
#### Бизнес-метрики
- Топ пользователей по использованию квоты
- Популярные размеры миниатюр
- Использование хранилища по типам файлов
### Пример запроса для Grafana
```sql
-- Количество загрузок по часам
SELECT
time_bucket('1 hour', timestamp) AS time,
COUNT(*) as uploads
FROM quoter_uploads
WHERE timestamp > NOW() - INTERVAL '24 hours'
GROUP BY time
ORDER BY time;
```
## Здоровье системы
### Health check endpoint
Добавьте endpoint для проверки здоровья:
```rust
async fn health_check() -> HttpResponse {
// Проверка Redis
let redis_ok = check_redis_connection().await;
// Проверка S3
let s3_ok = check_s3_connection().await;
if redis_ok && s3_ok {
HttpResponse::Ok().json(json!({
"status": "healthy",
"timestamp": chrono::Utc::now(),
"services": {
"redis": "ok",
"s3": "ok"
}
}))
} else {
HttpResponse::ServiceUnavailable().json(json!({
"status": "unhealthy",
"timestamp": chrono::Utc::now(),
"services": {
"redis": if redis_ok { "ok" } else { "error" },
"s3": if s3_ok { "ok" } else { "error" }
}
}))
}
}
```
### Kubernetes liveness/readiness probes
```yaml
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
```
## Трассировка
### Distributed tracing
Для отслеживания запросов через микросервисы:
```toml
[dependencies]
opentelemetry = "0.20"
tracing = "0.1"
tracing-opentelemetry = "0.20"
```
### Логирование с контекстом
```rust
use tracing::{info, warn, error, instrument};
#[instrument(skip(state))]
async fn upload_handler(
req: HttpRequest,
payload: Multipart,
state: web::Data<AppState>,
) -> Result<HttpResponse> {
let user_id = get_user_id(&req).await?;
info!(user_id = %user_id, "Starting file upload");
// ... логика загрузки
info!(user_id = %user_id, filename = %filename, "File uploaded successfully");
Ok(response)
}
```
## Рекомендации
### Продакшен
1. **Логирование**: Используйте структурированные логи в JSON формате
2. **Метрики**: Настройте Prometheus + Grafana
3. **Алерты**: Настройте уведомления для критических событий
4. **Ротация логов**: Настройте logrotate или отправку в ELK stack
5. **Мониторинг ресурсов**: Отслеживайте CPU, память, диск, сеть
### Разработка
1. **Локальное логирование**: Используйте `RUST_LOG=debug`
2. **Отладка**: Включите trace логи для детальной отладки
3. **Тестирование**: Создайте тесты для проверки метрик
4. **Документация**: Документируйте все кастомные метрики