中文版文件 (Chinese Documentation) 推薦閱讀中文版,包含更詳細的使用說明和最佳實踐範例
github.com/Bofry/trace is a structured, severity-based distributed tracing library built on OpenTelemetry. It enhances standard OpenTelemetry spans with severity levels (DEBUG through EMERG) and provides fluent APIs for structured logging and cross-service trace propagation with Jaeger integration.
- 8-Level Severity System: Following syslog standard (DEBUG to EMERG)
- Fluent API: Intuitive method chaining for span operations
- Cross-Service Tracing: Complete distributed tracing context propagation
- Deferred Event System: Efficient event batching with flush-on-end
- No-op Detection: Automatic performance optimization for disabled tracing
go get github.com/Bofry/tracepackage main
import (
"context"
"github.com/Bofry/trace"
"log"
"time"
)
func main() {
// Create TracerProvider (OTLP - Recommended)
tp, err := trace.OTLPProvider("http://localhost:4318",
trace.ServiceName("my-service"),
trace.Environment("production"),
trace.Pid(),
)
if err != nil {
log.Fatal(err)
}
// Set as global provider
trace.SetTracerProvider(tp)
// Create tracer and span
tracer := trace.Tracer("main")
span := tracer.Open(context.Background(), "main-operation")
defer span.End()
// Use severity-based logging
span.Info("Operation started")
span.Debug("Debug info: %s", "some debug data")
// Record structured data
span.Argv(map[string]any{"user_id": 123, "action": "create"})
span.Reply(trace.PASS, "Operation completed")
// Graceful shutdown
defer func(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, time.Second*5)
defer cancel()
tp.Shutdown(ctx)
}(context.Background())
}graph TB
A[SeverityTracerProvider] --> B[SeverityTracer]
B --> C[SeveritySpan]
C --> D[SpanEvent]
A --> E[OpenTelemetry TracerProvider]
B --> F[OpenTelemetry Tracer]
C --> G[OpenTelemetry Span]
style A fill:#e1f5fe
style C fill:#f3e5f5
| Level | Value | Name | Usage |
|---|---|---|---|
| DEBUG | 0 | debug | Debug information |
| INFO | 1 | info | General information |
| NOTICE | 2 | notice | Important information |
| WARN | 3 | warn | Warning messages |
| ERR | 4 | err | Error messages |
| CRIT | 5 | crit | Critical errors |
| ALERT | 6 | alert | Immediate attention needed |
| EMERG | 7 | emerg | System unusable |
// Modern OTLP approach (recommended)
tp, err := trace.OTLPProvider("http://localhost:4318",
trace.ServiceName("my-service"),
trace.Environment("production"),
)
// Legacy Jaeger compatibility (auto-converts to OTLP)
tp, err := trace.JaegerCompatibleProvider("http://localhost:14268/api/traces",
trace.ServiceName("my-service"),
)// Root span - creates new trace
rootSpan := tracer.Open(ctx, "root-operation")
// Child span - inherits current context
childSpan := tracer.Start(parentSpan.Context(), "child-operation")
// Linked span - related but not parent-child
linkedSpan := tracer.Link(ctx, parentSpan.Link(), "linked-operation")
// Extracted span - from cross-service context
extractedSpan := tracer.Extract(ctx, carrier, "extracted-operation")sequenceDiagram
participant A as Service A
participant B as Service B
participant J as Jaeger
A->>A: Create Span
A->>A: span.Inject(carrier)
A->>B: HTTP Request + Headers
B->>B: tracer.Extract(carrier)
B->>B: Create Child Span
B->>J: Send Traces
A->>J: Send Traces
J->>J: Correlate Traces
// Service A - Inject context
carrier := make(propagation.MapCarrier)
span.Inject(nil, carrier)
// Pass through HTTP headers
for key, value := range carrier {
req.Header.Set(key, value)
}
// Service B - Extract context
carrier := make(propagation.MapCarrier)
for key, values := range req.Header {
if len(values) > 0 {
carrier.Set(key, values[0])
}
}
extractedSpan := tracer.Extract(ctx, carrier, "downstream-operation")docker run -d --name jaeger \
-p 16686:16686 \
-p 14268:14268 \
-p 4317:4317 \
-p 4318:4318 \
jaegertracing/all-in-one:latest# Copy test environment file
cp trace_test.env.sample trace_test.env
# Edit with your Jaeger endpoints
# JAEGER_TRACE_URL=http://127.0.0.1:14268/api/traces
# JAEGER_QUERY_URL=http://127.0.0.1:16686/api/traces# Standard development sequence
go mod tidy # Clean up dependencies
go fmt ./... # Format all code
go vet ./... # Static analysis
go test ./... # Run all tests
# Additional testing
go test -cover ./... # Coverage analysis
go test -race ./... # Race condition detection- No-op Detection: Automatically optimizes performance when tracing is disabled
- Event Batching: Deferred event processing with flush-on-end
- Atomic Operations: Thread-safe global state management
- Lazy Evaluation: Attributes constructed only when needed
- Test Coverage: 90.7% (89/89 tests passing)
- Total Test Files: 5 comprehensive test suites
- Benchmark Tests: 20 performance benchmarks
BenchmarkSeveritySpan_Debug 42,077,848 28.44 ns/op 72 B/op 2 allocs/op
BenchmarkSeveritySpan_Info 43,334,922 27.89 ns/op 72 B/op 2 allocs/op
BenchmarkSeveritySpan_Warning 44,706,405 27.77 ns/op 72 B/op 2 allocs/op
BenchmarkSeveritySpan_NoopSpan 41,718,452 27.13 ns/op 72 B/op 2 allocs/op
BenchmarkExpandObject_String 72,578,631 16.97 ns/op 64 B/op 1 allocs/op
BenchmarkExpandObject_Map 3,132,738 384.5 ns/op 640 B/op 15 allocs/op
BenchmarkSpanFromContext 450,409,731 2.676 ns/op 0 B/op 0 allocs/op
BenchmarkSpanEvent_Creation 100,000,000 10.62 ns/op 8 B/op 0 allocs/op
BenchmarkNoopEvent_Operations 665,452,064 1.811 ns/op 0 B/op 0 allocs/op
- Recording Span: ~28ns per operation, 72 bytes allocated
- Context Operations: ~3ns per operation, zero allocations
- Event Creation: ~11ns per operation, minimal allocations
- No-op Operations: ~2ns per operation, zero allocations
SeverityTracerProvider: Enhanced tracer providerSeverityTracer: Creates severity-enabled spansSeveritySpan: Span with severity logging methodsSpanEvent: Deferred event systemSeverity: 8-level severity enum
OTLPProvider(endpoint, attrs...): RECOMMENDED - OTLP HTTP providerOTLPGRPCProvider(endpoint, attrs...): OTLP gRPC providerJaegerCompatibleProvider(url, attrs...): Legacy Jaeger compatibility layer (auto-converts endpoints to OTLP)
- Severity Logging:
Debug(),Info(),Notice(),Warning(),Crit(),Alert(),Emerg() - Data Recording:
Argv(),Reply(),Tags(),Err() - Context Operations:
Inject(),Link(),Context()
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.
Note: This library uses modern OTLP protocol as the primary transport.
For Jaeger compatibility, use JaegerCompatibleProvider which automatically
converts Jaeger endpoints to OTLP (port 14268→4318, 14250→4317).