@@ -274,6 +274,8 @@ func (i *Ingester) Push(ctx context.Context, req *client.WriteRequest) (*client.
274
274
return i .v2Push (ctx , req )
275
275
}
276
276
277
+ // NOTE: because we use `unsafe` in deserialisation, we must not
278
+ // retain anything from `req` past the call to ReuseSlice
277
279
defer client .ReuseSlice (req .Timeseries )
278
280
279
281
userID , err := user .ExtractOrgID (ctx )
@@ -298,6 +300,7 @@ func (i *Ingester) Push(ctx context.Context, req *client.WriteRequest) (*client.
298
300
299
301
for _ , ts := range req .Timeseries {
300
302
for _ , s := range ts .Samples {
303
+ // append() copies the memory in `ts.Labels` except on the error path
301
304
err := i .append (ctx , userID , ts .Labels , model .Time (s .TimestampMs ), model .SampleValue (s .Value ), req .Source , record )
302
305
if err == nil {
303
306
continue
@@ -309,12 +312,14 @@ func (i *Ingester) Push(ctx context.Context, req *client.WriteRequest) (*client.
309
312
continue
310
313
}
311
314
312
- return nil , wrapWithUser (err , userID )
315
+ // non-validation error: abandon this request
316
+ return nil , grpcForwardableError (userID , http .StatusInternalServerError , err )
313
317
}
314
318
}
315
319
316
320
if lastPartialErr != nil {
317
- return & client.WriteResponse {}, lastPartialErr .WrapWithUser (userID ).WrappedError ()
321
+ // grpcForwardableError turns the error into a string so it no longer references `req`
322
+ return & client.WriteResponse {}, grpcForwardableError (userID , lastPartialErr .code , lastPartialErr )
318
323
}
319
324
320
325
if record != nil {
@@ -328,6 +333,8 @@ func (i *Ingester) Push(ctx context.Context, req *client.WriteRequest) (*client.
328
333
return & client.WriteResponse {}, nil
329
334
}
330
335
336
+ // NOTE: memory for `labels` is unsafe; anything retained beyond the
337
+ // life of this function must be copied
331
338
func (i * Ingester ) append (ctx context.Context , userID string , labels labelPairs , timestamp model.Time , value model.SampleValue , source client.WriteRequest_SourceEnum , record * Record ) error {
332
339
labels .removeBlanks ()
333
340
@@ -346,6 +353,7 @@ func (i *Ingester) append(ctx context.Context, userID string, labels labelPairs,
346
353
return fmt .Errorf ("ingester stopping" )
347
354
}
348
355
356
+ // getOrCreateSeries copies the memory for `labels`, except on the error path.
349
357
state , fp , series , err := i .userStates .getOrCreateSeries (ctx , userID , labels , record )
350
358
if err != nil {
351
359
if ve , ok := err .(* validationError ); ok {
0 commit comments