OpenTelemetry cho Go
Một hàm setup đọc biến OTEL_* chuẩn, otelhttp cho server và client, otelslog cho log có trace, và flush khi tắt tiến trình.
Go không có agent tự gắn, nên bạn thêm một hàm setup và bọc HTTP server, client. Exporter, resource và cách lấy mẫu vẫn lấy từ bộ biến chuẩn — không có gì riêng của Belvador được biên dịch vào.
Đã kiểm ngày 2026-10-24 với go 1.27.3, go.opentelemetry.io/otel v1.47.0, otelhttp v0.72.0, otelslog v0.21.0: traces đạt, logs đạt, log mang trace/span của request.
Cài đặt#
go get go.opentelemetry.io/otel \ go.opentelemetry.io/otel/sdk \ go.opentelemetry.io/otel/sdk/log \ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp \ go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp \ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp \ go.opentelemetry.io/contrib/bridges/otelslogSetup một lần#
Thêm file này vào package main. Nó dựng đường gửi traces và logs từ biến môi trường và trả về một hàm gửi nốt cả hai:
package mainimport ( "context" "errors" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/log/global" "go.opentelemetry.io/otel/propagation" sdklog "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace")func setupOTel(ctx context.Context) (func(context.Context) error, error) { res, err := resource.New(ctx, resource.WithFromEnv(), resource.WithTelemetrySDK(), resource.WithHost()) if err != nil { return nil, err } traceExp, err := otlptracehttp.New(ctx) if err != nil { return nil, err } logExp, err := otlploghttp.New(ctx) if err != nil { return nil, err } tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(traceExp), sdktrace.WithResource(res)) lp := sdklog.NewLoggerProvider(sdklog.WithProcessor(sdklog.NewBatchProcessor(logExp)), sdklog.WithResource(res)) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) global.SetLoggerProvider(lp) return func(ctx context.Context) error { return errors.Join(tp.Shutdown(ctx), lp.Shutdown(ctx)) }, nil}Dùng#
shutdown, err := setupOTel(ctx)if err != nil { log.Fatal(err)}defer shutdown(context.Background()) // flushes on exitlogger := otelslog.NewLogger("my-service")client := &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}srv := &http.Server{Addr: ":8080", Handler: otelhttp.NewHandler(mux, "server")}// Inside a handler: pass r.Context() so the log line carries the request's span.logger.WarnContext(r.Context(), "payment declined", "order", orderID)otelhttp.NewHandlertạo một span server cho mỗi request và nối tiếp trace của bên gọi từtraceparent.otelhttp.NewTransporttạo một span client cho mỗi request đi ra và gửitraceparent, để dịch vụ tiếp theo vào cùng trace.otelslogbiến các lệnhlog/slogthành bản ghi log OpenTelemetry. Hãy dùng các hàm…Context(InfoContext,WarnContext,ErrorContext) với context của request: đó là cách bản ghi biết trace ID và span ID.logger.Warn(...)thường vẫn được gửi, nhưng không có hai ID đó.
Tắt tiến trình#
Gọi hàm được trả về trước khi tiến trình thoát — bộ gom giữ tới vài giây dữ liệu. Hãy xử lý SIGTERM (như signal.NotifyContext) để khi container dừng hay deploy cuốn chiếu, dữ liệu được gửi nốt thay vì mất lô cuối.
Thư viện khác#
Cùng cách đó cho gRPC (otelgrpc), driver cơ sở dữ liệu và framework có gói contrib riêng dưới go.opentelemetry.io/contrib/instrumentation/…. Chỉ net/http và log/slog nằm trong phần Belvador đã chạy.
Cùng SDK Go của Sentry#
Giữ sentry-go cho lỗi và để tracing tắt, để OpenTelemetry là bên duy nhất làm chủ tracing. sentryotel.NewOtelIntegration() gắn ID span vào lỗi được capture kèm context.Context của request — xem Cùng SDK Sentry; liên kết đó chưa được ghi là đã kiểm.
Thấy chỗ sai hoặc thiếu? Gửi cho chúng tôi: hello@belvador.dev