tracing

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 6, 2026 License: Apache-2.0 Imports: 15 Imported by: 3

README

tracing-kit

Go Reference Go Report Card License codecov

中文文档

A lightweight Go library for OpenTelemetry distributed tracing. This toolkit provides simple and easy-to-use APIs for trace context propagation, span management, and tracer initialization with OTLP export support.

Features

  • Tracer Initialization - Easy setup of OpenTelemetry tracer with OTLP HTTP exporter
  • Span Management - Simple APIs for creating, configuring, and managing spans
  • Context Propagation - Extract and inject trace context for distributed tracing
  • Attribute Support - Set span attributes with type-safe methods
  • Error Recording - Record errors with automatic status setting
  • Test Helpers - Utilities for testing tracing code with in-memory exporters

Installation

go get github.com/soulteary/tracing-kit

Quick Start

Initialize Tracer
import tracing "github.com/soulteary/tracing-kit"

func main() {
    // Initialize tracer with OTLP endpoint
    tp, err := tracing.InitTracer("my-service", "v1.0.0", "localhost:4318")
    if err != nil {
        log.Fatal(err)
    }
    defer func() {
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
        tracing.Shutdown(ctx)
    }()

    // Check if tracing is enabled
    if tracing.IsEnabled() {
        log.Println("Tracing is enabled")
    }
}
Create and Manage Spans
import (
    tracing "github.com/soulteary/tracing-kit"
    "go.opentelemetry.io/otel/codes"
    "go.opentelemetry.io/otel/trace"
)

func processRequest(ctx context.Context) error {
    // Start a new span
    ctx, span := tracing.StartSpan(ctx, "process.request")
    defer span.End()

    // Set string attributes
    tracing.SetSpanAttributes(span, map[string]string{
        "request.id":   "12345",
        "request.type": "api",
    })

    // Set mixed type attributes
    tracing.SetSpanAttributesFromMap(span, map[string]interface{}{
        "user.id":       42,
        "request.size":  int64(1024),
        "response.time": 0.125,
        "cached":        true,
    })

    // Simulate some work
    if err := doWork(ctx); err != nil {
        // Record error on span
        tracing.RecordError(span, err)
        return err
    }

    // Set success status
    tracing.SetSpanStatus(span, codes.Ok, "request processed successfully")
    return nil
}

func doWork(ctx context.Context) error {
    // Create a child span
    ctx, span := tracing.StartSpan(ctx, "do.work", 
        trace.WithSpanKind(trace.SpanKindInternal))
    defer span.End()

    // Get span from context
    currentSpan := tracing.GetSpanFromContext(ctx)
    currentSpan.AddEvent("work started")

    // ... do actual work ...

    return nil
}
Trace Context Propagation
import tracing "github.com/soulteary/tracing-kit"

// Extract trace context from incoming request headers
func handleIncomingRequest(headers map[string]string) {
    ctx := tracing.ExtractTraceContext(context.Background(), headers)
    
    // Continue with extracted context
    ctx, span := tracing.StartSpan(ctx, "handle.request")
    defer span.End()
    
    // Process request...
}

// Inject trace context into outgoing request headers
func makeOutgoingRequest(ctx context.Context) {
    headers := make(map[string]string)
    tracing.InjectTraceContext(ctx, headers)
    
    // Use headers for outgoing HTTP request
    // req.Header.Set("traceparent", headers["traceparent"])
}

// Round-trip example for distributed tracing
func propagateTrace(ctx context.Context) {
    // Service A: Inject context
    headers := make(map[string]string)
    tracing.InjectTraceContext(ctx, headers)
    
    // ... send request to Service B ...
    
    // Service B: Extract context and continue trace
    ctx = tracing.ExtractTraceContext(context.Background(), headers)
    ctx, span := tracing.StartSpan(ctx, "service.b.operation")
    defer span.End()
}
HTTP Middleware Example
import (
    tracing "github.com/soulteary/tracing-kit"
    "net/http"
)

func TracingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Extract trace context from headers
        headers := make(map[string]string)
        for k, v := range r.Header {
            if len(v) > 0 {
                headers[k] = v[0]
            }
        }
        ctx := tracing.ExtractTraceContext(r.Context(), headers)
        
        // Start span for this request
        ctx, span := tracing.StartSpan(ctx, r.Method+" "+r.URL.Path)
        defer span.End()
        
        // Set request attributes
        tracing.SetSpanAttributes(span, map[string]string{
            "http.method": r.Method,
            "http.url":    r.URL.String(),
            "http.host":   r.Host,
        })
        
        // Continue with traced context
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

API Reference

Tracer Initialization
Function Description
InitTracer(serviceName, version, endpoint) Initialize tracer with OTLP HTTP exporter
Shutdown(ctx) Gracefully shutdown the tracer provider
GetTracer() Get the global tracer (returns noop if not initialized)
IsEnabled() Check if tracing is enabled
Span Operations
Function Description
StartSpan(ctx, name, opts...) Start a new span
SetSpanAttributes(span, attrs) Set string attributes on a span
SetSpanAttributesFromMap(span, attrs) Set mixed-type attributes on a span
RecordError(span, err) Record an error and set error status
SetSpanStatus(span, code, description) Set the span status
GetSpanFromContext(ctx) Retrieve span from context
Context Propagation
Function Description
ExtractTraceContext(ctx, headers) Extract trace context from headers
InjectTraceContext(ctx, headers) Inject trace context into headers

Configuration

The tracer can be configured through environment variables or programmatically:

Environment Variable Description Default
OTEL_SERVICE_NAME Service name (overridden by parameter) -
OTEL_EXPORTER_OTLP_ENDPOINT OTLP endpoint (use parameter instead) -

Example with environment detection:

tp, err := tracing.InitTracer(
    "my-service",
    "v1.0.0",
    os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"),
)

Test Coverage

This project maintains 100% test coverage:

File Coverage
tracing.go 100%
span.go 100%
propagation.go 100%
test_helpers.go 100%
Total 100%

Run tests with coverage:

go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out

Testing Support

The library provides test helpers for unit testing:

import (
    tracing "github.com/soulteary/tracing-kit"
    "testing"
)

func TestMyTracedFunction(t *testing.T) {
    // Setup test tracer with in-memory exporter
    tp, exporter := tracing.SetupTestTracer(t)
    defer func() {
        tracing.ShutdownTracerProvider(tp)
        tracing.TeardownTestTracer()
    }()

    // Run your traced code
    ctx := context.Background()
    ctx, span := tracing.StartSpan(ctx, "test.operation")
    span.End()

    // Flush and verify spans
    tracing.ForceFlushTracerProvider(tp)
    spans := exporter.GetSpans()
    
    if len(spans) == 0 {
        t.Fatal("Expected at least one span")
    }
}

Requirements

  • Go 1.21 or later
  • OpenTelemetry Go SDK v1.39.0+

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExtractTraceContext

func ExtractTraceContext(ctx context.Context, headers map[string]string) context.Context

ExtractTraceContext extracts trace context from headers

func ForceFlushTracerProvider

func ForceFlushTracerProvider(tp *sdktrace.TracerProvider)

ForceFlushTracerProvider safely flushes a tracer provider, ignoring errors in test cleanup

func GetSpanFromContext

func GetSpanFromContext(ctx context.Context) trace.Span

GetSpanFromContext retrieves a span from context

func GetTracer

func GetTracer() trace.Tracer

GetTracer returns the global tracer

func InitTracer

func InitTracer(svcName, serviceVersion, otlpEndpoint string) (*sdktrace.TracerProvider, error)

InitTracer initializes OpenTelemetry tracer

func InjectTraceContext

func InjectTraceContext(ctx context.Context, headers map[string]string)

InjectTraceContext injects trace context into headers

func IsEnabled

func IsEnabled() bool

IsEnabled returns whether tracing is enabled

func RecordError

func RecordError(span trace.Span, err error)

RecordError records an error on a span

func ResetHooks added in v1.0.0

func ResetHooks()

ResetHooks resets the hook functions to their default implementations

func SetOtlptraceNewFunc added in v1.0.0

func SetOtlptraceNewFunc(fn func(ctx context.Context, client otlptrace.Client) (*otlptrace.Exporter, error))

SetOtlptraceNewFunc sets a custom otlptrace.New function for testing

func SetResourceNewFunc added in v1.0.0

func SetResourceNewFunc(fn func(ctx context.Context, opts ...resource.Option) (*resource.Resource, error))

SetResourceNewFunc sets a custom resource.New function for testing

func SetSpanAttributes

func SetSpanAttributes(span trace.Span, attrs map[string]string)

SetSpanAttributes sets attributes on a span

func SetSpanAttributesFromMap

func SetSpanAttributesFromMap(span trace.Span, attrs map[string]interface{})

SetSpanAttributesFromMap sets attributes from a map with various value types

func SetSpanStatus

func SetSpanStatus(span trace.Span, code codes.Code, description string)

SetSpanStatus sets the status of a span

func SetupTestTracer

func SetupTestTracer(t *testing.T) (*sdktrace.TracerProvider, *tracetest.InMemoryExporter)

SetupTestTracer sets up a tracer for testing

func Shutdown

func Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the tracer provider

func ShutdownTracerProvider

func ShutdownTracerProvider(tp *sdktrace.TracerProvider)

ShutdownTracerProvider safely shuts down a tracer provider, ignoring errors in test cleanup

func StartSpan

func StartSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span)

StartSpan starts a new span with the given name

func TeardownTestTracer

func TeardownTestTracer()

TeardownTestTracer cleans up the tracer

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL