1
2
3
4
5 package trace
6
7 import (
8 "fmt"
9 "slices"
10 "time"
11 _ "unsafe"
12 )
13
14
15 type recorder struct {
16 r *FlightRecorder
17
18 headerReceived bool
19 }
20
21 func (w *recorder) Write(b []byte) (n int, err error) {
22 r := w.r
23
24 defer func() {
25 if err != nil {
26
27 if r.err == nil {
28 r.err = err
29 }
30 }
31 }()
32
33 if !w.headerReceived {
34 if len(b) < len(r.header) {
35 return 0, fmt.Errorf("expected at least %d bytes in the first write", len(r.header))
36 }
37 r.header = ([16]byte)(b[:16])
38 n += 16
39 w.headerReceived = true
40 }
41 if len(b) == n {
42 return 0, nil
43 }
44 ba, gen, nb, err := readBatch(b[n:])
45 if err != nil {
46 return len(b) - int(nb) - n, err
47 }
48 n += int(nb)
49
50
51 if r.active.gen == 0 {
52 r.active.gen = gen
53 }
54 if r.active.minTime == 0 || r.active.minTime > r.freq.mul(ba.time) {
55 r.active.minTime = r.freq.mul(ba.time)
56 }
57 r.active.size += len(ba.data)
58 r.active.batches = append(r.active.batches, ba)
59
60 return len(b), nil
61 }
62
63 func (w *recorder) endGeneration() {
64 r := w.r
65
66
67 r.ringMu.Lock()
68
69
70 now := traceTimeNow(r.freq)
71
72
73
74
75
76
77
78 newRing := []rawGeneration{r.active}
79 size := r.active.size
80 for i := len(r.ring) - 1; i >= 0; i-- {
81
82
83
84 if uint64(size) > r.wantSize || now.Sub(newRing[len(newRing)-1].minTime) > r.wantDur {
85 break
86 }
87 size += r.ring[i].size
88 newRing = append(newRing, r.ring[i])
89 }
90 slices.Reverse(newRing)
91 r.ring = newRing
92 r.ringMu.Unlock()
93
94
95 r.active = rawGeneration{}
96 }
97
98 type rawGeneration struct {
99 gen uint64
100 size int
101 minTime eventTime
102 batches []batch
103 }
104
105 func traceTimeNow(freq frequency) eventTime {
106 return freq.mul(timestamp(runtime_traceClockNow()))
107 }
108
109
110 func runtime_traceClockNow() uint64
111
112
113 type frequency float64
114
115
116 func (f frequency) mul(t timestamp) eventTime {
117 return eventTime(float64(t) * float64(f))
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 type eventTime int64
140
141
142 func (t eventTime) Sub(t0 eventTime) time.Duration {
143 return time.Duration(int64(t) - int64(t0))
144 }
145
View as plain text