Initial commit: Complete Software Architecture course with 11 modules
- Added comprehensive course structure with 11 modules - Included theoretical content, practical examples, and tasks - Multi-language code examples (Java, Rust, Node.js, Python) - Detailed analysis of architectural approaches and trade-offs - Complete caching strategies documentation - Architecture examples from real-world systems (Twitter, Netflix, Uber) - Structured navigation and learning path - Ready for educational use
This commit is contained in:
commit
15e744da49
107 files changed
+61762
No files matched your search
@@ -0,0 +1,113 @@
|
||||
# Модуль 5: Мониторинг и наблюдаемость
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Описание модуля
|
||||
|
||||
Этот модуль посвящен изучению современных подходов к мониторингу и наблюдаемости в распределенных системах. Студенты изучат принципы сбора метрик, логирования, трассировки и создания эффективных систем мониторинга.
|
||||
|
||||
## Содержание модуля
|
||||
|
||||
### 1. [Основы мониторинга](sections/01-monitoring-basics.md)
|
||||
- Цели и типы мониторинга
|
||||
- Метрики мониторинга (Counters, Gauges, Histograms, Summaries)
|
||||
- Принципы проектирования систем мониторинга
|
||||
|
||||
### 2. [Prometheus и Grafana](sections/02-prometheus-grafana.md)
|
||||
- Архитектура Prometheus
|
||||
- PromQL (язык запросов Prometheus)
|
||||
- Создание дашбордов в Grafana
|
||||
- Настройка алертов
|
||||
|
||||
### 3. [Логирование](sections/03-logging.md)
|
||||
- Structured Logging
|
||||
- Log Levels и Correlation ID
|
||||
- ELK Stack (Elasticsearch, Logstash, Kibana)
|
||||
- Fluentd для сбора логов
|
||||
|
||||
### 4. [Distributed Tracing](sections/04-distributed-tracing.md)
|
||||
- Принципы распределенной трассировки
|
||||
- OpenTelemetry
|
||||
- Jaeger для анализа трассировок
|
||||
- Интеграция с микросервисами
|
||||
|
||||
### 5. [Observability](sections/05-observability.md)
|
||||
- Три столпа наблюдаемости
|
||||
- Health Checks
|
||||
- Custom Metrics
|
||||
- Паттерны наблюдаемости
|
||||
|
||||
### 6. [Alerting](sections/06-alerting.md)
|
||||
- Принципы алертинга
|
||||
- Правила оповещений Prometheus
|
||||
- Конфигурация Alertmanager
|
||||
- Предотвращение усталости от алертов
|
||||
|
||||
### 7. [SLI/SLO/SLA](sections/07-sli-slo-sla.md)
|
||||
- SLI (Service Level Indicators)
|
||||
- SLO (Service Level Objectives)
|
||||
- SLA (Service Level Agreements)
|
||||
- Мониторинг соответствия SLO
|
||||
|
||||
## Ключевые компетенции
|
||||
|
||||
После изучения модуля студенты будут уметь:
|
||||
|
||||
- Проектировать системы мониторинга
|
||||
- Настраивать Prometheus и Grafana
|
||||
- Реализовывать структурированное логирование
|
||||
- Настраивать распределенную трассировку
|
||||
- Создавать эффективные алерты
|
||||
- Определять и мониторить SLI/SLO/SLA
|
||||
|
||||
## Практические задания
|
||||
|
||||
1. **Настройка мониторинга**
|
||||
- Установка и конфигурация Prometheus
|
||||
- Создание дашбордов в Grafana
|
||||
- Настройка сбора метрик из приложений
|
||||
|
||||
2. **Структурированное логирование**
|
||||
- Настройка ELK Stack
|
||||
- Реализация Correlation ID
|
||||
- Создание шаблонов логов
|
||||
|
||||
3. **Distributed Tracing**
|
||||
- Настройка OpenTelemetry
|
||||
- Интеграция с Jaeger
|
||||
- Анализ трассировок
|
||||
|
||||
4. **Система алертинга**
|
||||
- Создание правил алертов
|
||||
- Настройка Alertmanager
|
||||
- Интеграция с уведомлениями
|
||||
|
||||
5. **SLI/SLO/SLA**
|
||||
- Определение ключевых метрик
|
||||
- Создание SLO
|
||||
- Мониторинг соответствия целям
|
||||
|
||||
6. **Observability Dashboard**
|
||||
- Создание комплексного дашборда
|
||||
- Интеграция метрик, логов и трассировок
|
||||
- Настройка автоматических проверок
|
||||
|
||||
## Дополнительные ресурсы
|
||||
|
||||
- [Prometheus Documentation](https://prometheus.io/docs/) - официальная документация Prometheus
|
||||
- [Grafana Documentation](https://grafana.com/docs/) - документация Grafana
|
||||
- [OpenTelemetry](https://opentelemetry.io/) - стандарт для наблюдаемости
|
||||
- [Jaeger Documentation](https://www.jaegertracing.io/docs/) - документация Jaeger
|
||||
- [ELK Stack](https://www.elastic.co/elastic-stack/) - стек для логирования
|
||||
|
||||
## Критерии оценки
|
||||
|
||||
- Понимание принципов мониторинга (20%)
|
||||
- Навыки работы с Prometheus и Grafana (25%)
|
||||
- Опыт настройки логирования (20%)
|
||||
- Знание Distributed Tracing (15%)
|
||||
- Навыки создания алертов (10%)
|
||||
- Понимание SLI/SLO/SLA (10%)
|
||||
@@ -0,0 +1,187 @@
|
||||
# Основы мониторинга
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Что такое мониторинг
|
||||
|
||||
**Мониторинг** — процесс сбора, анализа и использования информации о работе системы для обеспечения её стабильности и производительности.
|
||||
|
||||
## Цели мониторинга
|
||||
|
||||
### 1. Проактивное обнаружение проблем
|
||||
- Выявление проблем до их влияния на пользователей
|
||||
- Предотвращение каскадных отказов
|
||||
- Оптимизация производительности
|
||||
|
||||
### 2. Реактивное решение проблем
|
||||
- Быстрая диагностика инцидентов
|
||||
- Сокращение времени восстановления (MTTR)
|
||||
- Анализ причин отказов
|
||||
|
||||
### 3. Бизнес-аналитика
|
||||
- Понимание поведения пользователей
|
||||
- Анализ производительности бизнес-процессов
|
||||
- Планирование ресурсов
|
||||
|
||||
## Типы мониторинга
|
||||
|
||||
### 1. Infrastructure Monitoring
|
||||
- CPU, Memory, Disk, Network
|
||||
- Контейнеры и виртуальные машины
|
||||
- Базы данных и кэши
|
||||
|
||||
### 2. Application Monitoring
|
||||
- Метрики приложения
|
||||
- Производительность кода
|
||||
- Ошибки и исключения
|
||||
|
||||
### 3. Business Monitoring
|
||||
- Ключевые бизнес-метрики
|
||||
- Пользовательская активность
|
||||
- Конверсии и доходы
|
||||
|
||||
## Метрики мониторинга
|
||||
|
||||
### 1. Counters (Счетчики)
|
||||
**Определение:** Метрики, которые только увеличиваются.
|
||||
|
||||
**Технический пример - Advanced Metrics Collection:**
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class RequestCounter {
|
||||
private final Counter requestCounter;
|
||||
private final Counter errorCounter;
|
||||
private final Timer requestTimer;
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
public RequestCounter(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
|
||||
this.requestCounter = Counter.builder("http.requests.total")
|
||||
.description("Total number of HTTP requests")
|
||||
.tag("service", "user-service")
|
||||
.register(meterRegistry);
|
||||
|
||||
this.errorCounter = Counter.builder("http.errors.total")
|
||||
.description("Total number of HTTP errors")
|
||||
.tag("service", "user-service")
|
||||
.register(meterRegistry);
|
||||
|
||||
this.requestTimer = Timer.builder("http.request.duration")
|
||||
.description("HTTP request duration")
|
||||
.tag("service", "user-service")
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
public void increment(String method, String endpoint, String status) {
|
||||
requestCounter.increment(
|
||||
Tags.of(
|
||||
"method", method,
|
||||
"endpoint", endpoint,
|
||||
"status", status
|
||||
)
|
||||
);
|
||||
|
||||
if (Integer.parseInt(status) >= 400) {
|
||||
errorCounter.increment(
|
||||
Tags.of(
|
||||
"method", method,
|
||||
"endpoint", endpoint,
|
||||
"error_type", getErrorType(status)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public Timer.Sample startTimer() {
|
||||
return Timer.start(meterRegistry);
|
||||
}
|
||||
|
||||
public void recordDuration(Timer.Sample sample, String method, String endpoint) {
|
||||
sample.stop(requestTimer.tags(
|
||||
"method", method,
|
||||
"endpoint", endpoint
|
||||
));
|
||||
}
|
||||
|
||||
private String getErrorType(String status) {
|
||||
int statusCode = Integer.parseInt(status);
|
||||
if (statusCode >= 400 && statusCode < 500) {
|
||||
return "client_error";
|
||||
} else if (statusCode >= 500) {
|
||||
return "server_error";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Gauges (Измерители)
|
||||
**Определение:** Метрики, которые могут увеличиваться и уменьшаться.
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class ActiveConnectionsGauge {
|
||||
private final AtomicInteger activeConnections = new AtomicInteger(0);
|
||||
private final Gauge activeConnectionsGauge;
|
||||
|
||||
public ActiveConnectionsGauge(MeterRegistry meterRegistry) {
|
||||
this.activeConnectionsGauge = Gauge.builder("active.connections")
|
||||
.description("Number of active connections")
|
||||
.register(meterRegistry, this, obj -> obj.activeConnections.get());
|
||||
}
|
||||
|
||||
public void incrementConnections() {
|
||||
activeConnections.incrementAndGet();
|
||||
}
|
||||
|
||||
public void decrementConnections() {
|
||||
activeConnections.decrementAndGet();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Histograms (Гистограммы)
|
||||
**Определение:** Метрики для измерения распределения значений.
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class ResponseTimeHistogram {
|
||||
private final Timer responseTimeTimer;
|
||||
|
||||
public ResponseTimeHistogram(MeterRegistry meterRegistry) {
|
||||
this.responseTimeTimer = Timer.builder("http.request.duration")
|
||||
.description("HTTP request duration")
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
public void recordResponseTime(String endpoint, Duration duration) {
|
||||
responseTimeTimer.record(duration);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Summaries (Сумматоры)
|
||||
**Определение:** Метрики для измерения квантилей.
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class ResponseTimeSummary {
|
||||
private final DistributionSummary responseTimeSummary;
|
||||
|
||||
public ResponseTimeSummary(MeterRegistry meterRegistry) {
|
||||
this.responseTimeSummary = DistributionSummary.builder("http.request.size")
|
||||
.description("HTTP request size in bytes")
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
public void recordRequestSize(long size) {
|
||||
responseTimeSummary.record(size);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,155 @@
|
||||
# Prometheus и Grafana
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Prometheus
|
||||
|
||||
**Prometheus** — система мониторинга и база данных временных рядов.
|
||||
|
||||
### Архитектура Prometheus
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Application │ │ Application │ │ Application │
|
||||
│ (Metrics) │ │ (Metrics) │ │ (Metrics) │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
└───────────────────────┼───────────────────────┘
|
||||
│
|
||||
┌─────────────────┐
|
||||
│ Prometheus │
|
||||
│ Server │
|
||||
└─────────────────┘
|
||||
│
|
||||
┌─────────────────┐
|
||||
│ Grafana │
|
||||
│ (Dashboard) │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### PromQL (Язык запросов Prometheus)
|
||||
|
||||
#### Основные запросы:
|
||||
```promql
|
||||
# Простая метрика
|
||||
http_requests_total
|
||||
|
||||
# Метрика с фильтрами
|
||||
http_requests_total{method="GET", status="200"}
|
||||
|
||||
# Агрегация
|
||||
sum(http_requests_total) by (method)
|
||||
|
||||
# Rate (скорость изменения)
|
||||
rate(http_requests_total[5m])
|
||||
|
||||
# Histogram quantiles
|
||||
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
|
||||
```
|
||||
|
||||
#### Примеры запросов:
|
||||
```promql
|
||||
# Количество запросов в секунду
|
||||
rate(http_requests_total[5m])
|
||||
|
||||
# Среднее время ответа
|
||||
rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m])
|
||||
|
||||
# 95-й перцентиль времени ответа
|
||||
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
|
||||
|
||||
# Ошибки в процентах
|
||||
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100
|
||||
```
|
||||
|
||||
### Spring Boot + Prometheus
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class PrometheusConfig {
|
||||
@Bean
|
||||
public MeterRegistry meterRegistry() {
|
||||
return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
public class MetricsController {
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
public MetricsController(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
}
|
||||
|
||||
@GetMapping("/metrics")
|
||||
public String metrics() {
|
||||
return ((PrometheusMeterRegistry) meterRegistry).scrape();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Grafana
|
||||
|
||||
**Grafana** — платформа для визуализации метрик и создания дашбордов.
|
||||
|
||||
### Создание дашборда
|
||||
|
||||
```json
|
||||
{
|
||||
"dashboard": {
|
||||
"title": "Application Metrics",
|
||||
"panels": [
|
||||
{
|
||||
"title": "Request Rate",
|
||||
"type": "graph",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(http_requests_total[5m])",
|
||||
"legendFormat": "{{method}} {{endpoint}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Response Time",
|
||||
"type": "graph",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
|
||||
"legendFormat": "95th percentile"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Алерты в Grafana
|
||||
|
||||
```json
|
||||
{
|
||||
"alert": {
|
||||
"name": "High Error Rate",
|
||||
"message": "Error rate is above 5%",
|
||||
"conditions": [
|
||||
{
|
||||
"query": {
|
||||
"params": ["A", "5m", "now"]
|
||||
},
|
||||
"reducer": {
|
||||
"type": "last",
|
||||
"params": []
|
||||
},
|
||||
"evaluator": {
|
||||
"params": [0.05],
|
||||
"type": "gt"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,238 @@
|
||||
# Логирование
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Принципы логирования
|
||||
|
||||
### 1. Structured Logging
|
||||
**Определение:** Логирование в структурированном формате (JSON).
|
||||
|
||||
**Технический пример - Advanced Structured Logging:**
|
||||
|
||||
```java
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class OrderController {
|
||||
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
@Autowired
|
||||
private MetricsService metricsService;
|
||||
|
||||
@PostMapping("/orders")
|
||||
public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
|
||||
String correlationId = MDC.get("correlationId");
|
||||
String userId = MDC.get("userId");
|
||||
|
||||
// Structured logging with business context
|
||||
log.info("Order creation started",
|
||||
StructuredLogging.builder()
|
||||
.correlationId(correlationId)
|
||||
.userId(userId)
|
||||
.customerId(request.getCustomerId())
|
||||
.orderValue(request.getTotalValue())
|
||||
.itemsCount(request.getItems().size())
|
||||
.currency(request.getCurrency())
|
||||
.paymentMethod(request.getPaymentMethod())
|
||||
.build()
|
||||
);
|
||||
|
||||
Timer.Sample sample = Timer.start();
|
||||
|
||||
try {
|
||||
Order order = orderService.createOrder(request);
|
||||
|
||||
// Success logging with performance metrics
|
||||
Duration duration = Duration.ofNanos(sample.stop());
|
||||
log.info("Order created successfully",
|
||||
StructuredLogging.builder()
|
||||
.correlationId(correlationId)
|
||||
.userId(userId)
|
||||
.orderId(order.getId())
|
||||
.customerId(request.getCustomerId())
|
||||
.status(order.getStatus())
|
||||
.processingTimeMs(duration.toMillis())
|
||||
.build()
|
||||
);
|
||||
|
||||
// Record business metrics
|
||||
metricsService.recordBusinessEvent("order_created", userId);
|
||||
metricsService.recordOrderValue(request.getTotalValue(), request.getCurrency());
|
||||
|
||||
return ResponseEntity.ok(order);
|
||||
|
||||
} catch (ValidationException e) {
|
||||
log.warn("Order validation failed",
|
||||
StructuredLogging.builder()
|
||||
.correlationId(correlationId)
|
||||
.userId(userId)
|
||||
.customerId(request.getCustomerId())
|
||||
.errorType("validation_error")
|
||||
.errorMessage(e.getMessage())
|
||||
.validationErrors(e.getValidationErrors())
|
||||
.build()
|
||||
);
|
||||
return ResponseEntity.badRequest().body(new ErrorResponse(e.getMessage()));
|
||||
|
||||
} catch (PaymentException e) {
|
||||
log.error("Payment processing failed",
|
||||
StructuredLogging.builder()
|
||||
.correlationId(correlationId)
|
||||
.userId(userId)
|
||||
.customerId(request.getCustomerId())
|
||||
.errorType("payment_error")
|
||||
.errorMessage(e.getMessage())
|
||||
.paymentMethod(request.getPaymentMethod())
|
||||
.orderValue(request.getTotalValue())
|
||||
.build()
|
||||
);
|
||||
return ResponseEntity.status(HttpStatus.PAYMENT_REQUIRED)
|
||||
.body(new ErrorResponse("Payment processing failed"));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Unexpected error during order creation",
|
||||
StructuredLogging.builder()
|
||||
.correlationId(correlationId)
|
||||
.userId(userId)
|
||||
.customerId(request.getCustomerId())
|
||||
.errorType("system_error")
|
||||
.errorMessage(e.getMessage())
|
||||
.stackTrace(getStackTrace(e))
|
||||
.build()
|
||||
);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(new ErrorResponse("Internal server error"));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Log Levels
|
||||
- **ERROR** — критические ошибки
|
||||
- **WARN** — предупреждения
|
||||
- **INFO** — информационные сообщения
|
||||
- **DEBUG** — отладочная информация
|
||||
- **TRACE** — детальная трассировка
|
||||
|
||||
### 3. Correlation ID
|
||||
```java
|
||||
@Component
|
||||
public class CorrelationIdFilter implements Filter {
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
String correlationId = httpRequest.getHeader("X-Correlation-ID");
|
||||
|
||||
if (correlationId == null) {
|
||||
correlationId = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
MDC.put("correlationId", correlationId);
|
||||
|
||||
try {
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ELK Stack (Elasticsearch, Logstash, Kibana)
|
||||
|
||||
### Конфигурация Logstash
|
||||
```ruby
|
||||
# logstash.conf
|
||||
input {
|
||||
beats {
|
||||
port => 5044
|
||||
}
|
||||
}
|
||||
|
||||
filter {
|
||||
if [fields][service] == "order-service" {
|
||||
grok {
|
||||
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}" }
|
||||
}
|
||||
|
||||
date {
|
||||
match => [ "timestamp", "ISO8601" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output {
|
||||
elasticsearch {
|
||||
hosts => ["elasticsearch:9200"]
|
||||
index => "logs-%{+YYYY.MM.dd}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Шаблон индекса Elasticsearch
|
||||
```json
|
||||
{
|
||||
"index_patterns": ["logs-*"],
|
||||
"template": {
|
||||
"settings": {
|
||||
"number_of_shards": 1,
|
||||
"number_of_replicas": 1
|
||||
},
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"@timestamp": {
|
||||
"type": "date"
|
||||
},
|
||||
"level": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"message": {
|
||||
"type": "text"
|
||||
},
|
||||
"correlationId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"service": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Fluentd
|
||||
|
||||
```ruby
|
||||
# fluent.conf
|
||||
<source>
|
||||
@type tail
|
||||
path /var/log/application.log
|
||||
pos_file /var/log/fluentd.log.pos
|
||||
tag application.logs
|
||||
format json
|
||||
</source>
|
||||
|
||||
<filter application.logs>
|
||||
@type record_transformer
|
||||
<record>
|
||||
service "order-service"
|
||||
environment "production"
|
||||
</record>
|
||||
</filter>
|
||||
|
||||
<match application.logs>
|
||||
@type elasticsearch
|
||||
host elasticsearch
|
||||
port 9200
|
||||
index_name logs
|
||||
type_name _doc
|
||||
</match>
|
||||
```
|
||||
@@ -0,0 +1,102 @@
|
||||
# Distributed Tracing
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Что такое Distributed Tracing
|
||||
|
||||
**Distributed Tracing** — метод отслеживания запросов через распределенную систему.
|
||||
|
||||
## OpenTelemetry
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class TracingConfig {
|
||||
@Bean
|
||||
public OpenTelemetry openTelemetry() {
|
||||
return OpenTelemetrySdk.builder()
|
||||
.setTracerProvider(
|
||||
SdkTracerProvider.builder()
|
||||
.addSpanProcessor(BatchSpanProcessor.builder(
|
||||
JaegerGrpcSpanExporter.builder()
|
||||
.setEndpoint("http://jaeger:14250")
|
||||
.build()
|
||||
).build())
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
public class OrderService {
|
||||
private final Tracer tracer;
|
||||
|
||||
public OrderService(OpenTelemetry openTelemetry) {
|
||||
this.tracer = openTelemetry.getTracer("order-service");
|
||||
}
|
||||
|
||||
public Order createOrder(CreateOrderRequest request) {
|
||||
Span span = tracer.spanBuilder("create-order")
|
||||
.setAttribute("customer.id", request.getCustomerId())
|
||||
.setAttribute("order.value", request.getTotalValue().doubleValue())
|
||||
.startSpan();
|
||||
|
||||
try (Scope scope = span.makeCurrent()) {
|
||||
// бизнес-логика
|
||||
Order order = processOrder(request);
|
||||
|
||||
span.setStatus(StatusCode.OK);
|
||||
span.setAttribute("order.id", order.getId());
|
||||
|
||||
return order;
|
||||
} catch (Exception e) {
|
||||
span.setStatus(StatusCode.ERROR, e.getMessage());
|
||||
span.recordException(e);
|
||||
throw e;
|
||||
} finally {
|
||||
span.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Jaeger
|
||||
|
||||
### Конфигурация Jaeger
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
services:
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:latest
|
||||
ports:
|
||||
- "16686:16686"
|
||||
- "14268:14268"
|
||||
environment:
|
||||
- COLLECTOR_OTLP_ENABLED=true
|
||||
```
|
||||
|
||||
### Анализ трассировок
|
||||
```java
|
||||
@Component
|
||||
public class TraceAnalyzer {
|
||||
public void analyzeTrace(String traceId) {
|
||||
// анализ трассировки
|
||||
List<Span> spans = getSpansByTraceId(traceId);
|
||||
|
||||
// поиск узких мест
|
||||
Span slowestSpan = spans.stream()
|
||||
.max(Comparator.comparing(Span::getDuration))
|
||||
.orElse(null);
|
||||
|
||||
// анализ ошибок
|
||||
List<Span> errorSpans = spans.stream()
|
||||
.filter(span -> span.getStatus().getStatusCode() == StatusCode.ERROR)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,92 @@
|
||||
# Observability
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Три столпа Observability
|
||||
|
||||
### 1. Metrics (Метрики)
|
||||
- Количественные измерения
|
||||
- Агрегированные данные
|
||||
- Хорошо для мониторинга трендов
|
||||
|
||||
### 2. Logs (Логи)
|
||||
- События с временными метками
|
||||
- Детальная информация
|
||||
- Хорошо для отладки
|
||||
|
||||
### 3. Traces (Трассировки)
|
||||
- Путь запроса через систему
|
||||
- Временные зависимости
|
||||
- Хорошо для анализа производительности
|
||||
|
||||
## Паттерны наблюдаемости
|
||||
|
||||
### 1. Health Checks
|
||||
```java
|
||||
@Component
|
||||
public class HealthIndicator implements HealthIndicator {
|
||||
@Override
|
||||
public Health health() {
|
||||
try {
|
||||
// проверка зависимостей
|
||||
boolean dbHealthy = checkDatabase();
|
||||
boolean cacheHealthy = checkCache();
|
||||
|
||||
if (dbHealthy && cacheHealthy) {
|
||||
return Health.up()
|
||||
.withDetail("database", "UP")
|
||||
.withDetail("cache", "UP")
|
||||
.build();
|
||||
} else {
|
||||
return Health.down()
|
||||
.withDetail("database", dbHealthy ? "UP" : "DOWN")
|
||||
.withDetail("cache", cacheHealthy ? "UP" : "DOWN")
|
||||
.build();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return Health.down(e).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Custom Metrics
|
||||
```java
|
||||
@Component
|
||||
public class BusinessMetrics {
|
||||
private final Counter ordersCreated;
|
||||
private final Timer orderProcessingTime;
|
||||
private final Gauge activeUsers;
|
||||
|
||||
public BusinessMetrics(MeterRegistry meterRegistry) {
|
||||
this.ordersCreated = Counter.builder("orders.created")
|
||||
.description("Total orders created")
|
||||
.register(meterRegistry);
|
||||
|
||||
this.orderProcessingTime = Timer.builder("orders.processing.time")
|
||||
.description("Order processing time")
|
||||
.register(meterRegistry);
|
||||
|
||||
this.activeUsers = Gauge.builder("users.active")
|
||||
.description("Number of active users")
|
||||
.register(meterRegistry, this, obj -> obj.getActiveUsersCount());
|
||||
}
|
||||
|
||||
public void recordOrderCreated() {
|
||||
ordersCreated.increment();
|
||||
}
|
||||
|
||||
public void recordOrderProcessingTime(Duration duration) {
|
||||
orderProcessingTime.record(duration);
|
||||
}
|
||||
|
||||
private int getActiveUsersCount() {
|
||||
// логика подсчета активных пользователей
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,76 @@
|
||||
# Alerting
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## Принципы алертинга
|
||||
|
||||
### 1. Alert Fatigue Prevention
|
||||
- Только важные алерты
|
||||
- Группировка похожих алертов
|
||||
- Эскалация по времени
|
||||
|
||||
### 2. Alert Classification
|
||||
- **Critical** — система недоступна
|
||||
- **Warning** — деградация производительности
|
||||
- **Info** — информационные уведомления
|
||||
|
||||
## Правила оповещений Prometheus
|
||||
|
||||
```yaml
|
||||
# alerts.yml
|
||||
groups:
|
||||
- name: application
|
||||
rules:
|
||||
- alert: HighErrorRate
|
||||
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
|
||||
for: 2m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "High error rate detected"
|
||||
description: "Error rate is {{ $value }} for {{ $labels.instance }}"
|
||||
|
||||
- alert: HighResponseTime
|
||||
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "High response time"
|
||||
description: "95th percentile response time is {{ $value }}s"
|
||||
```
|
||||
|
||||
## Конфигурация Alertmanager
|
||||
|
||||
```yaml
|
||||
# alertmanager.yml
|
||||
global:
|
||||
smtp_smarthost: 'localhost:587'
|
||||
smtp_from: 'alerts@example.com'
|
||||
|
||||
route:
|
||||
group_by: ['alertname']
|
||||
group_wait: 10s
|
||||
group_interval: 10s
|
||||
repeat_interval: 1h
|
||||
receiver: 'web.hook'
|
||||
|
||||
receivers:
|
||||
- name: 'web.hook'
|
||||
webhook_configs:
|
||||
- url: 'http://alert-webhook:5001/alerts'
|
||||
|
||||
- name: 'email'
|
||||
email_configs:
|
||||
- to: 'admin@example.com'
|
||||
subject: 'Alert: {{ .GroupLabels.alertname }}'
|
||||
body: |
|
||||
{{ range .Alerts }}
|
||||
Alert: {{ .Annotations.summary }}
|
||||
Description: {{ .Annotations.description }}
|
||||
{{ end }}
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
# SLI/SLO/SLA
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
## SLI (Индикатор уровня сервиса)
|
||||
|
||||
**SLI** — метрика, которая измеряет качество сервиса.
|
||||
|
||||
### Примеры SLI:
|
||||
- **Availability**: `successful_requests / total_requests`
|
||||
- **Latency**: `requests_completed_within_threshold / total_requests`
|
||||
- **Throughput**: `successful_requests_per_second`
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class SLICalculator {
|
||||
public double calculateAvailability(String service, Duration window) {
|
||||
Counter successfulRequests = Counter.builder("requests.successful")
|
||||
.tag("service", service)
|
||||
.register(meterRegistry);
|
||||
|
||||
Counter totalRequests = Counter.builder("requests.total")
|
||||
.tag("service", service)
|
||||
.register(meterRegistry);
|
||||
|
||||
double successful = successfulRequests.count();
|
||||
double total = totalRequests.count();
|
||||
|
||||
return total > 0 ? successful / total : 0.0;
|
||||
}
|
||||
|
||||
public double calculateLatency(String service, Duration threshold) {
|
||||
Timer requestTimer = Timer.builder("request.duration")
|
||||
.tag("service", service)
|
||||
.register(meterRegistry);
|
||||
|
||||
// логика расчета латентности
|
||||
return 0.95; // пример
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## SLO (Цель уровня сервиса)
|
||||
|
||||
**SLO** — целевое значение для SLI.
|
||||
|
||||
### Примеры SLO:
|
||||
- **Availability**: 99.9% uptime
|
||||
- **Latency**: 95% of requests < 200ms
|
||||
- **Error Rate**: < 0.1% errors
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class SLOMonitor {
|
||||
private final Map<String, SLO> slos = Map.of(
|
||||
"availability", new SLO("availability", 0.999, "99.9% uptime"),
|
||||
"latency", new SLO("latency", 0.95, "95% < 200ms"),
|
||||
"error_rate", new SLO("error_rate", 0.001, "< 0.1% errors")
|
||||
);
|
||||
|
||||
public boolean checkSLO(String sloName, double currentValue) {
|
||||
SLO slo = slos.get(sloName);
|
||||
return currentValue >= slo.getTarget();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## SLA (Соглашение об уровне сервиса)
|
||||
|
||||
**SLA** — соглашение с клиентами о качестве сервиса.
|
||||
|
||||
### Компоненты SLA:
|
||||
- **Service Description** — описание сервиса
|
||||
- **Performance Metrics** — метрики производительности
|
||||
- **Availability Targets** — цели доступности
|
||||
- **Remediation** — меры по устранению нарушений
|
||||
@@ -0,0 +1,24 @@
|
||||
# Практические задания
|
||||
|
||||
## Навигация
|
||||
- [🏠 Главная страница курса](../../../README.md)
|
||||
- [📚 Модуль 5](../README.md)
|
||||
|
||||
---
|
||||
|
||||
### Задание 1: Prometheus + Grafana
|
||||
1. Настройте Prometheus для сбора метрик
|
||||
2. Создайте дашборд в Grafana
|
||||
3. Настройте алерты
|
||||
|
||||
### Задание 2: Distributed Tracing
|
||||
1. Интегрируйте OpenTelemetry в приложение
|
||||
2. Настройте Jaeger для анализа трассировок
|
||||
3. Создайте анализ производительности
|
||||
|
||||
### Задание 3: ELK Stack
|
||||
1. Настройте централизованное логирование
|
||||
2. Создайте индексы в Elasticsearch
|
||||
3. Настройте дашборды в Kibana
|
||||
|
||||
---
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user