Без єдиного стандарту телеметрії ви втрачаєте до 40% часу на пошук кореня проблеми: трейси в одному бекенді, метрики — в іншому, логи — в третьому. OpenTelemetry об'єднує все в один інтерфейс, заощаджуючи до 30% експлуатаційних витрат. Ми працюємо з цим стеком понад 5 років і впровадили його в 50+ проєктах — типова економія від впровадження становить суттєву суму на місяць за рахунок скорочення даунтайму.
Інструментування — це додавання в код точок спостереження: де починається операція, де закінчується, які атрибути вона несе, чи успішно завершилася. OpenTelemetry SDK стандартизує цей процес: один API для трейсів, метрик і логів, незалежно від того, куди в результаті підуть дані.
Два рівні інструментування існують для кожної мови. Automatic — агент/патч інструментує популярні бібліотеки без змін у коді. Manual — розробник явно створює spans для бізнес-логіки: «оформлення замовлення», «розрахунок знижки», «виклик зовнішнього API партнера». Автоматичне не замінює ручне — воно лише покриває інфраструктурний шар.
Чому варто обрати OpenTelemetry SDK для інструментування?
На відміну від пропрієтарних рішень (Datadog, New Relic), OpenTelemetry не прив'язує до вендора: ви можете змінювати бекенд (Prometheus, Jaeger, Grafana) без переписування коду. А ще це відкритий стандарт, який підтримують усі великі хмари та інструменти. Наші інженери сертифіковані за Kubernetes та OpenTelemetry — гарантуємо коректне налаштування з першого разу.
Ручне інструментування: правильні патерни
На Python з використанням context manager (правильний спосіб):
from opentelemetry import trace
from opentelemetry.trace import SpanKind
tracer = trace.get_tracer("order-service", "1.4.2")
def process_order(order_id: str, user_id: str) -> Order:
with tracer.start_as_current_span(
"order.process",
kind=SpanKind.INTERNAL,
attributes={
"order.id": order_id,
"user.id": user_id,
},
) as span:
try:
order = fetch_order(order_id)
span.set_attribute("order.total_amount", order.total)
span.set_attribute("order.items_count", len(order.items))
result = apply_discounts(order)
span.add_event("discounts_applied", {"discount_percent": result.discount_percent})
return result
except OrderNotFoundException as e:
span.record_exception(e)
span.set_status(trace.StatusCode.ERROR, str(e))
raise
record_exception() автоматично додає stack trace в span events. set_status(ERROR) — сигнал для бекендів і sampling-політик. Без явного ERROR статусу tail-based sampler може не зберегти span з винятком.
Метрики: Counter, Histogram, Gauge
from opentelemetry import metrics
meter = metrics.get_meter("order-service", "1.4.2")
# Лічильник запитів
order_counter = meter.create_counter(
"orders.created.total",
unit="1",
description="Total number of orders created"
)
# Гістограма часу обробки
processing_duration = meter.create_histogram(
"orders.processing.duration",
unit="ms",
description="Order processing duration"
)
def create_order(order_data):
start = time.monotonic()
order = _create_order_internal(order_data)
duration_ms = (time.monotonic() - start) * 1000
order_counter.add(1, {"order.type": order.type, "region": order.region})
processing_duration.record(duration_ms, {"order.type": order.type})Важливий момент з атрибутами метрик: кожна унікальна комбінація атрибутів — окрема time series у Prometheus. user.id як атрибут метрики — катастрофа для кардинальності. order.type з 5-10 значеннями — нормально.
Як уникнути висококардинальних метрик?
Використовуйте лише низькокардинальні атрибути: тип запиту, регіон, версія сервісу. Для унікальних ідентифікаторів (user_id, order_id) залишайте їх тільки в спанах, не в метриках. Це збереже продуктивність Prometheus і не перевантажить сховище.
Як інструментувати Java-застосунки?
Для Spring Boot доступні два шляхи: Auto-instrumentation через агент (рекомендується для старту):
-javaagent:opentelemetry-javaagent-2.x.jar
-Dotel.service.name=order-service
-Dotel.exporter.otlp.endpoint=http://otel-collector:4317
-Dotel.logs.exporter=otlpSpring Boot Starter для ручного інструментування — додайте залежність у pom.xml і використовуйте авто-wire Tracer через @Autowired. Приклад:
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
<version>2.3.0-alpha</version>
</dependency>Після цього ви можете впровадити OpenTelemetry та створювати спани для бізнес-логіки, як показано в документації.
Кореляція логів з трейсами
Щоб із Grafana Loki можна було перейти в конкретний trace, лог-рядки повинні містити trace_id та span_id. OTel надає хелпери для популярних бібліотек.
Python + structlog:
import structlog
from opentelemetry import trace
def add_trace_context(logger, method, event_dict):
span = trace.get_current_span()
if span.is_recording():
ctx = span.get_span_context()
event_dict["trace_id"] = format(ctx.trace_id, "032x")
event_dict["span_id"] = format(ctx.span_id, "016x")
return event_dict
structlog.configure(
processors=[add_trace_context, structlog.processors.JSONRenderer()]
) Порівняння автоматичного та ручного інструментування
| Параметр | Автоматичне | Ручне |
|---|---|---|
| Зміни в коді | Ні (підключається агент) | Так (додавання спанів) |
| Охоплення бізнес-логіки | Тільки інфраструктурні виклики | Повний контроль |
| Час впровадження на сервіс | 30 хвилин | 1–2 дні |
| Залежність від версій бібліотек | Так (агент під кожну версію) | Ні |
Ручне інструментування дає в 3 рази більше корисних даних для налагодження, але потребує дисципліни. Оптимально: автоматичне для швидкого старту + ручне для ключових операцій.
Рекомендовані бібліотеки для різних мов
| Мова | Auto-instrumentation | Manual SDK |
|---|---|---|
| Java | OpenTelemetry Java Agent | opentelemetry-java |
| Python | opentelemetry-distro | opentelemetry-api / SDK |
| Go | немає вбудованого аналога | opentelemetry-go |
| .NET | OpenTelemetry .NET AutoInstrumentation | OpenTelemetry .NET |
Вибір між auto та manual залежить від зрілості сервісу та потреб у деталізації.
Що входить у роботу з впровадження
- Аудит поточного коду та інфраструктури
- Налаштування OTel Collector з фільтрацією та семплінгом
- Інтеграція з бекендами (Prometheus, Loki, Jaeger)
- Написання контрактів телеметрії (документація за атрибутами та метриками)
- Навчання команди (воркшоп з інструментування та кореляції)
- Супровід протягом 2 тижнів після впровадження
Чек-лист завершення інструментування
- Усі зовнішні HTTP-виклики мають spans із
http.request.method,server.address,http.response.status_code - DB-операції:
db.system,db.name,db.statement(без credentials та PII) - Помилки записуються через
record_exception()таset_status(ERROR) -
trace_idпотрапляє в логи - Метрики не мають висококардинальних атрибутів (user_id, order_id)
- Span names — стабільні рядки, не містять динамічних ID
Докладніше про вибір семплінгу
Head-based sampling (наприклад, ProbabilisticSampler) вирішує, чи зберігати трейс на початку. Tail-based sampling (IdGenerator) приймає рішення після завершення, ґрунтуючись на помилках і тривалості. Для економії ресурсів використовуйте head-based з імовірністю 10%, а tail-based — для зберігання лише проблемних трейсів.Термін інструментування залежить від кількості сервісів і складності бізнес-логіки: від 2-3 днів на 3-5 сервісів до 1-2 тижнів на великий поліглот-стек. Зв'яжіться з нами — оцінимо ваш проєкт за 1 день і запропонуємо план впровадження. Замовте впровадження та отримайте 2 тижні підтримки безкоштовно.







