417 lines
12 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.

# Audit Logger - Абстракция для логирования действий пользователей
## 📋 Описание
`audit_logger` — это shared library для централизованного логирования всех действий пользователей во всех микросервисах, API слоях и API Gateway.
## 🎯 Назначение
Предоставляет unified interface для:
- Логирования действий пользователей (CRUD, Login, Logout и т.д.)
- Отслеживания успехов и ошибок
- Сбора метаданных (IP адрес, User Agent, время выполнения)
- Поиска и фильтрации логов
- Расширяемости через trait-based архитектуру
## 📦 Структура
```
shared_libs/audit_logger/
├── src/
│ ├── lib.rs # Main module exports
│ ├── models.rs # Data models (AuditLog, ActionType, etc)
│ ├── store.rs # Storage abstraction and in-memory impl
│ └── logger.rs # Main AuditLogger implementation
└── Cargo.toml
```
## 🚀 Использование
### Базовая настройка
```rust
use std::sync::Arc;
use audit_logger::{AuditLogger, ActionType, InMemoryAuditStore};
// Создать in-memory хранилище (для разработки)
let store = Arc::new(InMemoryAuditStore::new());
// Создать логгер для сервиса
let logger = AuditLogger::new(store, "api_gateway");
```
### Логирование простого действия
```rust
// Логировать простое действие
logger
.log_action(
Some("user_123".to_string()),
ActionType::Create,
"users".to_string(),
"/api/users".to_string(),
)
.await?;
```
### Логирование с деталями
```rust
// Логировать с дополнительной информацией
logger
.log_detailed(
Some("user_123".to_string()),
ActionType::Update,
"users".to_string(),
"/api/users/123".to_string(),
Some("192.168.1.1".to_string()),
Some("Mozilla/5.0...".to_string()),
Some("Updated user profile".to_string()),
)
.await?;
```
### Логирование ошибок
```rust
// Логировать ошибку
logger
.log_error(
Some("user_123".to_string()),
ActionType::Delete,
"users".to_string(),
"/api/users/123".to_string(),
"User not found".to_string(),
)
.await?;
```
### Логирование с таймингом
```rust
// Логировать действие и измерить время выполнения
let result = logger
.log_timed(
Some("user_123".to_string()),
ActionType::Read,
"users".to_string(),
"/api/users".to_string(),
async {
// Ваш асинхронный код
expensive_operation().await
},
)
.await?;
```
### Логирование входа/выхода
```rust
// Логировать вход пользователя
logger
.log_login(
"user_123".to_string(),
Some("192.168.1.1".to_string()),
Some("Mozilla/5.0...".to_string()),
)
.await?;
// Логировать выход пользователя
logger
.log_logout(
"user_123".to_string(),
Some("192.168.1.1".to_string()),
)
.await?;
```
### Поиск логов
```rust
use audit_logger::SearchParams;
// Получить логи пользователя
let logs = logger.get_user_logs("user_123", 50).await?;
// Расширенный поиск
let results = logger
.search(SearchParams {
user_id: Some("user_123".to_string()),
resource: Some("users".to_string()),
service: Some("api_gateway".to_string()),
limit: 100,
offset: 0,
})
.await?;
println!("Found {} logs", results.total);
for log in results.logs {
println!("{:?}", log);
}
```
## 📊 Типы действий (ActionType)
```rust
pub enum ActionType {
Login, // Вход в систему
Logout, // Выход из системы
Create, // Создание ресурса
Update, // Обновление ресурса
Delete, // Удаление ресурса
Read, // Просмотр ресурса
Export, // Экспорт данных
Import, // Импорт данных
Download, // Скачивание файла
Upload, // Загрузка файла
Error, // Ошибка/Фейлюр
Custom(String), // Пользовательское действие
}
```
## 📈 Статусы действий (ActionStatus)
```rust
pub enum ActionStatus {
Success, // Успешно
Failure, // Ошибка
InProgress, // В процессе
}
```
## 🔍 Структура AuditLog
```rust
pub struct AuditLog {
pub id: Uuid, // Уникальный ID
pub user_id: Option<String>, // ID пользователя
pub action: ActionType, // Тип действия
pub status: ActionStatus, // Статус
pub resource: String, // Ресурс
pub resource_id: Option<String>, // ID ресурса
pub service: String, // Сервис
pub endpoint: String, // Endpoint
pub ip_address: Option<String>, // IP адрес
pub user_agent: Option<String>, // User Agent
pub description: Option<String>, // Описание
pub error_details: Option<String>, // Детали ошибки
pub metadata: Option<serde_json::Value>, // Метаданные
pub duration_ms: Option<i64>, // Время выполнения
pub created_at: DateTime<Utc>, // Время логирования
pub api_version: Option<String>, // Версия API
}
```
## 🔌 Расширяемость (AuditStore trait)
Можно реализовать свой backend для хранения логов:
```rust
use async_trait::async_trait;
use audit_logger::store::{AuditStore, AuditResult, SearchParams};
#[async_trait]
impl AuditStore for MyCustomStore {
async fn save(&self, log: AuditLog) -> AuditResult<()> {
// Сохранить в БД, файл и т.д.
Ok(())
}
async fn get(&self, id: Uuid) -> AuditResult<AuditLog> {
// Получить из БД
todo!()
}
async fn search(&self, params: SearchParams) -> AuditResult<SearchResults> {
// Поиск в БД
todo!()
}
async fn cleanup_old(&self, days: i64) -> AuditResult<usize> {
// Удалить старые логи
Ok(0)
}
}
```
## 🔄 Интеграция в сервисы
### API Gateway
```rust
use audit_logger::{AuditLogger, InMemoryAuditStore};
use std::sync::Arc;
let store = Arc::new(InMemoryAuditStore::new());
let logger = Arc::new(AuditLogger::new(store, "api_gateway"));
// В handlers
async fn get_users(logger: Arc<AuditLogger>) -> Json<Vec<User>> {
let _ = logger
.log_action(
None,
ActionType::Read,
"users".to_string(),
"/api/users".to_string(),
)
.await;
// ...
}
```
### Microservices
```rust
let logger = Arc::new(create_audit_logger());
impl UserService for UserServiceImpl {
async fn get_users(&self, _request: Request<GetUsersRequest>) {
let _ = self
.audit_logger
.log_action(
None,
ActionType::Read,
"users".to_string(),
"/GetUsers".to_string(),
)
.await;
// ...
}
}
```
## 📝 Примеры использования
### Пример 1: REST endpoint с логированием
```rust
async fn create_user(
logger: Arc<AuditLogger>,
Json(req): Json<CreateUserRequest>,
) -> (StatusCode, Json<User>) {
let user = User {
id: 3,
name: req.name.clone(),
email: req.email.clone(),
};
let _ = logger
.log_detailed(
None,
ActionType::Create,
"users".to_string(),
"/api/users".to_string(),
None,
None,
Some(format!("Created user: {}", req.name)),
)
.await;
(StatusCode::CREATED, Json(user))
}
```
### Пример 2: gRPC сервис с логированием
```rust
async fn get_user(
&self,
request: Request<GetUserRequest>,
) -> Result<Response<UserResponse>, Status> {
let user_id = request.into_inner().id;
let _ = self
.audit_logger
.log_detailed(
None,
ActionType::Read,
"users".to_string(),
"/GetUser".to_string(),
None,
None,
Some(format!("Getting user {}", user_id)),
)
.await;
// ...
}
```
## 🔮 Будущие расширения
### В фазе 2 можно добавить:
1. **Database Backend** (PostgreSQL)
```rust
pub struct PostgresAuditStore {
pool: PgPool,
}
```
2. **Elasticsearch Backend** для быстрого поиска
3. **Kafka Backend** для распределенного логирования
4. **Middleware** для автоматического логирования всех requests
5. **Metrics/Monitoring** интеграция
6. **Retention Policy** (автоматическая очистка старых логов)
## ⚙️ Конфигурация
### Зависимости в Cargo.toml
```toml
audit_logger = { path = "../shared_libs/audit_logger" }
```
### Features
- `default = ["in-memory"]` - Включить in-memory backend
- Можно отключить для использования только trait'ов
## 🧪 Тестирование
```bash
# Запустить все тесты
cargo test --package audit_logger
# Запустить конкретный тест
cargo test --package audit_logger test_audit_log_creation
```
## 📊 Производительность
- **In-memory store**: ~1-2 микросекунд на логирование
- **Масштабируемость**: До 10k логов в памяти без проблем
- **Поиск**: O(n) для in-memory, может быть O(log n) в БД
## 🔐 Безопасность
- Чувствительные данные НЕ логируются автоматически
- Логирование пароля - ответственность разработчика
- IP адреса и User Agent могут содержать PII
- Соответствует GDPR (можно удалить личные данные)
## 📞 API Reference
Полный API доступен через docs:
```bash
cargo doc --package audit_logger --open
```
## 🎯 Лучшие практики
1. ✅ Всегда логируйте CRUD операции
2. ✅ Логируйте вход/выход пользователей
3. ✅ Логируйте ошибки с полными деталями
4. ✅ Используйте в-memory store для разработки
5. ✅ Переключайтесь на БД для production
6.НЕ логируйте пароли
7.НЕ логируйте токены в полном виде
8.НЕ логируйте чувствительные данные
---
**Статус**: ✅ Готово к использованию во всех сервисах