82 lines
1.6 KiB
Go
82 lines
1.6 KiB
Go
package tracing
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// Tracer provides distributed tracing
|
|
type Tracer struct {
|
|
serviceName string
|
|
}
|
|
|
|
// NewTracer creates a new tracer
|
|
func NewTracer(serviceName string) *Tracer {
|
|
return &Tracer{serviceName: serviceName}
|
|
}
|
|
|
|
// Span represents a trace span
|
|
type Span struct {
|
|
TraceID string
|
|
SpanID string
|
|
ParentID string
|
|
Name string
|
|
StartTime time.Time
|
|
EndTime time.Time
|
|
Tags map[string]string
|
|
Logs []LogEntry
|
|
}
|
|
|
|
// LogEntry represents a log entry in a span
|
|
type LogEntry struct {
|
|
Timestamp time.Time
|
|
Fields map[string]interface{}
|
|
}
|
|
|
|
// StartSpan starts a new span
|
|
func (t *Tracer) StartSpan(ctx context.Context, name string) (*Span, context.Context) {
|
|
traceID := generateID()
|
|
spanID := generateID()
|
|
|
|
span := &Span{
|
|
TraceID: traceID,
|
|
SpanID: spanID,
|
|
Name: name,
|
|
StartTime: time.Now(),
|
|
Tags: make(map[string]string),
|
|
Logs: []LogEntry{},
|
|
}
|
|
|
|
// Add to context
|
|
ctx = context.WithValue(ctx, "trace_id", traceID)
|
|
ctx = context.WithValue(ctx, "span_id", spanID)
|
|
|
|
return span, ctx
|
|
}
|
|
|
|
// Finish finishes a span
|
|
func (s *Span) Finish() {
|
|
s.EndTime = time.Now()
|
|
// In production, this would send span to tracing backend
|
|
}
|
|
|
|
// SetTag sets a tag on the span
|
|
func (s *Span) SetTag(key, value string) {
|
|
s.Tags[key] = value
|
|
}
|
|
|
|
// Log adds a log entry to the span
|
|
func (s *Span) Log(fields map[string]interface{}) {
|
|
s.Logs = append(s.Logs, LogEntry{
|
|
Timestamp: time.Now(),
|
|
Fields: fields,
|
|
})
|
|
}
|
|
|
|
// generateID generates a random ID
|
|
func generateID() string {
|
|
return fmt.Sprintf("%x", time.Now().UnixNano())
|
|
}
|
|
|