Documentation
¶
Overview ¶
Package otel exposes the OpenTelemetry HTTP middleware + tracer bootstrap helpers for craftgo runtimes. The package owns the global TracerProvider; HTTP instrumentation is gated by an atomic flag so a never-Init'd process pays one atomic load per request and nothing else.
Pick one of:
otel.InitDefault() // in-process spans, ids in logs only otel.Init(otel.WithStdoutExporter()) // JSON spans on stdout otel.Init(otel.WithOTLPgRPCExporter(ctx, "collector:4317")) otel.Init(otel.WithOTLPHTTPExporter(ctx, "http://collector:4318"))
Multiple exporter options can be stacked — every span is fanned to each registered processor (e.g. stdout for local debugging while OTLP runs against a real collector).
Index ¶
- Constants
- func Disable()
- func HTTPMiddleware(operation string) server.Middleware
- func Init(opts ...Option) (*sdktrace.TracerProvider, error)
- func InitDefault() *sdktrace.TracerProvider
- func InitFromConfig(ctx context.Context, c Config) (*sdktrace.TracerProvider, error)
- func IsEnabled() bool
- type Config
- type Option
Constants ¶
const ( ExporterNone = "none" ExporterStdout = "stdout" ExporterOTLPgRPC = "otlp_grpc" ExporterOTLPHTTP = "otlp_http" )
Config is the YAML-shaped tracer configuration the generated runtime hands to InitFromConfig. It mirrors the fields a project keeps in `config/config.yaml` under the `otel:` block so the call site reads like `craftotel.InitFromConfig(ctx, cfg.OTel)`. Defining the type here keeps the dispatch logic in the library (so projects do not re-implement the exporter switch in their own main.go) and gives the generated config package a canonical type to import. Exporter selector values for [Config.Exporter].
Variables ¶
This section is empty.
Functions ¶
func Disable ¶
func Disable()
Disable returns the middleware to no-op mode without dismantling any SDK configuration. Tests use this to isolate runs.
func HTTPMiddleware ¶
func HTTPMiddleware(operation string) server.Middleware
HTTPMiddleware returns a server.Middleware that wraps every request with `otelhttp.NewHandler` when the gate is open, and is a pass-through otherwise. operation is the span name surfaced when the wrapper is active.
Once the span is active on the request context, the middleware also injects the W3C trace context onto the response via the configured `OTel TextMapPropagator` (`otelapi.GetTextMapPropagator`). With the default `propagation.TraceContext{}` propagator that lands a standard `traceparent` (and `tracestate` when set) header on the response - the same wire format the spec uses for request propagation, so downstream services / clients can re-attach to the same trace tree without bespoke header handling. Headers are written BEFORE the downstream handler runs, which keeps them in the outbound response regardless of whether the handler streams or writes a single body.
Wire it with `srv.Use(otel.HTTPMiddleware("api"))`. Even on a disabled gate the call is cheap - a single atomic load - so it's fine to leave permanently in main.go.
func Init ¶
func Init(opts ...Option) (*sdktrace.TracerProvider, error)
Init wires a TracerProvider with the supplied options, installs it on the global slot, and flips the HTTP middleware gate ON. With zero options the provider has no exporter - spans get valid IDs but go nowhere, which is exactly what you want for `go run` sessions where the only observability signal needed is trace_id / span_id flowing into the logs.
Returns the configured provider so callers can shut it down via `provider.Shutdown(ctx)` during graceful termination - important for OTLP exporters so the final batch flushes before the process exits.
func InitDefault ¶
func InitDefault() *sdktrace.TracerProvider
InitDefault is the dev-friendly shorthand: no exporter, no resource customisation, just a TracerProvider that produces valid trace ids for log correlation. Production code calls Init with the exporters it actually needs.
func InitFromConfig ¶
InitFromConfig dispatches the exporter selection encoded in c. When c.Enabled is false the function returns (nil, nil) so the caller can keep its shutdown code single-pathed (a nil provider is a no-op Shutdown). Returns the active TracerProvider for graceful shutdown.
Types ¶
type Config ¶
type Config struct {
// Enabled flips both the TracerProvider install and the HTTP
// middleware gate. False is a complete no-op - no exporter, no
// span creation, no atomic load past the first.
Enabled bool `yaml:"enabled"`
// ServiceName surfaces in the OTel resource attribute
// `service.name`. Defaults to "craftgo-service" when blank.
ServiceName string `yaml:"serviceName"`
// Exporter selects the destination for spans:
// - "none" / "" - in-process spans only (ids in logs, no export)
// - "stdout" - JSON spans on stdout (debugging)
// - "otlp_grpc" - push to OTLP collector via gRPC
// - "otlp_http" - push to OTLP collector via HTTP/protobuf
Exporter string `yaml:"exporter"`
// Endpoint is the collector address for the OTLP exporters.
// Ignored for "none" / "stdout".
// - otlp_http: a full URL WITH scheme - the scheme picks transport
// security: `http://collector:4318` (plaintext) or
// `https://collector.example.com` (TLS).
// - otlp_grpc: a bare `host:port` (e.g. `collector:4317`, plaintext)
// OR a full URL whose scheme picks security
// (`https://collector:4317` for TLS).
Endpoint string `yaml:"endpoint"`
}
type Option ¶
type Option func(*config)
Option configures the TracerProvider built by Init. Each option either appends a SpanProcessor (stdout, OTLP gRPC, OTLP HTTP) or attaches resource metadata. Errors that occur while building exporters are captured on the config; the first error short-circuits the rest and surfaces from Init.
func WithOTLPHTTPExporter ¶
func WithOTLPHTTPExporter(ctx context.Context, endpoint string, opts ...otlptracehttp.Option) Option
WithOTLPHTTPExporter pushes spans to an OTLP collector via HTTP/protobuf. endpoint is the full URL, including scheme: `"http://collector:4318"` (plaintext) or `"https://collector.example.com"` (TLS). The URL SCHEME selects transport security - `http` connects insecurely, `https` uses TLS - so no separate insecure/TLS toggle is needed; pass `otlptracehttp.WithTLSClientConfig(...)` in opts only for a custom certificate.
The endpoint is wired via otlptracehttp.WithEndpointURL, which parses scheme + host + port + path so the scheme drives transport security and the host/port land correctly.
func WithOTLPgRPCExporter ¶
WithOTLPgRPCExporter pushes spans to an OTLP collector via gRPC. addr may be either:
- a bare `host:port` (e.g. `"otel-collector.observability:4317"`) — connects INSECURE (plain-text), the convention for collectors on a trusted local network; or
- a full URL whose SCHEME selects transport security — `http://host:4317` (plaintext) or `https://host:4317` (TLS).
The URL form lets a project enable TLS straight from config.yaml (`endpoint: https://...`) instead of needing code; pass `otlptracegrpc.WithTLSCredentials(...)` in opts for custom certs.
func WithServiceName ¶
WithServiceName attaches the supplied service.name to the TracerProvider's Resource so spans self-label correctly when shipped to a backend. Defaults to "craftgo" when no option is supplied.
func WithStdoutExporter ¶
func WithStdoutExporter() Option
WithStdoutExporter writes every span as a JSON object on stdout. Useful for local debugging where running a full collector is overkill - `tail -f` the program output and you have a span trace.