Трейсингът е метод за наблюдение на потока на заявки през разпределена система, при който всяка стъпка на обработка се записва като отделно събитие с времеви печат. Според данните на OpenTelemetry, 2025, trace обединява пълния път на заявката от точката на вход до крайния отговор, преминавайки през всички микроуслуги и външни призови. Това позволява на разработчиците да идентифицират уски места, забавяния и повреди в сложни архитектури на мобилни backend-ове.
Основни моменти
Трейсингът е метод за разпределено наблюдение, при който всяка входяща заявка се проследва през всички услуги и компоненти на система. За разлика от метриките, които показват агрегирани стойности (средно време за отговор, брой грешки), трейсингът запазва пълния контекст на една конкретна заявка.
Всяка стъпка на обработка — призов към база данни, HTTP заявка към друга микроуслуга, изпълнение на фонова задача — се записва като отделна единица с времеви печат, състояние и атрибути. Според данните на Google Dapper (оригинална публикация от 2010 г.), трейсингът позволява локализиране на забавяния в разпределени системи с точност до един призов.
Трейсингът е особено важен за мобилните приложения, където backend се състои от десетки микроуслуги. Потребителско действие — например, влязане в профил — може да премине през API Gateway, услугата за удостовяване, базата данни и Push услугата. Без trace е практически невъзможно да се определи кой компонент забавя отговора.
Основната единица на трейсинга е span. Всяка span представлява една логическа операция: HTTP заявка, SQL запитване, gRPC призов, JSON сериализация. Span съдържа уникален идентификатор, идентификатор на родителя, име на операцията, време на началото, продължителност, състояние и набор от атрибути.
Всички spanове, отнасящи се към една корена заявка, се обединяват в trace. Кореният span (root span) представлява точката на вход — HTTP заявка от мобилния клиент към API. Дочерните spanове образуват дърво, в което всяка span се позовава към родителя чрез полето parent_span_id.
Продължителността на trace е равна на сбора от продължителностите на уникалните времеви сегменти на всички spanове. Ако два дочерни spanа се изпълняват паралелно, времето им не се сумира — това е критично за правилния анализ на забавянията, причинени от паралелни призови на микроуслуги.
Всяка span може да съдържа атрибути — двойки ключ-стойност с метаинформация: URL на заявката, ID на потребителя, версия на API, име на хоста. Атрибутите се използват за филтриране и групиране на traceовете. Освен атрибутите, span подкрепя събития — времеви печати с текстово описание, например „пропуск на кеша“ или „опит за повторно свързване“.
Distributed tracing решава проблема за свързване на spanове, които се създават в различни процеси и на различни машини. Механизмът се базира на контекстно предаване: при призов на услуга B от услуга A, към изходящата заявка се добавя хедър с идентификатора на текущия trace и родителския span.
Стандартни протоколи за предаване на контекст — W3C Trace Context (хедъри traceparent и tracestate) и Zipkin B3 (хедъри X-B3-TraceId, X-B3-SpanId). W3C Trace Context е приет като стандарт от консорциума W3C през 2021 г. и се подкрепя от всички основни доставчици на телеметрия.
При получаване на заявката, услуга B извлича trace_id от хедъра и създава дочерен span с този trace_id. По този начин, след завършването на заявката, всички spanове от различни услуги се обединяват в един trace от страна на колектора. За това всяка услуга трябва да бъде инструментирана с една и съща библиотека за трейсинг.
В мобилното разработване контекстното предаване охварля не само backend-а, но и взаимодействието клиент-сървър. Мобилното приложение може да изпраща trace_id в хедъра на всяка API заявка, позволявайки свързване на клиентското действие с сървърната обработка. OpenTelemetry SDK за iOS и Android подкрепя автоматичното създаване и предаване на trace контекст чрез HTTP клиенти.
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
class TracingInterceptor : Interceptor {
private val tracer: Tracer = OpenTelemetry.getTracer("mobile-app")
override fun intercept(chain: Interceptor.Chain): Response {
val span = tracer.spanBuilder("HTTP POST /api/login")
.setParent(Context.current())
.startSpan()
return chain.proceed(chain.request())
.also { span.end() }
}
}
Представеният interceptor в Kotlin създава span за всяка HTTP заявка към сървъра. Родителският контекст се предава от викащия код чрез Context.current(), което позволява да се свърже клиентският trace с сървърния.
OpenTelemetry — де факто стандарт за събиране на trace данни. Предоставя единен API за генериране на spanове, автоматично инструментиране на популярни библиотеки и гъвкав механизъм за експорт на данни към различни backendове: Jaeger, Zipkin, Grafana Tempo, Datadog, New Relic.
OpenTelemetry подкрепя автоматично създаване на spanове за популярни рамки: Spring Boot, Ktor, Flask, Express, gRPC. Разработчикът трябва само да добави зависимост към проекта, и библиотеката самостоятелно прехварля входящите и изходящите заявки. Auto-instrumentation за Java използва javaagent, който модифицира bytecode в реално време без промяна на изходния код.
За мобилни платформи OpenTelemetry предоставя Swift SDK и Kotlin SDK. Те автоматично създават spanове за мрежови заявки (URLSession, OkHttp), работа с база данни (CoreData, Room) и фонови задачи. Разработчикът може да добавя потребителски spanове за бизнес логиката.
Събраните spanове се изпращат на колектора чрез протокол OTLP (OpenTelemetry Protocol). Колекторът може да буферира, филтрира и пренасочва данните към една или повече системи за съхранение. Според документацията на OpenTelemetry, типичното забавяне от генерирането на span до показването му на таблото е 2–5 секунди при използване на gRPC експорт.
import OpenTelemetryApi
import OpenTelemetrySdk
import URLSessionInstrumentation
let instrumentation = URLSessionInstrumentation()
instrumentation.enable()
let tracer = OpenTelemetry.instance.tracerFactory
.get("mobile-monitoring")
let span = tracer.spanBuilder("fetch-user-profile")
.setAttribute(key: "user.id", value: userId)
.startSpan()
span.end()
Кодът в Swift активира автоматичното инструментиране на мрежовия слой и създава потребителски span за операцията по получаване на потребителския профил. Атрибутът user.id позволява по-късно филтриране на traceовете по конкретен потребител.
В системи с високо натоварване е невъзможно да се трейсира всяка заявка — това би създало неприемлемо натоварване на хранилището и мрежата. Избирането на проби решава този проблем, като запазва само част от traceовете. Изборът на стратегия пряко повлиява пълнотата на данните и разходите за инфраструктура.
Решението за запазване на trace се взима в момента на неговото създаване — в корения span. Най-простият и най-разпространен подход: фиксиран процент заявки (например, 5%) се запазва, останалите се отхвърлят. Недостатък — не може да се гарантира, че редки грешки ще бъдат уловени. Probability sampler в OpenTelemetry подкрепя настройка на вероятност от 0,0 до 1,0.
Решението се отлага до завършването на всички spanове на trace-а. Анализаторът преценява дали trace съдържа грешки, превишаване на времето или интересни атрибути и едва тогава го запазва. Този подход изисква буфериране на всички spanове в колектора, което увеличава консумацията на памет. Според данните на Grafana Labs, tail-based sampling е 40–60% по-ефективен по отношение на цена за полезни данни в системи с редки, но критични грешки.
| Стратегия | Предимства | Недостатъци |
|---|---|---|
| Fixed probability | Простота, предвидимо натоварване | Пропуска редки събития |
| Rate limiting | Гарантиран обем данни | Неравномерно покритие |
| Tail-based | Уловяне на всички грешки | Висока консумация на памет |
| Adaptive | Баланс на разходите и покритието | Сложност на настройката |
Логването записва отделни събития с ниво на важност (info, warn, error), но не ги свързва в контекста на една заявка. Трейсингът, обратно, създава структурирано дърво от операции, принадлежащи на една заявка от край до край. На практика тези два подхода не се изключват, а се допълват.
Логовете са ефективни за подробен анализ на конкретна грешка: разработчикът вижда точното съобщение, стектрейса, стойностите на променливите. Трейсингът отговаря на въпроса „защо заявката отнима 5 секунди“ — показва коя микроуслуга или призов е отнел най-много време. Според данните на Honeycomb (2024), екиповете, които използват трейсинг заедно с логването, намират основната причина за инцидентите 2,3 пъти по-бързо.
Съвременният подход — observability — обединява trace-овете, метриките и логовете в едина система. OpenTelemetry подкрепя корелацията между тези три сигнала: всяка span може да съдържа препратки към свързани логове, а метриките могат да бъдат маркирани с trace_id за навигиране към конкретни trace-ове.
Често задавани въпроси
Мониторингът показва агрегирани метрики на системата — средно време за отговор, брой грешки на минута, натоварване на CPU. Трейсингът показва пътя на една конкретна заявка през всички компоненти. Мониторингът отговаря на въпроса „какво се случва“, трейсингът — „защо се случва“.
За производствените системи е достатъчно 1–5% от заявките при head-based sampling. Ако системата редко дава грешки, се препоръчва tail-based sampling с фокус върху улавянето на всички грешни trace-ове. За staging среда е допустимо да се трейсират 100% от заявките без ограничения.
Основните инструменти: Jaeger (решение на Uber, отворен код), Grafana Tempo (мащабируемо хранилище за trace), Datadog APM, New Relic Distributed Tracing, AWS X-Ray и Honeycomb. Всичките подкрепят стандарта OpenTelemetry за прием на данни.
Да, локалният трейсинг работи в рамките на един процес. OpenTelemetry SDK за iOS и Android създава spanове за локални операции: четене от база данни, обработка на изображения, мрежови заявки. Такива trace не са разпределени, но са полезни за диагностика на производителността на клиентската част.
Съвременните библиотеки за трейсинг добавят по-малко от 1% оверхед при head-based sampling. OpenTelemetry използва асинхронен експорт на данни, който не блокира основната нишка. За мобилните устройства се препоръчва да се ограничи честотата на създаването на spanове и да се използва стратегия на адаптивно избиране.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също