Skip to content

Commit 88e3941

Browse files
committed
docs: наблюдаемость (метрики, логи, Jaeger); collector OpenSearch exporter; compose DemoTraffic
1 parent 8c2f755 commit 88e3941

7 files changed

Lines changed: 161 additions & 13 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,7 @@ yarn-error.log*
8181
.env
8282
.env.local
8383
.env.*.local
84+
85+
## Tests / coverage (локальные отчёты; в CI артефакт не коммитится)
86+
TestResults/
87+
TestResults-*/

README.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,98 @@ OpenTelemetry: трейсы и метрики.
276276

277277
**Дашборд:** [**docs/grafana-dashboard.md**](docs/grafana-dashboard.md).
278278

279+
### Иллюстрации: метрики, сбор и связка с логами
280+
281+
Ниже — скриншоты из поднятого стека (`docker compose up -d`): Prometheus и Grafana (**Explore → Metrics**, источник Prometheus). Файлы лежат в [`docs/screenshots/`](docs/screenshots/).
282+
283+
#### 1. Prometheus: цели сбора (`/targets`)
284+
285+
Два job’а в статусе **UP**: API отдаёт метрики на `http://api:8080/metrics`, worker — на `http://worker:9464/metrics`. Это базовая проверка, что экспортёры доступны и scrape проходит без ошибок.
286+
287+
![Prometheus Targets: order-tracking-api и order-tracking-worker UP](docs/screenshots/metrics-prometheus-targets.png)
288+
289+
#### 2–3. Grafana Explore → Metrics: входящий HTTP, DNS, сборки, исключения, GC (обзор)
290+
291+
Встроенный режим **Metrics** в Grafana (данные с Prometheus) без ручного PromQL: маршрутизация ASP.NET Core (`aspnetcore_routing_match_attempts_total`), DNS-клиент, счётчик сборок (`dotnet_assembly_count`), отсутствие исключений (`dotnet_exceptions_total` на нуле), активность GC и аллокаций на куче. Два кадра — соседние страницы/масштаб того же типа дашборда.
292+
293+
![Grafana Metrics: routing, DNS, .NET startup и GC — обзор](docs/screenshots/metrics-grafana-explore-runtime-overview.png)
294+
295+
![Grafana Metrics: routing, DNS, .NET — альтернативный кадр](docs/screenshots/metrics-grafana-explore-runtime-overview-alt.png)
296+
297+
#### 4. Среда выполнения .NET подробно
298+
299+
Панели GC (размер кучи после сборки, паузы JIT, объём скомпилированного IL, методы), блокировки монитора, CPU процесса, working set, очередь thread pool. По графикам видно старт приложения (всплеск JIT) и затем устойчивое состояние под нагрузкой DemoTraffic.
300+
301+
![Grafana Metrics: GC, JIT, CPU, память, thread pool](docs/screenshots/metrics-grafana-explore-dotnet-deep.png)
302+
303+
#### 5. Исходящий HTTP (`HttpClient`)
304+
305+
Метрики клиента: открытые соединения, длительность запросов, время в очереди, распределения по bucket’ам. Для этого API характерен цикл вызовов к самому себе (DemoTraffic через `127.0.0.1:8080`), поэтому видны стабильные исходящие запросы и один долгоживущий коннект.
306+
307+
![Grafana Metrics: HttpClient и thread pool (исходящие запросы)](docs/screenshots/metrics-grafana-explore-http-outbound.png)
308+
309+
#### 6. Входящий HTTP (Kestrel) и продуктовые счётчики
310+
311+
Серверная часть: активные запросы, длительность обработки, соединения Kestrel, очередь соединений. Внизу — кастомные счётчики домена (`order_tracking_catalog_orders_list_requests_total`, `order_tracking_catalog_order_detail_views_total`), которые считаются в коде и попадают в Prometheus через OTEL meter.
312+
313+
![Grafana Metrics: HTTP server, Kestrel, каталог заказов](docs/screenshots/metrics-grafana-explore-http-server-business.png)
314+
315+
#### 7. Метаданные scrape и здоровье цели в Grafana
316+
317+
Показатели самого процесса scraping’а: `scrape_duration_seconds`, число сэмплов, серии, а также **otel_scope_info**, **target_info** и **`up` = 1** для выбранного таргета. Подтверждает, что Grafana читает те же данные, что видит Prometheus, и что цель считается доступной.
318+
319+
![Grafana Metrics: scrape, OTEL scope, target_info, up](docs/screenshots/metrics-grafana-explore-scrape-target-health.png)
320+
321+
### Иллюстрации: логи (Loki, VictoriaLogs, VMUI)
322+
323+
Цепочка **OTLP → collector → Loki / VictoriaLogs** и типичные запросы разобраны в [**docs/logs-query-languages.md**](docs/logs-query-languages.md). Ниже — три скрина из поднятого стека; файлы в [`docs/screenshots/`](docs/screenshots/).
324+
325+
#### 1. Grafana → Loki: доставка статуса в UI (Broadcasted)
326+
327+
**Explore** или панель **Logs**, datasource **Loki**, режим **Code**, запрос:
328+
329+
```logql
330+
{job=~"order-tracking.*"} |= "Broadcasted"
331+
```
332+
333+
На скрине: гистограмма **Logs volume** и строки **Information** из **`OrderStatusKafkaConsumerHostedService`**: сообщение **Broadcasted status update**, переходы статусов заказа (**Old** / **New**), в теле OTLP — **`traceid`** и **`spanid`** (удобно искать ту же трассу в Jaeger).
334+
335+
![Grafana Loki: Broadcasted и trace context](docs/screenshots/logs-grafana-loki-broadcasted.png)
336+
337+
#### 2. Grafana → VictoriaLogs: outbox и EF в потоке логов
338+
339+
Тот же стек, datasource **VictoriaLogs**, широкий селектор по сервисам, например `{service.name=~"order-tracking.*"}`. В потоке видны структурированные записи **Entity Framework**: выполнение **`DbCommand`** с запросом к **`outbox_messages`** (`FOR UPDATE SKIP LOCKED`) — это фоновый **worker**, который по паттерну **transactional outbox** забирает сообщения перед публикацией в Kafka. Дополнительно могут проходить строки про scrape **`GET …/metrics`** — это нормальная фоновая активность наблюдаемости.
340+
341+
![Grafana VictoriaLogs: outbox, DbCommand, метрики worker](docs/screenshots/logs-grafana-victorialogs-outbox.png)
342+
343+
#### 3. VictoriaLogs VMUI (`:9428`): worker и outbox «как в логах целиком»
344+
345+
Нативный UI по адресу **http://localhost:9428**: запрос **`{service.name=~"order-tracking.*"}`** за последние минуты. На скрине явно выделен поток **`order-tracking-worker`**: периодический **`SELECT * FROM outbox_messages … FOR UPDATE SKIP LOCKED`**, ответы **`HTTP/1.1 GET http://worker:9464/metrics`** со статусом **200** — видно и бизнес-цикл outbox, и успешный scrape Prometheus с worker.
346+
347+
![VictoriaLogs VMUI: worker, outbox, /metrics](docs/screenshots/logs-victorialogs-vmui-worker.png)
348+
349+
### Иллюстрации: трейсы (Jaeger)
350+
351+
Подробный разбор UI, тегов и типичных имён операций — [**docs/traces-jaeger.md**](docs/traces-jaeger.md). Ниже три кадра **экрана поиска** (**http://localhost:16686**): два для **`order-tracking-api`** (диаграмма + список), один для **`order-tracking-worker`**. Имеет смысл приложить к отчёту вместе с [**деталью трассы**](docs/traces-jaeger.md) (`jaeger-trace-detail.png`), когда в дереве видны нужные спаны.
352+
353+
#### 1. API: диаграмма и список трасс
354+
355+
Сервис **`order-tracking-api`**, lookback **Last Hour**. Видны быстрые **`HEAD /health`**, **`GET`** и серии **`order_tracking`** — смешение HTTP и коротких трасс, связанных с инфраструктурой запросов к БД.
356+
357+
![Jaeger search: order-tracking-api, scatter и список](docs/screenshots/traces-jaeger-search-api-scatter.png)
358+
359+
#### 2. API: фрагмент списка (недавние трассы)
360+
361+
Тот же сервис: удобно показать в отчёте «живой» поток операций и пометку **1 Span** в строке — напоминание открыть трассу целиком или использовать **Tags** для поиска по Kafka / доменным полям.
362+
363+
![Jaeger search: order-tracking-api, список](docs/screenshots/traces-jaeger-search-api-list.png)
364+
365+
#### 3. Worker: фоновые трассы
366+
367+
Сервис **`order-tracking-worker`**: регулярные короткие трассы с операцией вроде **`order_tracking`** соответствуют циклу работы воркера с базой и **outbox**; детали спанов **`Outbox.Dispatch`** / **`Kafka.Produce`** — после перехода внутрь выбранной трассы.
368+
369+
![Jaeger search: order-tracking-worker](docs/screenshots/traces-jaeger-search-worker.png)
370+
279371
### Спаны в коде
280372

281373
- HTTP (ASP.NET Core), EF Core

deploy/observability/otel-collector-config.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ exporters:
2727
tls:
2828
insecure: true
2929

30-
elasticsearch:
31-
endpoints:
32-
- http://opensearch:9200
30+
# OpenSearch: отдельный экспортёр (elasticsearch-экспортёр с OS 2.x часто не создаёт индексы).
31+
opensearch:
32+
http:
33+
endpoint: http://opensearch:9200
34+
tls:
35+
insecure: true
36+
dataset: otel
37+
namespace: logs
3338
logs_index: otel-logs
3439
mapping:
3540
mode: ecs
@@ -52,4 +57,4 @@ service:
5257
logs:
5358
receivers: [otlp]
5459
processors: [batch]
55-
exporters: [loki, elasticsearch, otlphttp/victorialogs]
60+
exporters: [loki, opensearch, otlphttp/victorialogs]

docker-compose.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ services:
182182
environment:
183183
- ASPNETCORE_ENVIRONMENT=Development
184184
- ASPNETCORE_URLS=http://+:8080
185+
# Явная привязка Kestrel в Program.cs (0.0.0.0:8080) — как в smoke; без этого на части окружений healthcheck не попадает на слушатель
186+
- DOTNET_RUNNING_IN_CONTAINER=true
185187
# Пустое значение снимает дефолт образа (8080 через deferred endpoints), чтобы совпадало с app.Urls в Program.cs
186188
- ASPNETCORE_HTTP_PORTS=
187189
- ConnectionStrings__Postgres=Host=postgres;Port=5432;Database=order_tracking;Username=postgres;Password=postgres
@@ -197,7 +199,8 @@ services:
197199
- OpenTelemetry__Exporters__Console=false
198200
- DemoTraffic__Enabled=true
199201
- DemoTraffic__BaseUrl=http://127.0.0.1:8080
200-
- DemoTraffic__Rounds=2
202+
# Больше раундов — стабильнее Kafka / SignalR трассы в Jaeger после первых секунд up
203+
- DemoTraffic__Rounds=40
201204
- DemoTraffic__DelayMs=4000
202205
ports:
203206
- "5086:8080"
@@ -209,11 +212,11 @@ services:
209212
otel-collector:
210213
condition: service_started
211214
healthcheck:
212-
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1"]
215+
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://127.0.0.1:8080/health || exit 1"]
213216
interval: 10s
214217
timeout: 5s
215-
retries: 12
216-
start_period: 60s
218+
retries: 18
219+
start_period: 90s
217220

218221
worker:
219222
image: order-tracking-worker:local

docs/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717

1818
## Логи
1919

20-
[logs-query-languages.md](logs-query-languages.md) — OTLP → collector → Loki, OpenSearch, VictoriaLogs; LogQL, LogsQL, Lucene, DQL. Иллюстрации: `screenshots/loki-explore.png`, `victorialogs-query.png`, `opensearch-discover.png`.
20+
[logs-query-languages.md](logs-query-languages.md) — OTLP → collector → Loki, OpenSearch, VictoriaLogs; LogQL, LogsQL, Lucene, DQL. Иллюстрации: `screenshots/logs-grafana-loki-broadcasted.png`, `logs-grafana-victorialogs-outbox.png`, `logs-victorialogs-vmui-worker.png`, также `loki-explore.png`, `victorialogs-query.png`, `opensearch-discover.png`. Краткий блок с теми же скринами — в корневом [README.md](../README.md#наблюдаемость).
2121

2222
## Трейсы
2323

24-
[traces-jaeger.md](traces-jaeger.md) — OTLP, Jaeger UI, теги поиска, связь с логами. Иллюстрации: `screenshots/jaeger-search.png`, `jaeger-trace-detail.png`.
24+
[traces-jaeger.md](traces-jaeger.md) — OTLP, Jaeger UI, теги поиска, связь с логами. Иллюстрации: `screenshots/traces-jaeger-search-api-scatter.png`, `traces-jaeger-search-api-list.png`, `traces-jaeger-search-worker.png`, также `jaeger-search.png`, `jaeger-trace-detail.png`. Краткий блок — в корневом [README.md](../README.md#наблюдаемость).
2525

2626
## Grafana
2727

docs/logs-query-languages.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ flowchart LR
4141
logs:
4242
receivers: [otlp]
4343
processors: [batch]
44-
exporters: [loki, elasticsearch, otlphttp/victorialogs]
44+
exporters: [loki, opensearch, otlphttp/victorialogs]
4545
```
4646
4747
| Экспортёр | Назначение |
4848
|-----------|------------|
4949
| `loki` | Grafana Loki, **LogQL** |
50-
| `elasticsearch` | OpenSearch, индекс `otel-logs`, ECS mapping; **Lucene** и **DQL** в Dashboards |
50+
| `opensearch` | OpenSearch, индекс `otel-logs`, ECS mapping; **Lucene** и **DQL** в Dashboards |
5151
| `otlphttp/victorialogs` | VictoriaLogs, endpoint OTLP `/insert/opentelemetry/v1/logs`, **LogsQL** |
5252

5353
Три бэкенда получают одни и те же записи логов; имена полей после записи могут немного различаться.
@@ -87,6 +87,12 @@ sum(count_over_time({job=~"order-tracking.*"} |= "Broadcasted" [$__interval]))
8787

8888
Справка Grafana: [Log queries](https://grafana.com/docs/loki/latest/query/log_queries/).
8989

90+
**Пример из Grafana (Explore / Logs):** запрос `{job=~"order-tracking.*"} |= "Broadcasted"`, гистограмма **Logs volume** и развёрнутые OTLP-строки: **`OrderStatusKafkaConsumerHostedService`**, текст **Broadcasted status update**, поля **`traceid`** / **`spanid`**, смена статусов заказа.
91+
92+
![Grafana Loki: Broadcasted, consumer, trace id](screenshots/logs-grafana-loki-broadcasted.png)
93+
94+
Дополнительный пример Explore (автосъёмка в CI):
95+
9096
![Grafana Explore: Loki — пример запроса LogQL](screenshots/loki-explore.png)
9197

9298
---
@@ -122,6 +128,16 @@ sum(count_over_time({job=~"order-tracking.*"} |= "Broadcasted" [$__interval]))
122128

123129
![VictoriaLogs: запрос LogsQL в UI или Grafana](screenshots/victorialogs-query.png)
124130

131+
**Пример из Grafana (VictoriaLogs datasource):** широкий селектор `{service.name=~"order-tracking.*"}` — в ленте видны **`DbCommand`** Entity Framework с **`SELECT * FROM outbox_messages … FOR UPDATE SKIP LOCKED`** (worker, transactional outbox), а также служебные строки про scrape **`/metrics`**.
132+
133+
![Grafana VictoriaLogs: outbox, EF, worker](screenshots/logs-grafana-victorialogs-outbox.png)
134+
135+
### Веб-интерфейс VictoriaLogs (VMUI)
136+
137+
Помимо Grafana, у сервиса **`victorialogs`** есть свой UI: **`http://localhost:9428`**. Запрос **`{service.name=~"order-tracking.*"}`** за короткий интервал показывает поток **`order-tracking-worker`**: периодический опрос **outbox** и успешные **`GET http://worker:9464/metrics`** (ответ **200**) — то есть одновременно видно бизнес-цикл и доступность экспортёра метрик.
138+
139+
![VictoriaLogs VMUI: worker, outbox, scrape metrics](screenshots/logs-victorialogs-vmui-worker.png)
140+
125141
---
126142

127143
## 5. OpenSearch: **Lucene** и **DQL**

docs/traces-jaeger.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,35 @@ Jaeger не использует отдельный SQL-подобный язы
3333

3434
1. Service — выбрать `order-tracking-api` или `order-tracking-worker`.
3535
2. Lookback — интервал времени.
36-
3. Find Traces — список трасс.
36+
3. **Find Traces** — список трасс и диаграмма рассеяния (длительность × время).
37+
38+
### Примеры экрана поиска
39+
40+
Интерфейс: **http://localhost:16686**. В левой колонке задаются **Service**, **Operation** (часто `all`), **Lookback** (например **Last Hour**) и лимит результатов.
41+
42+
#### Поиск по сервису `order-tracking-api`
43+
44+
На диаграмме видно распределение длительностей трасс по времени; в списке ниже — отдельные операции. Типичные корневые имена в этом проекте:
45+
46+
- **`HEAD /health`** — проверки живости (короткие трассировки);
47+
- **`GET`** с усечённым в UI именем — входящие HTTP-запросы к API (список заказов, карточка и т.д.);
48+
- **`order_tracking`** (или похожее имя из инструментирования **EF Core** / БД) — отдельные короткие трассы, связанные с доступом к PostgreSQL и именем базы **`order_tracking`**.
49+
50+
В сводной строке Jaeger часто показывают **«1 Span»**: это значит, что в данной трассировке на момент записи виден один корневой спан (или одна «ветка» без дочерних в экспорте). Вложенные спаны **`Kafka.Consume`** / **`SignalR.Broadcast`** ищите **внутри конкретной трассы** (клик по строке → timeline / дерево) или через фильтр **Tags**, например `messaging.system=kafka`.
51+
52+
![Jaeger: поиск, сервис order-tracking-api — scatter и список](screenshots/traces-jaeger-search-api-scatter.png)
53+
54+
Тот же сервис, акцент на последних трассах и смешении операций (**`order_tracking`**, **`GET`**, **`HEAD /health`**):
55+
56+
![Jaeger: поиск по order-tracking-api — фрагмент списка](screenshots/traces-jaeger-search-api-list.png)
57+
58+
#### Поиск по сервису `order-tracking-worker`
59+
60+
Для worker выберите **Service → `order-tracking-worker`**. Часто доминируют короткие трассы с операцией вроде **`order_tracking`** — это периодический фон **опроса БД** и работы с **outbox** (в связке с доменным кодом и EF). Спаны **`Outbox.Dispatch`** и **`Kafka.Produce`** смотрите в **детальном виде** выбранной трассы; при пустом дереве проверьте нагрузку (DemoTraffic / смена статусов) и фильтры по тегам.
61+
62+
![Jaeger: поиск, сервис order-tracking-worker](screenshots/traces-jaeger-search-worker.png)
63+
64+
Кадр из автоматической съёмки документации (**Playwright**, см. [`tools/doc-screenshots`](../tools/doc-screenshots)):
3765

3866
![Jaeger: поиск трасс по сервису и интервалу](screenshots/jaeger-search.png)
3967

0 commit comments

Comments
 (0)