-
Notifications
You must be signed in to change notification settings - Fork 1
/
trace.go
82 lines (71 loc) · 1.75 KB
/
trace.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
package gcp
import (
"crypto/rand"
"encoding/binary"
"fmt"
"sync/atomic"
"time"
api "google.golang.org/api/cloudtrace/v1"
)
func init() {
// Set spanIDCounter and spanIDIncrement to random values. nextSpanID will
// return an arithmetic progression using these values, skipping zero. We set
// the LSB of spanIDIncrement to 1, so that the cycle length is 2^64.
binary.Read(rand.Reader, binary.LittleEndian, &spanIDCounter)
binary.Read(rand.Reader, binary.LittleEndian, &spanIDIncrement)
spanIDIncrement |= 1
}
var (
spanIDCounter uint64
spanIDIncrement uint64
)
// nextSpanID returns a new span ID. It will never return zero.
func nextSpanID() uint64 {
var id uint64
for id == 0 {
id = atomic.AddUint64(&spanIDCounter, spanIDIncrement)
}
return id
}
// nextTraceID returns a new trace ID.
func nextTraceID() string {
id1 := nextSpanID()
id2 := nextSpanID()
return fmt.Sprintf("%016x%016x", id1, id2)
}
type span struct {
id spanID
name string
labels map[string][]byte
start time.Time
end time.Time
}
func finish(c *client, projID string, spans []*span) error {
// group by trace ID.
var traces []*api.Trace
for _, s := range spans {
t := constructTrace(projID, s)
traces = append(traces, t)
}
return c.upload(traces)
}
func constructTrace(projID string, span *span) *api.Trace {
s := &api.TraceSpan{
Name: span.name,
SpanId: span.id.ID,
ParentSpanId: span.id.ParentID,
StartTime: span.start.In(time.UTC).Format(time.RFC3339Nano),
EndTime: span.end.In(time.UTC).Format(time.RFC3339Nano),
// TODO(jbd): add labels
}
return &api.Trace{
ProjectId: projID,
TraceId: span.id.TraceID,
Spans: []*api.TraceSpan{s},
}
}
type spanID struct {
TraceID string
ParentID uint64
ID uint64
}