Files
byre/internal/trace/trace.go
T

72 lines
1.3 KiB
Go

package trace
import (
"context"
"fmt"
"strings"
"sync"
"time"
)
type span struct {
name string
dur time.Duration
}
type Trace struct {
mu sync.Mutex
spans []span
}
type ctxKey struct{}
func New(ctx context.Context) (context.Context, *Trace) {
t := &Trace{}
return context.WithValue(ctx, ctxKey{}, t), t
}
func Start(ctx context.Context, name string) func() {
start := time.Now()
return func() {
Add(ctx, name, time.Since(start))
}
}
func Add(ctx context.Context, name string, dur time.Duration) {
t, _ := ctx.Value(ctxKey{}).(*Trace)
if t == nil {
return
}
t.mu.Lock()
t.spans = append(t.spans, span{name: name, dur: dur})
t.mu.Unlock()
}
func (t *Trace) Header(total time.Duration) string {
t.mu.Lock()
defer t.mu.Unlock()
parts := []string{fmt.Sprintf("total;dur=%.1f", ms(total))}
for _, s := range t.spans {
parts = append(parts, fmt.Sprintf("%s;dur=%.1f", token(s.name), ms(s.dur)))
}
return strings.Join(parts, ", ")
}
func (t *Trace) String() string {
t.mu.Lock()
defer t.mu.Unlock()
parts := []string{}
for _, s := range t.spans {
parts = append(parts, fmt.Sprintf("%s %s", s.name, s.dur.Round(time.Millisecond)))
}
return strings.Join(parts, ", ")
}
func ms(d time.Duration) float64 {
return float64(d.Microseconds()) / 1000
}
func token(name string) string {
return strings.ReplaceAll(name, " ", "-")
}