-
-
Notifications
You must be signed in to change notification settings - Fork 671
/
Copy pathtracing.go
83 lines (69 loc) · 1.43 KB
/
tracing.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package tracing
import (
"fmt"
"os"
"strings"
"sync"
"time"
)
type Tracer struct {
mu sync.Mutex
spans []*Span
outFile string
timeFn func() time.Time
}
func NewTracer(outFile string) *Tracer {
return &Tracer{
outFile: outFile,
}
}
type Span struct {
parent *Tracer
name string
startedAt time.Time
endedAt time.Time
}
func (t *Tracer) Start(name string) *Span {
t.mu.Lock()
defer t.mu.Unlock()
if t.timeFn == nil {
t.timeFn = time.Now
}
result := &Span{
parent: t,
name: name,
startedAt: t.timeFn(),
}
t.spans = append(t.spans, result)
return result
}
func (s *Span) Stop() {
s.parent.mu.Lock()
defer s.parent.mu.Unlock()
s.endedAt = s.parent.timeFn()
}
func (t *Tracer) WriteOutput() error {
t.mu.Lock()
defer t.mu.Unlock()
if t.outFile == "" {
return nil
}
return os.WriteFile(t.outFile, []byte(t.toMermaidOutput()), 0o644)
}
func (t *Tracer) toMermaidOutput() string {
out := `gantt
title Task Execution Timeline
dateFormat YYYY-MM-DD HH:mm:ss.SSS
axisFormat %X
`
dateFormat := "2006-01-02 15:04:05.000"
for _, span := range t.spans {
if span.endedAt.IsZero() {
continue
}
name := strings.Replace(span.name, ":", "|", -1)
duration := span.endedAt.Sub(span.startedAt).Truncate(time.Millisecond * 100)
out += fmt.Sprintf(" %s [%v] :done, %s, %s\n", name, duration, span.startedAt.Format(dateFormat), span.endedAt.Format(dateFormat))
}
return out
}