-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an experimental flag to block samples with timestamp too far in the future #6195
Changes from 1 commit
e5f1b43
eb34f48
4038070
544a38f
06b544c
d3e0d2f
7e80fc7
0b4c65b
24dccd0
20f86cd
2e630b1
82b93aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -207,7 +207,10 @@ func runReceive( | |
conf.allowOutOfOrderUpload, | ||
hashFunc, | ||
) | ||
writer := receive.NewWriter(log.With(logger, "component", "receive-writer"), dbs, conf.writerInterning) | ||
writer := receive.NewWriter(log.With(logger, "component", "receive-writer"), dbs, &receive.WriterOptions{ | ||
Intern: conf.writerInterning, | ||
TooFarInFutureTimeWindow: int64(time.Duration(*conf.tsdbTooFarInFutureTimeWindow)), | ||
}) | ||
|
||
var limitsConfig *receive.RootLimitsConfig | ||
if conf.writeLimitsConfig != nil { | ||
|
@@ -774,6 +777,7 @@ type receiveConfig struct { | |
|
||
tsdbMinBlockDuration *model.Duration | ||
tsdbMaxBlockDuration *model.Duration | ||
tsdbTooFarInFutureTimeWindow *model.Duration | ||
tsdbOutOfOrderTimeWindow *model.Duration | ||
tsdbOutOfOrderCapMax int64 | ||
tsdbAllowOverlappingBlocks bool | ||
|
@@ -866,6 +870,11 @@ func (rc *receiveConfig) registerFlag(cmd extkingpin.FlagClause) { | |
|
||
rc.tsdbMaxBlockDuration = extkingpin.ModelDuration(cmd.Flag("tsdb.max-block-duration", "Max duration for local TSDB blocks").Default("2h").Hidden()) | ||
|
||
rc.tsdbTooFarInFutureTimeWindow = extkingpin.ModelDuration(cmd.Flag("tsdb.too-far-in-future.time-window", | ||
fpetkovski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"[EXPERIMENTAL] Configures the allowed time window for ingesting samples too far in the future. Disabled (0s) by default"+ | ||
"Please note enable this flag will reject samples in the future of receive local NTP time + configured duration.", | ||
).Default("0s").Hidden()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a limit range we should allow it to put? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason for making this flag hidden? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no particular reason, i thought it is a convention for experimental flag, removed. |
||
|
||
rc.tsdbOutOfOrderTimeWindow = extkingpin.ModelDuration(cmd.Flag("tsdb.out-of-order.time-window", | ||
"[EXPERIMENTAL] Configures the allowed time window for ingestion of out-of-order samples. Disabled (0s) by default"+ | ||
"Please note if you enable this option and you use compactor, make sure you have the --enable-vertical-compaction flag enabled, otherwise you might risk compactor halt.", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,12 @@ package receive | |
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/go-kit/log" | ||
"github.com/go-kit/log/level" | ||
"github.com/pkg/errors" | ||
"github.com/prometheus/common/model" | ||
"github.com/prometheus/prometheus/model/exemplar" | ||
"github.com/prometheus/prometheus/storage" | ||
"github.com/prometheus/prometheus/tsdb" | ||
|
@@ -26,17 +28,25 @@ type TenantStorage interface { | |
TenantAppendable(string) (Appendable, error) | ||
} | ||
|
||
type WriterOptions struct { | ||
Intern bool | ||
TooFarInFutureTimeWindow int64 // Unit: nanoseconds | ||
} | ||
|
||
type Writer struct { | ||
logger log.Logger | ||
multiTSDB TenantStorage | ||
intern bool | ||
opts *WriterOptions | ||
} | ||
|
||
func NewWriter(logger log.Logger, multiTSDB TenantStorage, intern bool) *Writer { | ||
func NewWriter(logger log.Logger, multiTSDB TenantStorage, opts *WriterOptions) *Writer { | ||
if opts == nil { | ||
opts = &WriterOptions{} | ||
} | ||
return &Writer{ | ||
logger: logger, | ||
multiTSDB: multiTSDB, | ||
intern: intern, | ||
opts: opts, | ||
} | ||
} | ||
|
||
|
@@ -71,7 +81,7 @@ func (r *Writer) Write(ctx context.Context, tenantID string, wreq *prompb.WriteR | |
return errors.Wrap(err, "get appender") | ||
} | ||
getRef := app.(storage.GetRef) | ||
|
||
tooFarInFuture := model.Now().Add(time.Duration(r.opts.TooFarInFutureTimeWindow)) | ||
var ( | ||
ref storage.SeriesRef | ||
errs writeErrors | ||
|
@@ -105,13 +115,18 @@ func (r *Writer) Write(ctx context.Context, tenantID string, wreq *prompb.WriteR | |
if ref == 0 { | ||
// If not, copy labels, as TSDB will hold those strings long term. Given no | ||
// copy unmarshal we don't want to keep memory for whole protobuf, only for labels. | ||
labelpb.ReAllocZLabelsStrings(&t.Labels, r.intern) | ||
labelpb.ReAllocZLabelsStrings(&t.Labels, r.opts.Intern) | ||
lset = labelpb.ZLabelsToPromLabels(t.Labels) | ||
} | ||
|
||
// Append as many valid samples as possible, but keep track of the errors. | ||
for _, s := range t.Samples { | ||
ref, err = app.Append(ref, lset, s.Timestamp, s.Value) | ||
if tooFarInFuture != 0 && tooFarInFuture.Before(model.Time(s.Timestamp)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch |
||
// now + tooFarInFutureTimeWindow < sample timestamp | ||
err = storage.ErrOutOfBounds | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add debug log for how long it out of bounds? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we even make it Warning level? That is something that should fail a bit louder i think so errors can be investigated better. |
||
} else { | ||
ref, err = app.Append(ref, lset, s.Timestamp, s.Value) | ||
} | ||
switch err { | ||
case storage.ErrOutOfOrderSample: | ||
numSamplesOutOfOrder++ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe print an error and exit if the flag < 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value of the flag should be a duration string like "0s", "5m", "1h", etc