OpenTelemetry đã chạy thành công, nhưng tại sao lại phức tạp đến vậy?
(iconsolutions.com)- OpenTelemetry (OTel) là một framework và bộ công cụ về observability
- Các công cụ hiện có gồm Prometheus (metrics), Logstash (logs), OpenTracing (distributed tracing)
- OTel chuẩn hóa ba tín hiệu là metrics, logs và tracing, đồng thời cung cấp OpenTelemetry Protocol (OTLP), OpenTelemetry Collector và SDK cho nhiều ngôn ngữ
- Đáp ứng mọi từ khóa thời thượng như mã nguồn mở, độc lập nhà cung cấp, độc lập ngôn ngữ, phân tán, zero-code, v.v.
Những vấn đề của OTel
- Logs và metrics tương tự các công cụ hiện có nên có thể tích hợp dễ dàng. Chỉ cần thêm cấu hình là cũng có thể chuyển sang OTel
- Khó khăn trong việc triển khai tracing
- Context Propagation: cần thiết để truyền thông tin yêu cầu giữa các hệ thống phân tán
- Đơn vị yêu cầu được chia thành Trace và Span
- Ví dụ: nhấp nút "Mua hàng" → Frontend → Backend → mối quan hệ giữa các dịch vụ Payment/Shipping được biểu diễn bằng Span
- Cách OTel hỗ trợ:
- Cung cấp nhiều tiêu chuẩn Context Propagation khác nhau (ví dụ: b3, W3C Trace Context)
- OTel phải hỗ trợ nhiều tiêu chuẩn
- Khi chuyển từ OpenTracing hiện có sang OTel, có thể phát sinh xung đột ngoài dự kiến
- Lightbend Telemetry hỗ trợ logs và metrics của OpenTelemetry, nhưng không hỗ trợ tracing.
- Context Propagation: cần thiết để truyền thông tin yêu cầu giữa các hệ thống phân tán
Vấn đề xung đột giữa các API
Vấn đề tích hợp giữa Spring và Akka
- Spring: dùng để bootstrap ứng dụng và quản lý cấu hình
- Akka: dùng cho event sourcing, scheduling, clustering, v.v.
- Vấn đề:
- Khi dùng OTel, API tracing của Spring và Akka không tương tác với nhau
- Không thể chia sẻ cùng một Trace ID → kết quả tracing sai lệch
Giải pháp: OpenTracing Shim
- Công cụ chuyển OTel Tracer thành OpenTracing Tracer
- Vấn đề:
- Lightbend Telemetry của Akka không khớp với implementation OpenTracing
- Jaeger và OTel yêu cầu SpanContext khác nhau nên phát sinh xung đột
Quá trình giải quyết
Tích hợp thủ công giữa OTel và OpenTracing
- Chuyển OTel Context sang Jaeger SpanContext theo cách thủ công:
- Chèn OTel context vào Java Map
- Trích xuất map đó thành Jaeger SpanContext rồi thiết lập thủ công
- Ví dụ mã:
var otelContext = new HashMap<>(); GlobalOpenTelemetry.get().getPropagators().getTextMapPropagator() .inject(Context.current(), otelContext, (carrier, key, value) -> carrier.put(key, value)); var openTracingContext = new TextMapCodec(false).extract(new TextMapAdapter(otelContext)); GlobalExtendedTracer.get().local().activateContext(openTracingContext); - Kết quả:
- Tích hợp thành công dữ liệu tracing giữa Spring và Akka
- Trace được nối đúng cách qua các ranh giới HTTP
Kết luận
Nguyên nhân của sự phức tạp
- Cố gắng tích hợp hai thư viện tracing khác nhau
- Các tiêu chuẩn do OpenTelemetry cung cấp rất hữu ích, nhưng có thể phát sinh xung đột với các công cụ hiện có
Giá trị của OpenTelemetry
- OpenTelemetry đóng vai trò quan trọng trong việc chuẩn hóa observability
- Là một dự án mã nguồn mở phức tạp nhưng mạnh mẽ
Thách thức sắp tới
- Cần xác minh xem Trace Context của Akka có được truyền đúng giữa các thread hay không
- Cần thêm thử nghiệm và phản hồi để cải thiện dự án
1 bình luận
Ý kiến trên Hacker News
Trong lúc học và port Otel, tôi có cảm giác như quay lại thế giới Java. Việc lần theo code cho cảm giác kiểu EnterpriseFizzBuzz và gần như không có khả năng tự khám phá. Trên NodeJS, mức dùng CPU cao hơn khoảng 4 lần so với StatsD, và tôi đã giảm được bằng cách tự tổng hợp. OTEL không thân thiện với các ngôn ngữ dùng một tiến trình cho mỗi lõi CPU. Tốt hơn là nên dùng Prometheus.
Otel có thể tạo cảm giác phức tạp vì có SDK, agent và API do nhiều nhà cung cấp observability khác nhau cung cấp. OpenTelemetry đã trở thành tiêu chuẩn, và tôi đánh giá cao việc Grafana chấp nhận OpenTelemetry. Giá của Datadog đã trở nên mất kiểm soát ở khoảng giữa công ty quy mô vừa và doanh nghiệp lớn. Tài liệu có thể tốt hơn, và tài liệu onboarding khác nhau theo từng ngôn ngữ lập trình. Tôi đã tạo một gói khởi động nhanh OpenTelemetry cho stack NodeJS/Typescript cùng ví dụ về stack Grafana.
Tôi muốn có hỗ trợ log, trace và metric trong môi trường phát triển cục bộ nhưng không muốn chạy nhiều Docker image. Nhóm .NET đã phát hành .NET Aspire, và nhờ đó có thể trực quan hóa mọi thứ rất dễ trong stack phát triển cục bộ. Khi triển khai lên k8s, chỉ cần nối endpoint OTEL tới agent của DataDog là mọi thứ hoạt động. Tôi tránh thư viện trace và SDK tùy chỉnh của DataDog và dùng OTEL.
OpenTelemetry có thể phức tạp tùy theo nhu cầu. Nhóm của chúng tôi dùng khá đơn giản, sử dụng manual instrumentation để chọn lọc cẩn thận những gì cần quan sát. Chúng tôi dùng hai backend: một là dịch vụ bên thứ ba giá rẻ, cái còn lại là cài đặt Jaeger cho phát triển cục bộ.
Khi dùng Otel trong Python, nên dùng client của Logfire. Client do nhóm Pydantic tạo ra tốt hơn và đơn giản hơn nhiều so với thư viện Otel chính thức.
Nhiều web framework tự động xử lý phần lớn việc instrumentation. Nếu dùng opentelemetry-js và tự host thứ gì đó như Signoz thì có thể thu được rất nhiều dữ liệu chỉ trong chưa đầy một giờ.
Tôi đã bắt đầu một dự án mã nguồn mở có thể chạy bằng một lệnh duy nhất để giúp việc áp dụng OpenTelemetry dễ dàng hơn.
Nếu dùng stack tiêu chuẩn trong Python, bạn có thể tự động trace mọi thứ chỉ với vài import. Otel phức tạp vì nó được thiết kế cho các công ty bán phần mềm tương thích với Otel.
OpenTelemetry khởi đầu từ tracing, nhưng metric và log thì tốt hơn nên để cho các giải pháp chuyên biệt đảm nhiệm. Nỗ lực gom mọi thứ dưới một cái ô chung tạo cảm giác như vấn đề "leaky abstraction". Cơ sở dữ liệu SQL cũng có thể làm mọi thứ cùng lúc, nhưng điều đó không có nghĩa là nên làm vậy.