Files
zeekayandHanzo Dev 690dc8154a chore: delete the OTLP removal's leftovers
exporter_default.go was the default half of a //go:build pair whose grpc
half was deleted in 413feede4. Its errLegacyOTLPDisabled told a caller
holding Type=GRPC or Type=HTTP to migrate — and 66c2bb10b deleted those
constants, so no value reaching that branch has ever been a legacy OTLP
config. The only way in now is a raw cast of an unknown byte, for which
errUnknownExporterType already exists and says the true thing. One file,
one error var, one indirection gone; New's default branch returns the
right error directly.

ResolveCollectorAddr + envValue: born dead in 3ff36b828 and never called
anywhere in the workspace (grep across ~/work, including ignored files).
envValue is a stub returning "", so ResolveCollectorAddr could only ever
return "" — every service that wanted this wrote its own (hanzo/ai has
firstNonEmptyEnv). A helper that cannot work and has no callers.

var _ = net.IPv4zero: its own comment says it exists only to keep the
net import live. The import existed only for it. Both gone.

newZAPNativeExporter built a context with a 2s timeout, assigned it to
_, and cancelled it without dialing. Nothing observed it; the real
connect is exp.connect() below. Gone with the now-unused time import.

exporter_config.go's header explained that the type sits outside "the
tagged exporter files" so -tags otlp and -tags grpc builds share it.
There are no tagged exporter files and no such tags. A comment that
describes a build that cannot happen is worse than none.

Also gofmt -s the two test cases 66c2bb10b left misaligned; the repo's
CI runs a format check.

Build + go vet + go test clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 14:53:25 -07:00

99 lines
2.6 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package trace
import (
"context"
"fmt"
"io"
"time"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/trace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
const (
tracerExportTimeout = 10 * time.Second
// [tracerProviderShutdownTimeout] is longer than [tracerExportTimeout] so
// in-flight exports can finish before the tracer provider shuts down.
tracerProviderShutdownTimeout = 15 * time.Second
)
type Config struct {
ExporterConfig `json:"exporterConfig"`
// The fraction of traces to sample.
// If >= 1 always samples.
// If <= 0 never samples.
TraceSampleRate float64 `json:"traceSampleRate"`
AppName string `json:"appName"`
Version string `json:"version"`
}
type Tracer interface {
trace.Tracer
io.Closer
}
type tracer struct {
trace.Tracer
tp *sdktrace.TracerProvider
}
func (t *tracer) Close() error {
ctx, cancel := context.WithTimeout(context.Background(), tracerProviderShutdownTimeout)
defer cancel()
return t.tp.Shutdown(ctx)
}
// New returns a Tracer configured per config.
//
// ExporterConfig.Type semantics:
// - Disabled → Noop tracer, zero allocations on span ops.
// - ZAP → ZAP-native exporter — the only real export path. Ships
// spans as JSON inside ZAP envelopes to a collector at
// config.Endpoint (default 127.0.0.1:4317). No protobuf,
// no OTLP, no grpc.
// - anything else → not a transport this package can construct; an error.
func New(config Config) (Tracer, error) {
if config.ExporterConfig.Type == Disabled {
return Noop, nil
}
var (
exporter sdktrace.SpanExporter
err error
)
switch config.ExporterConfig.Type {
case ZAP:
exporter, err = newZAPNativeExporter(config.ExporterConfig, config.AppName, config.Version)
default:
err = fmt.Errorf("%w: %d", errUnknownExporterType, config.ExporterConfig.Type)
}
if err != nil {
return nil, err
}
tracerProviderOpts := []sdktrace.TracerProviderOption{
sdktrace.WithBatcher(exporter, sdktrace.WithExportTimeout(tracerExportTimeout)),
sdktrace.WithResource(resource.NewWithAttributes(semconv.SchemaURL,
attribute.String("version", config.Version),
semconv.ServiceNameKey.String(config.AppName),
)),
sdktrace.WithSampler(sdktrace.TraceIDRatioBased(config.TraceSampleRate)),
}
tracerProvider := sdktrace.NewTracerProvider(tracerProviderOpts...)
return &tracer{
Tracer: tracerProvider.Tracer(config.AppName),
tp: tracerProvider,
}, nil
}