88 "strconv"
99
1010 "go.opentelemetry.io/otel/attribute"
11+ "go.opentelemetry.io/otel/metric"
1112 "go.uber.org/zap"
1213 "golang.org/x/sync/errgroup"
1314 "golang.org/x/sync/singleflight"
@@ -17,8 +18,67 @@ import (
1718 "github.com/e2b-dev/infra/packages/shared/pkg/logger"
1819 "github.com/e2b-dev/infra/packages/shared/pkg/storage"
1920 "github.com/e2b-dev/infra/packages/shared/pkg/storage/header"
21+ "github.com/e2b-dev/infra/packages/shared/pkg/telemetry"
2022)
2123
24+ const (
25+ pullType = "pull-type"
26+ pullTypeLocal = "local"
27+ pullTypeRemote = "remote"
28+
29+ failureReason = "failure-reason"
30+
31+ failureTypeLocalRead = "local-read"
32+ failureTypeLocalReadAgain = "local-read-again"
33+ failureTypeRemoteRead = "remote-read"
34+ failureTypeCacheFetch = "cache-fetch"
35+ )
36+
37+ type precomputedAttrs struct {
38+ successFromCache metric.MeasurementOption
39+ successFromRemote metric.MeasurementOption
40+
41+ failCacheRead metric.MeasurementOption
42+ failRemoteFetch metric.MeasurementOption
43+ failLocalReadAgain metric.MeasurementOption
44+
45+ // RemoteReads timer (runFetch)
46+ remoteSuccess metric.MeasurementOption
47+ remoteFailure metric.MeasurementOption
48+ }
49+
50+ var chunkerAttrs = precomputedAttrs {
51+ successFromCache : telemetry .PrecomputeAttrs (
52+ telemetry .Success ,
53+ attribute .String (pullType , pullTypeLocal )),
54+
55+ successFromRemote : telemetry .PrecomputeAttrs (
56+ telemetry .Success ,
57+ attribute .String (pullType , pullTypeRemote )),
58+
59+ failCacheRead : telemetry .PrecomputeAttrs (
60+ telemetry .Failure ,
61+ attribute .String (pullType , pullTypeLocal ),
62+ attribute .String (failureReason , failureTypeLocalRead )),
63+
64+ failRemoteFetch : telemetry .PrecomputeAttrs (
65+ telemetry .Failure ,
66+ attribute .String (pullType , pullTypeRemote ),
67+ attribute .String (failureReason , failureTypeCacheFetch )),
68+
69+ failLocalReadAgain : telemetry .PrecomputeAttrs (
70+ telemetry .Failure ,
71+ attribute .String (pullType , pullTypeLocal ),
72+ attribute .String (failureReason , failureTypeLocalReadAgain )),
73+
74+ remoteSuccess : telemetry .PrecomputeAttrs (
75+ telemetry .Success ),
76+
77+ remoteFailure : telemetry .PrecomputeAttrs (
78+ telemetry .Failure ,
79+ attribute .String (failureReason , failureTypeRemoteRead )),
80+ }
81+
2282// Chunker is the interface satisfied by both FullFetchChunker and StreamingChunker.
2383type Chunker interface {
2484 Slice (ctx context.Context , off , length int64 ) ([]byte , error )
@@ -125,40 +185,32 @@ func (c *FullFetchChunker) Slice(ctx context.Context, off, length int64) ([]byte
125185
126186 b , err := c .cache .Slice (off , length )
127187 if err == nil {
128- timer .Success (ctx , length ,
129- attribute .String (pullType , pullTypeLocal ))
188+ timer .RecordRaw (ctx , length , chunkerAttrs .successFromCache )
130189
131190 return b , nil
132191 }
133192
134193 if ! errors .As (err , & BytesNotAvailableError {}) {
135- timer .Failure (ctx , length ,
136- attribute .String (pullType , pullTypeLocal ),
137- attribute .String (failureReason , failureTypeLocalRead ))
194+ timer .RecordRaw (ctx , length , chunkerAttrs .failCacheRead )
138195
139196 return nil , fmt .Errorf ("failed read from cache at offset %d: %w" , off , err )
140197 }
141198
142199 chunkErr := c .fetchToCache (ctx , off , length )
143200 if chunkErr != nil {
144- timer .Failure (ctx , length ,
145- attribute .String (pullType , pullTypeRemote ),
146- attribute .String (failureReason , failureTypeCacheFetch ))
201+ timer .RecordRaw (ctx , length , chunkerAttrs .failRemoteFetch )
147202
148203 return nil , fmt .Errorf ("failed to ensure data at %d-%d: %w" , off , off + length , chunkErr )
149204 }
150205
151206 b , cacheErr := c .cache .Slice (off , length )
152207 if cacheErr != nil {
153- timer .Failure (ctx , length ,
154- attribute .String (pullType , pullTypeLocal ),
155- attribute .String (failureReason , failureTypeLocalReadAgain ))
208+ timer .RecordRaw (ctx , length , chunkerAttrs .failLocalReadAgain )
156209
157210 return nil , fmt .Errorf ("failed to read from cache after ensuring data at %d-%d: %w" , off , off + length , cacheErr )
158211 }
159212
160- timer .Success (ctx , length ,
161- attribute .String (pullType , pullTypeRemote ))
213+ timer .RecordRaw (ctx , length , chunkerAttrs .successFromRemote )
162214
163215 return b , nil
164216}
@@ -210,24 +262,20 @@ func (c *FullFetchChunker) fetchToCache(ctx context.Context, off, length int64)
210262
211263 readBytes , err := c .base .ReadAt (ctx , b , fetchOff )
212264 if err != nil {
213- fetchSW .Failure (ctx , int64 (readBytes ),
214- attribute .String (failureReason , failureTypeRemoteRead ),
215- )
265+ fetchSW .RecordRaw (ctx , int64 (readBytes ), chunkerAttrs .remoteFailure )
216266
217267 return nil , fmt .Errorf ("failed to read chunk from base %d: %w" , fetchOff , err )
218268 }
219269
220270 if readBytes != len (b ) {
221- fetchSW .Failure (ctx , int64 (readBytes ),
222- attribute .String (failureReason , failureTypeRemoteRead ),
223- )
271+ fetchSW .RecordRaw (ctx , int64 (readBytes ), chunkerAttrs .remoteFailure )
224272
225273 return nil , fmt .Errorf ("failed to read chunk from base %d: expected %d bytes, got %d bytes" , fetchOff , len (b ), readBytes )
226274 }
227275
228276 c .cache .setIsCached (fetchOff , int64 (readBytes ))
229277
230- fetchSW .Success (ctx , int64 (readBytes ))
278+ fetchSW .RecordRaw (ctx , int64 (readBytes ), chunkerAttrs . remoteSuccess )
231279
232280 return nil , nil
233281 })
@@ -251,16 +299,3 @@ func (c *FullFetchChunker) Close() error {
251299func (c * FullFetchChunker ) FileSize () (int64 , error ) {
252300 return c .cache .FileSize ()
253301}
254-
255- const (
256- pullType = "pull-type"
257- pullTypeLocal = "local"
258- pullTypeRemote = "remote"
259-
260- failureReason = "failure-reason"
261-
262- failureTypeLocalRead = "local-read"
263- failureTypeLocalReadAgain = "local-read-again"
264- failureTypeRemoteRead = "remote-read"
265- failureTypeCacheFetch = "cache-fetch"
266- )
0 commit comments