Что такое OpenTelemetry?
OpenTelemetry (OTel) — vendor-neutral open-source стандарт и набор инструментов для генерации, сбора и экспорта телеметрии (traces, metrics, logs). Проект CNCF, объединивший OpenTracing и OpenCensus.
Пример
┌─────────────────────────────────────────────────────────────────┐
│ Ваше приложение │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ OTel SDK │ │ Auto-instrum │ │ Manual spans │ │
│ │ (Traces, │ │ (JDBC, HTTP, │ │ (ваш код) │ │
│ │ Metrics, │ │ Kafka, gRPC)│ │ │ │
│ │ Logs) │ │ │ │ │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ └──────────────────┼─────────────────┘ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ OTLP Exporter │ │
│ └────────┬─────────┘ │
└───────────────────────────┼──────────────────────────────────────┘
│ OTLP (gRPC/HTTP)
▼
┌──────────────────┐
│ OTel Collector │
│ │
│ Receivers → Processors → Exporters │
└──┬──────────┬──────────┬───────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌────────┐ ┌────────┐
│ Jaeger │ │Promethe│ │ Loki │
│ Tempo │ │ us │ │ │
└─────────┘ └────────┘ └────────┘
Три сигнала OpenTelemetry
- Traces — распределённые трейсы (stable)
- Metrics — метрики с поддержкой Counter, Gauge, Histogram (stable)
- Logs — логи с корреляцией трейсами (stable с 2024)
Auto-instrumentation vs Manual
Auto-instrumentation — Java-агент, автоматически инструментирующий популярные библиотеки:
Пример
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=order-service \
-Dotel.exporter.otlp.endpoint=http://otel-collector:4317 \
-Dotel.traces.sampler=parentbased_traceidratio \
-Dotel.traces.sampler.arg=0.1 \
-jar order-service.jar
Поддерживаемые библиотеки (автоматически): Spring MVC/WebFlux, JDBC, Hibernate, Kafka, RabbitMQ, gRPC, OkHttp, RestTemplate, WebClient, Jedis, Lettuce, Logback, Log4j2.
Manual instrumentation — явное создание спанов
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
@Service
public class OrderService {
private final Tracer tracer;
public OrderService(OpenTelemetry openTelemetry) {
this.tracer = openTelemetry.getTracer("order-service");
}
public Order processOrder(OrderRequest request) {
Span span = tracer.spanBuilder("processOrder")
.setAttribute("order.type", request.getType())
.setAttribute("order.items.count", request.getItems().size())
.startSpan();
try (Scope scope = span.makeCurrent()) {
Order order = createOrder(request);
span.setAttribute("order.id", order.getId());
span.addEvent("Order validated");
processPayment(order);
span.addEvent("Payment processed");
return order;
} catch (Exception e) {
span.setStatus(StatusCode.ERROR, e.getMessage());
span.recordException(e);
throw e;
} finally {
span.end();
}
}
}
Конфигурация OTel Collector
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 5s
send_batch_size: 1024
memory_limiter:
check_interval: 1s
limit_mib: 512
attributes:
actions:
- key: environment
value: production
action: upsert
tail_sampling:
decision_wait: 10s
policies:
- name: errors-policy
type: status_code
status_code:
status_codes: [ERROR]
- name: slow-traces-policy
type: latency
latency:
threshold_ms: 500
- name: probabilistic-policy
type: probabilistic
probabilistic:
sampling_percentage: 5
exporters:
otlp/tempo:
endpoint: tempo:4317
tls:
insecure: true
prometheus:
endpoint: 0.0.0.0:8889
loki:
endpoint: http://loki:3100/loki/api/v1/push
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch, tail_sampling]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [prometheus]
logs:
receivers: [otlp]
processors: [memory_limiter, batch, attributes]
exporters: [loki]
OTel vs Vendor-specific решения
| Аспект | OpenTelemetry | Jaeger / Zipkin |
|---|---|---|
| Стандарт | Vendor-neutral (CNCF) | Специфичный формат |
| Сигналы | Traces + Metrics + Logs | Только traces |
| Переключение бэкенда | Изменение конфига exporter’а | Переписывание интеграций |
| Auto-instrumentation | Единый Java-агент | Отдельные библиотеки |
| Будущее | Активно развивается, стандарт индустрии | Jaeger v2 использует OTel SDK |
Важное
- OpenTelemetry — это стандарт и SDK, а не бэкенд для хранения. Данные экспортируются в Jaeger, Tempo, Datadog и т.д.
- OTel Collector — рекомендуемый промежуточный слой между приложениями и бэкендами. Позволяет менять бэкенд без изменения приложений.
- Auto-instrumentation покрывает 80-90% потребностей. Manual instrumentation нужен только для кастомной бизнес-логики.
- OTLP (OpenTelemetry Protocol) — единый протокол для всех сигналов (gRPC и HTTP).
Частые ошибки
- Смешивание OTel с Jaeger/Zipkin SDK: используйте только OTel SDK, а Jaeger/Tempo — только как бэкенд.
- Отправка напрямую в бэкенд без Collector: теряется возможность батчинга, семплирования, обогащения данных.
- Не настроен memory_limiter в Collector: при высокой нагрузке Collector может съесть всю память.
- Забыть про context propagation: OTel автоматически передаёт контекст для HTTP и gRPC, но для Kafka/RabbitMQ нужна дополнительная настройка.
Как используется в 2026
- OpenTelemetry — стандарт индустрии. Все крупные вендоры (Datadog, New Relic, Dynatrace, Splunk) поддерживают OTLP.
- OTel Java Agent 2.x — с поддержкой виртуальных потоков (Project Loom), нативных образов (GraalVM).
- OTel Logs — stable API, заменяет прямую интеграцию с Logstash/Fluentd.
- OTel Profiling — экспериментальный сигнал для continuous profiling.
- Spring Boot 3.x — нативная интеграция через Micrometer Observation API -> OTel bridge.
На собеседовании: ключевое — OTel является vendor-neutral стандартом, не бэкендом. Объясните роль Collector как промежуточного слоя. Покажите понимание разницы между auto-instrumentation (Java-агент) и manual instrumentation. Сильный ответ включает упоминание OTLP как единого протокола и трёх сигналов (traces, metrics, logs).