opentel

opentel implements github.com/tecnickcom/nurago/pkg/metrics.Client using OpenTelemetry for both metrics and tracing.

Part of nurago, a collection of independent Go packages for backend services.

import "github.com/tecnickcom/nurago/pkg/metrics/opentel"

Package opentel implements github.com/tecnickcom/nurago/pkg/metrics.Client using OpenTelemetry for both metrics and tracing.

It provides an OpenTelemetry-backed client with interface-compatible instrumentation hooks:

  • inbound HTTP handler instrumentation
  • outbound HTTP transport instrumentation
  • SQL open/instrumentation helpers with otelsql
  • log-level and error-taxonomy counters

At startup, New configures and registers global OpenTelemetry providers (tracer, meter, propagator), creates default counters, and records shutdown functions so callers can terminate exporters via Client.Close or Client.CloseCtx.

Defaults and Configuration

By default, exporter selection is environment-driven:

  • Traces: OTLP/HTTP when OTEL_EXPORTER_OTLP_TRACES_ENDPOINT or OTEL_EXPORTER_OTLP_ENDPOINT is set; otherwise stdout exporter.
  • Metrics: OTLP/HTTP when OTEL_EXPORTER_OTLP_METRICS_ENDPOINT or OTEL_EXPORTER_OTLP_ENDPOINT is set; otherwise stdout exporter.

Resource attributes are resolved from explicit parameters and environment, including OTEL_SERVICE_NAME, OTEL_SERVICE_VERSION, OTEL_DEPLOYMENT_ENVIRONMENT_NAME, and OTEL_RESOURCE_ATTRIBUTES.

When To Use

  • Your platform collects OTLP and you want traces and metrics from one client.
  • Trace context must propagate across service boundaries via W3C headers.

Example

// The default providers export over OTLP. The example substitutes
// providers that discard their output, so it needs no collector.
// Production code omits both options and configures the exporter through
// the standard OTEL_EXPORTER_OTLP_* environment variables.
meterFn := func(_ context.Context, res *sdkresource.Resource) (*sdkmetric.MeterProvider, error) {
	return sdkmetric.NewMeterProvider(
		sdkmetric.WithResource(res),
		sdkmetric.WithReader(sdkmetric.NewManualReader()),
	), nil
}

tracerFn := func(_ context.Context, res *sdkresource.Resource) (*sdktrace.TracerProvider, error) {
	return sdktrace.NewTracerProvider(sdktrace.WithResource(res)), nil
}

// The returned Client satisfies metrics.Client, so application code
// depends on the contract rather than on OpenTelemetry.
var client metrics.Client

client, err := opentel.New(
	context.TODO(),
	"payments",
	"v1.2.3",
	opentel.WithMeterProviderFn(meterFn),
	opentel.WithTracerProviderFn(tracerFn),
)
if err != nil {
	fmt.Println(err)

	return
}

defer func() { _ = client.Close() }()

// The path label must be a low-cardinality route template, never a raw
// request URI containing identifiers.
handler := client.InstrumentHandler("/users/{id}", func(w http.ResponseWriter, _ *http.Request) {
	w.WriteHeader(http.StatusOK)
})

rec := httptest.NewRecorder()
handler.ServeHTTP(rec, httptest.NewRequestWithContext(
	context.TODO(), http.MethodGet, "/users/42", nil,
))

client.IncErrorCounter("user", "read", "404")

// OpenTelemetry is push-based, so the metrics endpoint exposes no
// scrape payload and answers with a health-style 200.
scrape := httptest.NewRecorder()
client.MetricsHandlerFunc()(scrape, httptest.NewRequestWithContext(
	context.TODO(), http.MethodGet, "/metrics", nil,
))

fmt.Println(rec.Code, scrape.Code)

// Output:
// 200 200

Full source is in example_opentel_test.go. More runnable examples are on pkg.go.dev.

Dependencies

Importing this package pulls 28 external modules:

  • github.com/XSAM/otelsql
  • github.com/cenkalti/backoff/v5
  • github.com/cespare/xxhash/v2
  • github.com/felixge/httpsnoop
  • github.com/go-logr/logr
  • github.com/go-logr/stdr
  • github.com/google/uuid
  • github.com/grpc-ecosystem/grpc-gateway/v2
  • go.opentelemetry.io/auto/sdk
  • go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  • go.opentelemetry.io/otel
  • go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp
  • go.opentelemetry.io/otel/exporters/otlp/otlptrace
  • go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
  • go.opentelemetry.io/otel/exporters/stdout/stdoutmetric
  • go.opentelemetry.io/otel/exporters/stdout/stdouttrace
  • go.opentelemetry.io/otel/metric
  • go.opentelemetry.io/otel/sdk
  • go.opentelemetry.io/otel/sdk/metric
  • go.opentelemetry.io/otel/trace
  • go.opentelemetry.io/proto/otlp
  • golang.org/x/net
  • golang.org/x/sys
  • golang.org/x/text
  • google.golang.org/genproto/googleapis/api
  • google.golang.org/genproto/googleapis/rpc
  • google.golang.org/grpc
  • google.golang.org/protobuf