<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Jaeger on DevOps-инженер &amp; CloudAdmin</title><link>https://ru-admin.github.io/ru/tags/jaeger/</link><description>Recent content in Jaeger on DevOps-инженер &amp; CloudAdmin</description><generator>Hugo -- gohugo.io</generator><language>ru-RU</language><atom:link href="https://ru-admin.github.io/ru/tags/jaeger/index.xml" rel="self" type="application/rss+xml"/><item><title>Observability и Telemetry для .NET Backend</title><link>https://ru-admin.github.io/ru/posts/sre-observability/dotnet-telemetry-observability/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://ru-admin.github.io/ru/posts/sre-observability/dotnet-telemetry-observability/</guid><description>&lt;h2 id="observability-для-net-backend-интеграция-телеметрии-и-оптимизация-производительности"&gt;Observability для .NET Backend: интеграция телеметрии и оптимизация производительности&lt;/h2&gt;
&lt;hr&gt;
&lt;h4 id="клиент"&gt;Клиент&lt;/h4&gt;
&lt;p&gt;E-commerce платформа с высоконагруженным .NET 8 бэкендом&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="задача"&gt;Задача&lt;/h4&gt;
&lt;p&gt;У .NET бэкенда не было наблюдаемости — никакого распределённого трассинга, централизованных метрик, структурированного логирования. Поиск медленных запросов требовал ручного разбора логов. Команда нуждалась в полном внедрении OpenTelemetry: проброс трейсов от Ingress через .NET к downstream-сервисам (PostgreSQL, Redis, RabbitMQ, HTTP upstreams), автоматическое обнаружение медленных запросов и путь к оптимизации P99 latency.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="решение"&gt;Решение&lt;/h4&gt;
&lt;h6 id="1-интеграция-opentelemetry-в-net-8"&gt;1. Интеграция OpenTelemetry в .NET 8&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;Подключены NuGet-пакеты: &lt;code&gt;OpenTelemetry.Extensions.Hosting&lt;/code&gt;, &lt;code&gt;Instrumentation.AspNetCore&lt;/code&gt;, &lt;code&gt;Instrumentation.Http&lt;/code&gt;, &lt;code&gt;Instrumentation.EntityFrameworkCore&lt;/code&gt;, &lt;code&gt;Instrumentation.StackExchangeRedis&lt;/code&gt;, &lt;code&gt;Instrumentation.Runtime&lt;/code&gt;, &lt;code&gt;Instrumentation.Process&lt;/code&gt;, &lt;code&gt;Exporter.OpenTelemetryProtocol&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Настроен &lt;code&gt;ActivitySource&lt;/code&gt; с инструментацией AspNetCore, HttpClient, EF Core, Redis&lt;/li&gt;
&lt;li&gt;Включён проброс W3C &lt;code&gt;traceparent&lt;/code&gt;; добавлен middleware для возврата &lt;code&gt;X-Trace-Id&lt;/code&gt; в заголовках ответа&lt;/li&gt;
&lt;li&gt;Экспорт через OTLP/gRPC в OTel Collector (&lt;code&gt;:4317&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="2-инфраструктурный-слой-kubernetes--nginx--otel-collector"&gt;2. Инфраструктурный слой (Kubernetes / Nginx / OTel Collector)&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nginx/Ingress&lt;/strong&gt;: инъекция заголовков &lt;code&gt;traceparent&lt;/code&gt;/&lt;code&gt;tracestate&lt;/code&gt; для проброса W3C контекста&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;K8s Deployment&lt;/strong&gt;: переменные окружения &lt;code&gt;OTEL_SERVICE_NAME&lt;/code&gt;, &lt;code&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;/code&gt;, конфиг семплирования (&lt;code&gt;parentbased_traceidratio&lt;/code&gt; 20%)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OTel Collector&lt;/strong&gt;: Tail-based sampling процессор — всегда захватываем ошибки (status_code: ERROR), медленные запросы (&amp;gt;1с latency), вероятностные 5% остальных; дропаем health checks&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="3-методология-поиска-медленных-запросов"&gt;3. Методология поиска медленных запросов&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Top-N Slow Endpoints (P95/P99)&lt;/strong&gt;: Grafana дашборды с &lt;code&gt;histogram_quantile(0.99, sum(rate(http_server_request_duration_seconds_bucket[5m])) by (le, http_route))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flame Graphs &amp;amp; Span Waterfall&lt;/strong&gt;: Анализ разбивки трейса — Middleware → Controller → EF Core → Downstream API → Serialization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runtime Metrics&lt;/strong&gt;: Мониторинг длины очереди ThreadPool, частоты Gen 2 GC, аллокаций для детекта sync-over-async блокировок&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Live Profiling&lt;/strong&gt;: &lt;code&gt;dotnet-trace&lt;/code&gt; + Speedscope/PerfView для CPU сэмплинга на проде под нагрузкой&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="4-чек-лист-оптимизаций"&gt;4. Чек-лист оптимизаций&lt;/h6&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Категория&lt;/th&gt;
&lt;th&gt;Применённые фиксы&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;База данных&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Добавлены недостающие индексы (EXPLAIN ANALYZE), устранено N+1 через &lt;code&gt;.Include()&lt;/code&gt;/&lt;code&gt;.Select()&lt;/code&gt;, &lt;code&gt;.AsNoTracking()&lt;/code&gt; для read-only, настроен connection pooling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;I/O &amp;amp; Сеть&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Полный перевод на async/await с CancellationToken, убраны &lt;code&gt;.Result&lt;/code&gt;/&lt;code&gt;.Wait()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Аллокации и GC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ArrayPool&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Memory&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;ReadOnlySpan&amp;lt;T&amp;gt;&lt;/code&gt;, стриминг JSON в &lt;code&gt;Response.BodyWriter&lt;/code&gt;, включён Server GC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Кэширование&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Redis distributed cache (FusionCache), OutputCaching для HTTP-ответов&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP Clients&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;IHttpClientFactory&lt;/code&gt; / singleton &lt;code&gt;SocketsHttpHandler&lt;/code&gt; с &lt;code&gt;PooledConnectionLifetime=15m&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h4 id="технологии"&gt;Технологии&lt;/h4&gt;
&lt;div class="row"&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/dotnet.svg" alt=".NET"&gt;&lt;div&gt;.NET 8&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/opentelemetry.svg" alt="OpenTelemetry"&gt;&lt;div&gt;OpenTelemetry&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/kubernetes-plain.svg" alt="Kubernetes"&gt;&lt;div&gt;Kubernetes&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/prometheus-original.svg" alt="Prometheus"&gt;&lt;div&gt;Prometheus&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/grafana-original.svg" alt="Grafana"&gt;&lt;div&gt;Grafana&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/jaeger.svg" alt="Jaeger"&gt;&lt;div&gt;Jaeger&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/postgresql.svg" alt="PostgreSQL"&gt;&lt;div&gt;PostgreSQL&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/redis.svg" alt="Redis"&gt;&lt;div&gt;Redis&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/rabbitmq.svg" alt="RabbitMQ"&gt;&lt;div&gt;RabbitMQ&lt;/div&gt;&lt;/div&gt;
&lt;div class="col-4 col-lg-2 pt-2" style="text-align: center;"&gt;&lt;img src="https://ru-admin.github.io/icons/helm-original.svg" alt="Helm"&gt;&lt;div&gt;Helm&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h4 id="результаты"&gt;Результаты&lt;/h4&gt;
&lt;p&gt;✅ &lt;strong&gt;Полное покрытие трейсами:&lt;/strong&gt; 100% запросов имеют &lt;code&gt;traceparent&lt;/code&gt;, &lt;code&gt;X-Trace-Id&lt;/code&gt; возвращается клиентам&lt;br&gt;
✅ &lt;strong&gt;P99 latency снижен:&lt;/strong&gt; с 2.3с до 420мс (улучшение 82%) после оптимизации топ-5 эндпоинтов&lt;br&gt;
✅ &lt;strong&gt;Обнаружение ошибок:&lt;/strong&gt; Tail-sampling захватывает 100% 5xx ошибок и запросов &amp;gt;1с даже при 20% sample rate&lt;br&gt;
✅ &lt;strong&gt;Проактивный алертинг:&lt;/strong&gt; Настроены алерты на P99 &amp;gt; SLA и скачки error-rate в Grafana/Alertmanager&lt;br&gt;
✅ &lt;strong&gt;Оптимизация БД:&lt;/strong&gt; N+1 устранено, индексы добавлены, пул соединений настроен — EF Core спалы снизились на 65%&lt;br&gt;
✅ &lt;strong&gt;ThreadPool здоров:&lt;/strong&gt; Длина очереди около нуля под пиковой нагрузкой; sync-over-async устранён&lt;br&gt;
✅ &lt;strong&gt;Нагрузочное тестирование:&lt;/strong&gt; k6 soak-тест подтверждает стабильный P99 под 2x ожидаемого RPS&lt;/p&gt;</description></item></channel></rss>