Combine Appender.Add and AddFast into a single Append method. (#8489)

This moves the label lookup into TSDB, whilst still keeping the cached-ref optimisation for repeated Appends.

This makes the API easier to consume and implement.  In particular this change is motivated by the scrape-time-aggregation work, which I don't think is possible to implement without it as it needs access to label values.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
This commit is contained in:
Tom Wilkie 2021-02-18 12:07:00 +00:00 committed by GitHub
parent 404d85f7a8
commit 7369561305
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 286 additions and 396 deletions

View file

@ -1105,12 +1105,10 @@ func (s *readyStorage) Appender(ctx context.Context) storage.Appender {
type notReadyAppender struct{} type notReadyAppender struct{}
func (n notReadyAppender) Add(l labels.Labels, t int64, v float64) (uint64, error) { func (n notReadyAppender) Append(ref uint64, l labels.Labels, t int64, v float64) (uint64, error) {
return 0, tsdb.ErrNotReady return 0, tsdb.ErrNotReady
} }
func (n notReadyAppender) AddFast(ref uint64, t int64, v float64) error { return tsdb.ErrNotReady }
func (n notReadyAppender) Commit() error { return tsdb.ErrNotReady } func (n notReadyAppender) Commit() error { return tsdb.ErrNotReady }
func (n notReadyAppender) Rollback() error { return tsdb.ErrNotReady } func (n notReadyAppender) Rollback() error { return tsdb.ErrNotReady }

View file

@ -265,11 +265,11 @@ func TestTimeMetrics(t *testing.T) {
)) ))
app := db.Appender(context.Background()) app := db.Appender(context.Background())
_, err = app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 1000, 1) _, err = app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 1000, 1)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 2000, 1) _, err = app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 2000, 1)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 3000, 1) _, err = app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 3000, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())

View file

@ -142,7 +142,7 @@ func createBlocks(input []byte, mint, maxt int64, maxSamplesInAppender int, outp
l := labels.Labels{} l := labels.Labels{}
p.Metric(&l) p.Metric(&l)
if _, err := app.Add(l, *ts, v); err != nil { if _, err := app.Append(0, l, *ts, v); err != nil {
return errors.Wrap(err, "add sample") return errors.Wrap(err, "add sample")
} }

View file

@ -35,7 +35,6 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/tsdb" "github.com/prometheus/prometheus/tsdb"
"github.com/prometheus/prometheus/tsdb/chunks" "github.com/prometheus/prometheus/tsdb/chunks"
tsdb_errors "github.com/prometheus/prometheus/tsdb/errors" tsdb_errors "github.com/prometheus/prometheus/tsdb/errors"
@ -206,25 +205,19 @@ func (b *writeBenchmark) ingestScrapesShard(lbls []labels.Labels, scrapeCount in
for _, s := range scrape { for _, s := range scrape {
s.value += 1000 s.value += 1000
if s.ref == nil { var ref uint64
ref, err := app.Add(s.labels, ts, float64(s.value)) if s.ref != nil {
if err != nil { ref = *s.ref
panic(err)
}
s.ref = &ref
} else if err := app.AddFast(*s.ref, ts, float64(s.value)); err != nil {
if errors.Cause(err) != storage.ErrNotFound {
panic(err)
}
ref, err := app.Add(s.labels, ts, float64(s.value))
if err != nil {
panic(err)
}
s.ref = &ref
} }
ref, err := app.Append(ref, s.labels, ts, float64(s.value))
if err != nil {
panic(err)
}
if s.ref == nil {
s.ref = &ref
}
total++ total++
} }
if err := app.Commit(); err != nil { if err := app.Commit(); err != nil {

View file

@ -71,10 +71,8 @@ func BenchmarkRangeQuery(b *testing.B) {
a := storage.Appender(context.Background()) a := storage.Appender(context.Background())
ts := int64(s * 10000) // 10s interval. ts := int64(s * 10000) // 10s interval.
for i, metric := range metrics { for i, metric := range metrics {
err := a.AddFast(refs[i], ts, float64(s)) ref, _ := a.Append(refs[i], metric, ts, float64(s))
if err != nil { refs[i] = ref
refs[i], _ = a.Add(metric, ts, float64(s))
}
} }
if err := a.Commit(); err != nil { if err := a.Commit(); err != nil {
b.Fatal(err) b.Fatal(err)

View file

@ -904,14 +904,15 @@ load 1ms
// Add some samples with negative timestamp. // Add some samples with negative timestamp.
db := test.TSDB() db := test.TSDB()
app := db.Appender(context.Background()) app := db.Appender(context.Background())
ref, err := app.Add(lblsneg, -1000000, 1000) ref, err := app.Append(0, lblsneg, -1000000, 1000)
require.NoError(t, err) require.NoError(t, err)
for ts := int64(-1000000 + 1000); ts <= 0; ts += 1000 { for ts := int64(-1000000 + 1000); ts <= 0; ts += 1000 {
require.NoError(t, app.AddFast(ref, ts, -float64(ts/1000)+1)) _, err := app.Append(ref, nil, ts, -float64(ts/1000)+1)
require.NoError(t, err)
} }
// To test the fix for https://github.com/prometheus/prometheus/issues/8433. // To test the fix for https://github.com/prometheus/prometheus/issues/8433.
_, err = app.Add(labels.FromStrings("__name__", "metric_timestamp"), 3600*1000, 1000) _, err = app.Append(0, labels.FromStrings("__name__", "metric_timestamp"), 3600*1000, 1000)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())

View file

@ -43,8 +43,8 @@ func TestDeriv(t *testing.T) {
a := storage.Appender(context.Background()) a := storage.Appender(context.Background())
metric := labels.FromStrings("__name__", "foo") metric := labels.FromStrings("__name__", "foo")
a.Add(metric, 1493712816939, 1.0) a.Append(0, metric, 1493712816939, 1.0)
a.Add(metric, 1493712846939, 1.0) a.Append(0, metric, 1493712846939, 1.0)
require.NoError(t, a.Commit()) require.NoError(t, a.Commit())

View file

@ -307,7 +307,7 @@ func (cmd *loadCmd) append(a storage.Appender) error {
m := cmd.metrics[h] m := cmd.metrics[h]
for _, s := range smpls { for _, s := range smpls {
if _, err := a.Add(m, s.T, s.V); err != nil { if _, err := a.Append(0, m, s.T, s.V); err != nil {
return err return err
} }
} }
@ -732,7 +732,7 @@ func (ll *LazyLoader) appendTill(ts int64) error {
ll.loadCmd.defs[h] = smpls[i:] ll.loadCmd.defs[h] = smpls[i:]
break break
} }
if _, err := app.Add(m, s.T, s.V); err != nil { if _, err := app.Append(0, m, s.T, s.V); err != nil {
return err return err
} }
if i == len(smpls)-1 { if i == len(smpls)-1 {

View file

@ -622,7 +622,7 @@ func (g *Group) Eval(ctx context.Context, ts time.Time) {
g.seriesInPreviousEval[i] = seriesReturned g.seriesInPreviousEval[i] = seriesReturned
}() }()
for _, s := range vector { for _, s := range vector {
if _, err := app.Add(s.Metric, s.T, s.V); err != nil { if _, err := app.Append(0, s.Metric, s.T, s.V); err != nil {
switch errors.Cause(err) { switch errors.Cause(err) {
case storage.ErrOutOfOrderSample: case storage.ErrOutOfOrderSample:
numOutOfOrder++ numOutOfOrder++
@ -647,7 +647,7 @@ func (g *Group) Eval(ctx context.Context, ts time.Time) {
for metric, lset := range g.seriesInPreviousEval[i] { for metric, lset := range g.seriesInPreviousEval[i] {
if _, ok := seriesReturned[metric]; !ok { if _, ok := seriesReturned[metric]; !ok {
// Series no longer exposed, mark it stale. // Series no longer exposed, mark it stale.
_, err = app.Add(lset, timestamp.FromTime(ts), math.Float64frombits(value.StaleNaN)) _, err = app.Append(0, lset, timestamp.FromTime(ts), math.Float64frombits(value.StaleNaN))
switch errors.Cause(err) { switch errors.Cause(err) {
case nil: case nil:
case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp: case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp:
@ -673,7 +673,7 @@ func (g *Group) cleanupStaleSeries(ctx context.Context, ts time.Time) {
app := g.opts.Appendable.Appender(ctx) app := g.opts.Appendable.Appender(ctx)
for _, s := range g.staleSeries { for _, s := range g.staleSeries {
// Rule that produced series no longer configured, mark it stale. // Rule that produced series no longer configured, mark it stale.
_, err := app.Add(s, timestamp.FromTime(ts), math.Float64frombits(value.StaleNaN)) _, err := app.Append(0, s, timestamp.FromTime(ts), math.Float64frombits(value.StaleNaN))
switch errors.Cause(err) { switch errors.Cause(err) {
case nil: case nil:
case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp: case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp:

View file

@ -547,9 +547,9 @@ func TestStaleness(t *testing.T) {
// A time series that has two samples and then goes stale. // A time series that has two samples and then goes stale.
app := st.Appender(context.Background()) app := st.Appender(context.Background())
app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 0, 1) app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 0, 1)
app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 1000, 2) app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 1000, 2)
app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 2000, math.Float64frombits(value.StaleNaN)) app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 2000, math.Float64frombits(value.StaleNaN))
err = app.Commit() err = app.Commit()
require.NoError(t, err) require.NoError(t, err)
@ -872,10 +872,10 @@ func TestNotify(t *testing.T) {
}) })
app := storage.Appender(context.Background()) app := storage.Appender(context.Background())
app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 1000, 2) app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 1000, 2)
app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 2000, 3) app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 2000, 3)
app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 5000, 3) app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 5000, 3)
app.Add(labels.FromStrings(model.MetricNameLabel, "a"), 6000, 0) app.Append(0, labels.FromStrings(model.MetricNameLabel, "a"), 6000, 0)
err = app.Commit() err = app.Commit()
require.NoError(t, err) require.NoError(t, err)

View file

@ -28,10 +28,9 @@ func (a nopAppendable) Appender(_ context.Context) storage.Appender {
type nopAppender struct{} type nopAppender struct{}
func (a nopAppender) Add(labels.Labels, int64, float64) (uint64, error) { return 0, nil } func (a nopAppender) Append(uint64, labels.Labels, int64, float64) (uint64, error) { return 0, nil }
func (a nopAppender) AddFast(uint64, int64, float64) error { return nil } func (a nopAppender) Commit() error { return nil }
func (a nopAppender) Commit() error { return nil } func (a nopAppender) Rollback() error { return nil }
func (a nopAppender) Rollback() error { return nil }
type sample struct { type sample struct {
metric labels.Labels metric labels.Labels
@ -46,47 +45,25 @@ type collectResultAppender struct {
result []sample result []sample
pendingResult []sample pendingResult []sample
rolledbackResult []sample rolledbackResult []sample
mapper map[uint64]labels.Labels
} }
func (a *collectResultAppender) AddFast(ref uint64, t int64, v float64) error { func (a *collectResultAppender) Append(ref uint64, lset labels.Labels, t int64, v float64) (uint64, error) {
if a.next == nil {
return storage.ErrNotFound
}
err := a.next.AddFast(ref, t, v)
if err != nil {
return err
}
a.pendingResult = append(a.pendingResult, sample{ a.pendingResult = append(a.pendingResult, sample{
metric: a.mapper[ref], metric: lset,
t: t, t: t,
v: v, v: v,
}) })
return err
}
func (a *collectResultAppender) Add(m labels.Labels, t int64, v float64) (uint64, error) {
a.pendingResult = append(a.pendingResult, sample{
metric: m,
t: t,
v: v,
})
if a.next == nil { if a.next == nil {
return 0, nil return 0, nil
} }
if a.mapper == nil { ref, err := a.next.Append(ref, lset, t, v)
a.mapper = map[uint64]labels.Labels{}
}
ref, err := a.next.Add(m, t, v)
if err != nil { if err != nil {
return 0, err return 0, err
} }
a.mapper[ref] = m
return ref, nil return ref, err
} }
func (a *collectResultAppender) Commit() error { func (a *collectResultAppender) Commit() error {

View file

@ -1306,20 +1306,19 @@ loop:
continue continue
} }
ce, ok := sl.cache.get(yoloString(met)) ce, ok := sl.cache.get(yoloString(met))
var (
ref uint64
lset labels.Labels
mets string
hash uint64
)
if ok { if ok {
err = app.AddFast(ce.ref, t, v) ref = ce.ref
_, err = sl.checkAddError(ce, met, tp, err, &sampleLimitErr, &appErrs) lset = ce.lset
// In theory this should never happen. } else {
if err == storage.ErrNotFound { mets = p.Metric(&lset)
ok = false hash = lset.Hash()
}
}
if !ok {
var lset labels.Labels
mets := p.Metric(&lset)
hash := lset.Hash()
// Hash label set as it is seen local to the target. Then add target labels // Hash label set as it is seen local to the target. Then add target labels
// and relabeling and store the final label set. // and relabeling and store the final label set.
@ -1335,17 +1334,18 @@ loop:
err = errNameLabelMandatory err = errNameLabelMandatory
break loop break loop
} }
}
var ref uint64 ref, err = app.Append(ref, lset, t, v)
ref, err = app.Add(lset, t, v) sampleAdded, err = sl.checkAddError(ce, met, tp, err, &sampleLimitErr, &appErrs)
sampleAdded, err = sl.checkAddError(nil, met, tp, err, &sampleLimitErr, &appErrs) if err != nil {
if err != nil { if err != storage.ErrNotFound {
if err != storage.ErrNotFound { level.Debug(sl.l).Log("msg", "Unexpected error", "series", string(met), "err", err)
level.Debug(sl.l).Log("msg", "Unexpected error", "series", string(met), "err", err)
}
break loop
} }
break loop
}
if !ok {
if tp == nil { if tp == nil {
// Bypass staleness logic if there is an explicit timestamp. // Bypass staleness logic if there is an explicit timestamp.
sl.cache.trackStaleness(hash, lset) sl.cache.trackStaleness(hash, lset)
@ -1380,7 +1380,7 @@ loop:
if err == nil { if err == nil {
sl.cache.forEachStale(func(lset labels.Labels) bool { sl.cache.forEachStale(func(lset labels.Labels) bool {
// Series no longer exposed, mark it stale. // Series no longer exposed, mark it stale.
_, err = app.Add(lset, defTime, math.Float64frombits(value.StaleNaN)) _, err = app.Append(0, lset, defTime, math.Float64frombits(value.StaleNaN))
switch errors.Cause(err) { switch errors.Cause(err) {
case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp: case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp:
// Do not count these in logging, as this is expected if a target // Do not count these in logging, as this is expected if a target
@ -1497,37 +1497,31 @@ func (sl *scrapeLoop) reportStale(app storage.Appender, start time.Time) (err er
func (sl *scrapeLoop) addReportSample(app storage.Appender, s string, t int64, v float64) error { func (sl *scrapeLoop) addReportSample(app storage.Appender, s string, t int64, v float64) error {
ce, ok := sl.cache.get(s) ce, ok := sl.cache.get(s)
var ref uint64
var lset labels.Labels
if ok { if ok {
err := app.AddFast(ce.ref, t, v) ref = ce.ref
switch errors.Cause(err) { lset = ce.lset
case nil: } else {
return nil lset = labels.Labels{
case storage.ErrNotFound: // The constants are suffixed with the invalid \xff unicode rune to avoid collisions
// Try an Add. // with scraped metrics in the cache.
case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp: // We have to drop it when building the actual metric.
// Do not log here, as this is expected if a target goes away and comes back labels.Label{Name: labels.MetricName, Value: s[:len(s)-1]},
// again with a new scrape loop.
return nil
default:
return err
} }
} lset = sl.reportSampleMutator(lset)
lset := labels.Labels{
// The constants are suffixed with the invalid \xff unicode rune to avoid collisions
// with scraped metrics in the cache.
// We have to drop it when building the actual metric.
labels.Label{Name: labels.MetricName, Value: s[:len(s)-1]},
} }
hash := lset.Hash() ref, err := app.Append(ref, lset, t, v)
lset = sl.reportSampleMutator(lset)
ref, err := app.Add(lset, t, v)
switch errors.Cause(err) { switch errors.Cause(err) {
case nil: case nil:
sl.cache.addRef(s, ref, lset, hash) if !ok {
sl.cache.addRef(s, ref, lset, lset.Hash())
}
return nil return nil
case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp: case storage.ErrOutOfOrderSample, storage.ErrDuplicateSampleForTimestamp:
// Do not log here, as this is expected if a target goes away and comes back
// again with a new scrape loop.
return nil return nil
default: default:
return err return err

View file

@ -1560,7 +1560,7 @@ type errorAppender struct {
collectResultAppender collectResultAppender
} }
func (app *errorAppender) Add(lset labels.Labels, t int64, v float64) (uint64, error) { func (app *errorAppender) Append(ref uint64, lset labels.Labels, t int64, v float64) (uint64, error) {
switch lset.Get(model.MetricNameLabel) { switch lset.Get(model.MetricNameLabel) {
case "out_of_order": case "out_of_order":
return 0, storage.ErrOutOfOrderSample return 0, storage.ErrOutOfOrderSample
@ -1569,14 +1569,10 @@ func (app *errorAppender) Add(lset labels.Labels, t int64, v float64) (uint64, e
case "out_of_bounds": case "out_of_bounds":
return 0, storage.ErrOutOfBounds return 0, storage.ErrOutOfBounds
default: default:
return app.collectResultAppender.Add(lset, t, v) return app.collectResultAppender.Append(ref, lset, t, v)
} }
} }
func (app *errorAppender) AddFast(ref uint64, t int64, v float64) error {
return app.collectResultAppender.AddFast(ref, t, v)
}
func TestScrapeLoopAppendGracefullyIfAmendOrOutOfOrderOrOutOfBounds(t *testing.T) { func TestScrapeLoopAppendGracefullyIfAmendOrOutOfOrderOrOutOfBounds(t *testing.T) {
app := &errorAppender{} app := &errorAppender{}

View file

@ -290,57 +290,38 @@ type limitAppender struct {
i int i int
} }
func (app *limitAppender) Add(lset labels.Labels, t int64, v float64) (uint64, error) { func (app *limitAppender) Append(ref uint64, lset labels.Labels, t int64, v float64) (uint64, error) {
if !value.IsStaleNaN(v) { if !value.IsStaleNaN(v) {
app.i++ app.i++
if app.i > app.limit { if app.i > app.limit {
return 0, errSampleLimit return 0, errSampleLimit
} }
} }
ref, err := app.Appender.Add(lset, t, v) ref, err := app.Appender.Append(ref, lset, t, v)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return ref, nil return ref, nil
} }
func (app *limitAppender) AddFast(ref uint64, t int64, v float64) error {
if !value.IsStaleNaN(v) {
app.i++
if app.i > app.limit {
return errSampleLimit
}
}
err := app.Appender.AddFast(ref, t, v)
return err
}
type timeLimitAppender struct { type timeLimitAppender struct {
storage.Appender storage.Appender
maxTime int64 maxTime int64
} }
func (app *timeLimitAppender) Add(lset labels.Labels, t int64, v float64) (uint64, error) { func (app *timeLimitAppender) Append(ref uint64, lset labels.Labels, t int64, v float64) (uint64, error) {
if t > app.maxTime { if t > app.maxTime {
return 0, storage.ErrOutOfBounds return 0, storage.ErrOutOfBounds
} }
ref, err := app.Appender.Add(lset, t, v) ref, err := app.Appender.Append(ref, lset, t, v)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return ref, nil return ref, nil
} }
func (app *timeLimitAppender) AddFast(ref uint64, t int64, v float64) error {
if t > app.maxTime {
return storage.ErrOutOfBounds
}
err := app.Appender.AddFast(ref, t, v)
return err
}
// populateLabels builds a label set from the given label set and scrape configuration. // populateLabels builds a label set from the given label set and scrape configuration.
// It returns a label set before relabeling was applied as the second return value. // It returns a label set before relabeling was applied as the second return value.
// Returns the original discovered label set found before relabelling was applied if the target is dropped during relabeling. // Returns the original discovered label set found before relabelling was applied if the target is dropped during relabeling.

View file

@ -143,33 +143,20 @@ type fanoutAppender struct {
secondaries []Appender secondaries []Appender
} }
func (f *fanoutAppender) Add(l labels.Labels, t int64, v float64) (uint64, error) { func (f *fanoutAppender) Append(ref uint64, l labels.Labels, t int64, v float64) (uint64, error) {
ref, err := f.primary.Add(l, t, v) ref, err := f.primary.Append(ref, l, t, v)
if err != nil { if err != nil {
return ref, err return ref, err
} }
for _, appender := range f.secondaries { for _, appender := range f.secondaries {
if _, err := appender.Add(l, t, v); err != nil { if _, err := appender.Append(ref, l, t, v); err != nil {
return 0, err return 0, err
} }
} }
return ref, nil return ref, nil
} }
func (f *fanoutAppender) AddFast(ref uint64, t int64, v float64) error {
if err := f.primary.AddFast(ref, t, v); err != nil {
return err
}
for _, appender := range f.secondaries {
if err := appender.AddFast(ref, t, v); err != nil {
return err
}
}
return nil
}
func (f *fanoutAppender) Commit() (err error) { func (f *fanoutAppender) Commit() (err error) {
err = f.primary.Commit() err = f.primary.Commit()

View file

@ -36,11 +36,11 @@ func TestFanout_SelectSorted(t *testing.T) {
priStorage := teststorage.New(t) priStorage := teststorage.New(t)
defer priStorage.Close() defer priStorage.Close()
app1 := priStorage.Appender(ctx) app1 := priStorage.Appender(ctx)
app1.Add(inputLabel, 0, 0) app1.Append(0, inputLabel, 0, 0)
inputTotalSize++ inputTotalSize++
app1.Add(inputLabel, 1000, 1) app1.Append(0, inputLabel, 1000, 1)
inputTotalSize++ inputTotalSize++
app1.Add(inputLabel, 2000, 2) app1.Append(0, inputLabel, 2000, 2)
inputTotalSize++ inputTotalSize++
err := app1.Commit() err := app1.Commit()
require.NoError(t, err) require.NoError(t, err)
@ -48,11 +48,11 @@ func TestFanout_SelectSorted(t *testing.T) {
remoteStorage1 := teststorage.New(t) remoteStorage1 := teststorage.New(t)
defer remoteStorage1.Close() defer remoteStorage1.Close()
app2 := remoteStorage1.Appender(ctx) app2 := remoteStorage1.Appender(ctx)
app2.Add(inputLabel, 3000, 3) app2.Append(0, inputLabel, 3000, 3)
inputTotalSize++ inputTotalSize++
app2.Add(inputLabel, 4000, 4) app2.Append(0, inputLabel, 4000, 4)
inputTotalSize++ inputTotalSize++
app2.Add(inputLabel, 5000, 5) app2.Append(0, inputLabel, 5000, 5)
inputTotalSize++ inputTotalSize++
err = app2.Commit() err = app2.Commit()
require.NoError(t, err) require.NoError(t, err)
@ -61,11 +61,11 @@ func TestFanout_SelectSorted(t *testing.T) {
defer remoteStorage2.Close() defer remoteStorage2.Close()
app3 := remoteStorage2.Appender(ctx) app3 := remoteStorage2.Appender(ctx)
app3.Add(inputLabel, 6000, 6) app3.Append(0, inputLabel, 6000, 6)
inputTotalSize++ inputTotalSize++
app3.Add(inputLabel, 7000, 7) app3.Append(0, inputLabel, 7000, 7)
inputTotalSize++ inputTotalSize++
app3.Add(inputLabel, 8000, 8) app3.Append(0, inputLabel, 8000, 8)
inputTotalSize++ inputTotalSize++
err = app3.Commit() err = app3.Commit()

View file

@ -136,18 +136,15 @@ func (f QueryableFunc) Querier(ctx context.Context, mint, maxt int64) (Querier,
// //
// Operations on the Appender interface are not goroutine-safe. // Operations on the Appender interface are not goroutine-safe.
type Appender interface { type Appender interface {
// Add adds a sample pair for the given series. A reference number is // Append adds a sample pair for the given series.
// returned which can be used to add further samples in the same or later // An optional reference number can be provided to accelerate calls.
// transactions. // A reference number is returned which can be used to add further
// samples in the same or later transactions.
// Returned reference numbers are ephemeral and may be rejected in calls // Returned reference numbers are ephemeral and may be rejected in calls
// to AddFast() at any point. Adding the sample via Add() returns a new // to Append() at any point. Adding the sample via Append() returns a new
// reference number. // reference number.
// If the reference is 0 it must not be used for caching. // If the reference is 0 it must not be used for caching.
Add(l labels.Labels, t int64, v float64) (uint64, error) Append(ref uint64, l labels.Labels, t int64, v float64) (uint64, error)
// AddFast adds a sample pair for the referenced series. It is generally
// faster than adding a sample by providing its full label set.
AddFast(ref uint64, t int64, v float64) error
// Commit submits the collected samples and purges the batch. If Commit // Commit submits the collected samples and purges the batch. If Commit
// returns a non-nil error, it also rolls back all modifications made in // returns a non-nil error, it also rolls back all modifications made in

View file

@ -212,8 +212,8 @@ type timestampTracker struct {
highestRecvTimestamp *maxTimestamp highestRecvTimestamp *maxTimestamp
} }
// Add implements storage.Appender. // Append implements storage.Appender.
func (t *timestampTracker) Add(_ labels.Labels, ts int64, _ float64) (uint64, error) { func (t *timestampTracker) Append(_ uint64, _ labels.Labels, ts int64, _ float64) (uint64, error) {
t.samples++ t.samples++
if ts > t.highestTimestamp { if ts > t.highestTimestamp {
t.highestTimestamp = ts t.highestTimestamp = ts
@ -221,12 +221,6 @@ func (t *timestampTracker) Add(_ labels.Labels, ts int64, _ float64) (uint64, er
return 0, nil return 0, nil
} }
// AddFast implements storage.Appender.
func (t *timestampTracker) AddFast(_ uint64, ts int64, v float64) error {
_, err := t.Add(nil, ts, v)
return err
}
// Commit implements storage.Appender. // Commit implements storage.Appender.
func (t *timestampTracker) Commit() error { func (t *timestampTracker) Commit() error {
t.writeStorage.samplesIn.incr(t.samples) t.writeStorage.samplesIn.incr(t.samples)

View file

@ -75,7 +75,7 @@ func (h *handler) write(ctx context.Context, req *prompb.WriteRequest) (err erro
for _, ts := range req.Timeseries { for _, ts := range req.Timeseries {
labels := labelProtosToLabels(ts.Labels) labels := labelProtosToLabels(ts.Labels)
for _, s := range ts.Samples { for _, s := range ts.Samples {
_, err = app.Add(labels, s.Timestamp, s.Value) _, err = app.Append(0, labels, s.Timestamp, s.Value)
if err != nil { if err != nil {
return err return err
} }

View file

@ -115,7 +115,7 @@ func (m *mockAppendable) Appender(_ context.Context) storage.Appender {
return m return m
} }
func (m *mockAppendable) Add(l labels.Labels, t int64, v float64) (uint64, error) { func (m *mockAppendable) Append(_ uint64, l labels.Labels, t int64, v float64) (uint64, error) {
if t < m.latest { if t < m.latest {
return 0, storage.ErrOutOfOrderSample return 0, storage.ErrOutOfOrderSample
} }
@ -129,10 +129,6 @@ func (m *mockAppendable) Commit() error {
return m.commitErr return m.commitErr
} }
func (*mockAppendable) AddFast(uint64, int64, float64) error {
return fmt.Errorf("not implemented")
}
func (*mockAppendable) Rollback() error { func (*mockAppendable) Rollback() error {
return fmt.Errorf("not implemented") return fmt.Errorf("not implemented")
} }

View file

@ -448,15 +448,10 @@ func createHead(tb testing.TB, w *wal.WAL, series []storage.Series, chunkDir str
for _, s := range series { for _, s := range series {
ref := uint64(0) ref := uint64(0)
it := s.Iterator() it := s.Iterator()
lset := s.Labels()
for it.Next() { for it.Next() {
t, v := it.At() t, v := it.At()
if ref != 0 { ref, err = app.Append(ref, lset, t, v)
err := app.AddFast(ref, t, v)
if err == nil {
continue
}
}
ref, err = app.Add(s.Labels(), t, v)
require.NoError(tb, err) require.NoError(tb, err)
} }
require.NoError(tb, it.Err()) require.NoError(tb, it.Err())

View file

@ -43,10 +43,10 @@ func TestBlockWriter(t *testing.T) {
// Add some series. // Add some series.
app := w.Appender(ctx) app := w.Appender(ctx)
ts1, v1 := int64(44), float64(7) ts1, v1 := int64(44), float64(7)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, ts1, v1) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, ts1, v1)
require.NoError(t, err) require.NoError(t, err)
ts2, v2 := int64(55), float64(12) ts2, v2 := int64(55), float64(12)
_, err = app.Add(labels.Labels{{Name: "c", Value: "d"}}, ts2, v2) _, err = app.Append(0, labels.Labels{{Name: "c", Value: "d"}}, ts2, v2)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
id, err := w.Flush(ctx) id, err := w.Flush(ctx)

View file

@ -1101,7 +1101,7 @@ func BenchmarkCompactionFromHead(b *testing.B) {
for ln := 0; ln < labelNames; ln++ { for ln := 0; ln < labelNames; ln++ {
app := h.Appender(context.Background()) app := h.Appender(context.Background())
for lv := 0; lv < labelValues; lv++ { for lv := 0; lv < labelValues; lv++ {
app.Add(labels.FromStrings(fmt.Sprintf("%d", ln), fmt.Sprintf("%d%s%d", lv, postingsBenchSuffix, ln)), 0, 0) app.Append(0, labels.FromStrings(fmt.Sprintf("%d", ln), fmt.Sprintf("%d%s%d", lv, postingsBenchSuffix, ln)), 0, 0)
} }
require.NoError(b, app.Commit()) require.NoError(b, app.Commit())
} }
@ -1134,9 +1134,9 @@ func TestDisableAutoCompactions(t *testing.T) {
db.DisableCompactions() db.DisableCompactions()
app := db.Appender(context.Background()) app := db.Appender(context.Background())
for i := int64(0); i < 3; i++ { for i := int64(0); i < 3; i++ {
_, err := app.Add(label, i*blockRange, 0) _, err := app.Append(0, label, i*blockRange, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(label, i*blockRange+1000, 0) _, err = app.Append(0, label, i*blockRange+1000, 0)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1249,11 +1249,11 @@ func TestDeleteCompactionBlockAfterFailedReload(t *testing.T) {
// Add some data to the head that is enough to trigger a compaction. // Add some data to the head that is enough to trigger a compaction.
app := db.Appender(context.Background()) app := db.Appender(context.Background())
_, err := app.Add(defaultLabel, 1, 0) _, err := app.Append(0, defaultLabel, 1, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, 2, 0) _, err = app.Append(0, defaultLabel, 2, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, 3+rangeToTriggerCompaction, 0) _, err = app.Append(0, defaultLabel, 3+rangeToTriggerCompaction, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())

View file

@ -173,7 +173,7 @@ func TestDataAvailableOnlyAfterCommit(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(labels.FromStrings("foo", "bar"), 0, 0) _, err := app.Append(0, labels.FromStrings("foo", "bar"), 0, 0)
require.NoError(t, err) require.NoError(t, err)
querier, err := db.Querier(context.TODO(), 0, 1) querier, err := db.Querier(context.TODO(), 0, 1)
@ -206,7 +206,7 @@ func TestNoPanicAfterWALCorruption(t *testing.T) {
{ {
for { for {
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(labels.FromStrings("foo", "bar"), maxt, 0) _, err := app.Append(0, labels.FromStrings("foo", "bar"), maxt, 0)
expSamples = append(expSamples, sample{t: maxt, v: 0}) expSamples = append(expSamples, sample{t: maxt, v: 0})
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -261,7 +261,7 @@ func TestDataNotAvailableAfterRollback(t *testing.T) {
}() }()
app := db.Appender(context.Background()) app := db.Appender(context.Background())
_, err := app.Add(labels.FromStrings("foo", "bar"), 0, 0) _, err := app.Append(0, labels.FromStrings("foo", "bar"), 0, 0)
require.NoError(t, err) require.NoError(t, err)
err = app.Rollback() err = app.Rollback()
@ -285,12 +285,13 @@ func TestDBAppenderAddRef(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app1 := db.Appender(ctx) app1 := db.Appender(ctx)
ref1, err := app1.Add(labels.FromStrings("a", "b"), 123, 0) ref1, err := app1.Append(0, labels.FromStrings("a", "b"), 123, 0)
require.NoError(t, err) require.NoError(t, err)
// Reference should already work before commit. // Reference should already work before commit.
err = app1.AddFast(ref1, 124, 1) ref2, err := app1.Append(ref1, nil, 124, 1)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, ref1, ref2)
err = app1.Commit() err = app1.Commit()
require.NoError(t, err) require.NoError(t, err)
@ -298,20 +299,22 @@ func TestDBAppenderAddRef(t *testing.T) {
app2 := db.Appender(ctx) app2 := db.Appender(ctx)
// first ref should already work in next transaction. // first ref should already work in next transaction.
err = app2.AddFast(ref1, 125, 0) ref3, err := app2.Append(ref1, nil, 125, 0)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, ref1, ref3)
ref2, err := app2.Add(labels.FromStrings("a", "b"), 133, 1) ref4, err := app2.Append(ref1, labels.FromStrings("a", "b"), 133, 1)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, ref1, ref4)
require.Equal(t, ref1, ref2)
// Reference must be valid to add another sample. // Reference must be valid to add another sample.
err = app2.AddFast(ref2, 143, 2) ref5, err := app2.Append(ref2, nil, 143, 2)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, ref1, ref5)
err = app2.AddFast(9999999, 1, 1) // Missing labels & invalid refs should fail.
require.Equal(t, storage.ErrNotFound, errors.Cause(err)) _, err = app2.Append(9999999, nil, 1, 1)
require.Equal(t, ErrInvalidSample, errors.Cause(err))
require.NoError(t, app2.Commit()) require.NoError(t, app2.Commit())
@ -340,11 +343,11 @@ func TestAppendEmptyLabelsIgnored(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app1 := db.Appender(ctx) app1 := db.Appender(ctx)
ref1, err := app1.Add(labels.FromStrings("a", "b"), 123, 0) ref1, err := app1.Append(0, labels.FromStrings("a", "b"), 123, 0)
require.NoError(t, err) require.NoError(t, err)
// Construct labels manually so there is an empty label. // Construct labels manually so there is an empty label.
ref2, err := app1.Add(labels.Labels{labels.Label{Name: "a", Value: "b"}, labels.Label{Name: "c", Value: ""}}, 124, 0) ref2, err := app1.Append(0, labels.Labels{labels.Label{Name: "a", Value: "b"}, labels.Label{Name: "c", Value: ""}}, 124, 0)
require.NoError(t, err) require.NoError(t, err)
// Should be the same series. // Should be the same series.
@ -396,7 +399,7 @@ Outer:
smpls := make([]float64, numSamples) smpls := make([]float64, numSamples)
for i := int64(0); i < numSamples; i++ { for i := int64(0); i < numSamples; i++ {
smpls[i] = rand.Float64() smpls[i] = rand.Float64()
app.Add(labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i]) app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i])
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -452,12 +455,12 @@ func TestAmendDatapointCausesError(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, 0) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, 1) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, 1)
require.Equal(t, storage.ErrDuplicateSampleForTimestamp, err) require.Equal(t, storage.ErrDuplicateSampleForTimestamp, err)
require.NoError(t, app.Rollback()) require.NoError(t, app.Rollback())
} }
@ -470,12 +473,12 @@ func TestDuplicateNaNDatapointNoAmendError(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, math.NaN()) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, math.NaN())
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, math.NaN()) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, math.NaN())
require.NoError(t, err) require.NoError(t, err)
} }
@ -487,12 +490,12 @@ func TestNonDuplicateNaNDatapointsCausesAmendError(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, math.Float64frombits(0x7ff0000000000001)) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, math.Float64frombits(0x7ff0000000000001))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, math.Float64frombits(0x7ff0000000000002)) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, math.Float64frombits(0x7ff0000000000002))
require.Equal(t, storage.ErrDuplicateSampleForTimestamp, err) require.Equal(t, storage.ErrDuplicateSampleForTimestamp, err)
} }
@ -504,7 +507,7 @@ func TestEmptyLabelsetCausesError(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(labels.Labels{}, 0, 0) _, err := app.Append(0, labels.Labels{}, 0, 0)
require.Error(t, err) require.Error(t, err)
require.Equal(t, "empty labelset: invalid sample", err.Error()) require.Equal(t, "empty labelset: invalid sample", err.Error())
} }
@ -518,9 +521,9 @@ func TestSkippingInvalidValuesInSameTxn(t *testing.T) {
// Append AmendedValue. // Append AmendedValue.
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, 1) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, 1)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 0, 2) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 0, 2)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -536,9 +539,9 @@ func TestSkippingInvalidValuesInSameTxn(t *testing.T) {
// Append Out of Order Value. // Append Out of Order Value.
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 10, 3) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 10, 3)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 7, 5) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 7, 5)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -560,7 +563,7 @@ func TestDB_Snapshot(t *testing.T) {
app := db.Appender(ctx) app := db.Appender(ctx)
mint := int64(1414141414000) mint := int64(1414141414000)
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
_, err := app.Add(labels.FromStrings("foo", "bar"), mint+int64(i), 1.0) _, err := app.Append(0, labels.FromStrings("foo", "bar"), mint+int64(i), 1.0)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -610,7 +613,7 @@ func TestDB_Snapshot_ChunksOutsideOfCompactedRange(t *testing.T) {
app := db.Appender(ctx) app := db.Appender(ctx)
mint := int64(1414141414000) mint := int64(1414141414000)
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
_, err := app.Add(labels.FromStrings("foo", "bar"), mint+int64(i), 1.0) _, err := app.Append(0, labels.FromStrings("foo", "bar"), mint+int64(i), 1.0)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -665,7 +668,7 @@ func TestDB_SnapshotWithDelete(t *testing.T) {
smpls := make([]float64, numSamples) smpls := make([]float64, numSamples)
for i := int64(0); i < numSamples; i++ { for i := int64(0); i < numSamples; i++ {
smpls[i] = rand.Float64() smpls[i] = rand.Float64()
app.Add(labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i]) app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i])
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -818,7 +821,7 @@ func TestDB_e2e(t *testing.T) {
series = append(series, sample{ts, v}) series = append(series, sample{ts, v})
_, err := app.Add(lset, ts, v) _, err := app.Append(0, lset, ts, v)
require.NoError(t, err) require.NoError(t, err)
ts += rand.Int63n(timeInterval) + 1 ts += rand.Int63n(timeInterval) + 1
@ -912,7 +915,7 @@ func TestWALFlushedOnDBClose(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(lbls, 0, 1) _, err := app.Append(0, lbls, 0, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -986,10 +989,10 @@ func TestWALSegmentSizeOptions(t *testing.T) {
for i := int64(0); i < 155; i++ { for i := int64(0); i < 155; i++ {
app := db.Appender(context.Background()) app := db.Appender(context.Background())
ref, err := app.Add(labels.Labels{labels.Label{Name: "wal" + fmt.Sprintf("%d", i), Value: "size"}}, i, rand.Float64()) ref, err := app.Append(0, labels.Labels{labels.Label{Name: "wal" + fmt.Sprintf("%d", i), Value: "size"}}, i, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
for j := int64(1); j <= 78; j++ { for j := int64(1); j <= 78; j++ {
err := app.AddFast(ref, i+j, rand.Float64()) _, err := app.Append(ref, nil, i+j, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1013,7 +1016,7 @@ func TestTombstoneClean(t *testing.T) {
smpls := make([]float64, numSamples) smpls := make([]float64, numSamples)
for i := int64(0); i < numSamples; i++ { for i := int64(0); i < numSamples; i++ {
smpls[i] = rand.Float64() smpls[i] = rand.Float64()
app.Add(labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i]) app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i])
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1356,7 +1359,7 @@ func TestSizeRetention(t *testing.T) {
it := s.Iterator() it := s.Iterator()
for it.Next() { for it.Next() {
tim, v := it.At() tim, v := it.At()
_, err := headApp.Add(s.Labels(), tim, v) _, err := headApp.Append(0, s.Labels(), tim, v)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, it.Err()) require.NoError(t, it.Err())
@ -1472,7 +1475,7 @@ func TestNotMatcherSelectsLabelsUnsetSeries(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
for _, lbls := range labelpairs { for _, lbls := range labelpairs {
_, err := app.Add(lbls, 0, 1) _, err := app.Append(0, lbls, 0, 1)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1657,9 +1660,9 @@ func TestChunkAtBlockBoundary(t *testing.T) {
label := labels.FromStrings("foo", "bar") label := labels.FromStrings("foo", "bar")
for i := int64(0); i < 3; i++ { for i := int64(0); i < 3; i++ {
_, err := app.Add(label, i*blockRange, 0) _, err := app.Append(0, label, i*blockRange, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(label, i*blockRange+1000, 0) _, err = app.Append(0, label, i*blockRange+1000, 0)
require.NoError(t, err) require.NoError(t, err)
} }
@ -1714,9 +1717,9 @@ func TestQuerierWithBoundaryChunks(t *testing.T) {
label := labels.FromStrings("foo", "bar") label := labels.FromStrings("foo", "bar")
for i := int64(0); i < 5; i++ { for i := int64(0); i < 5; i++ {
_, err := app.Add(label, i*blockRange, 0) _, err := app.Append(0, label, i*blockRange, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.FromStrings("blockID", strconv.FormatInt(i, 10)), i*blockRange, 0) _, err = app.Append(0, labels.FromStrings("blockID", strconv.FormatInt(i, 10)), i*blockRange, 0)
require.NoError(t, err) require.NoError(t, err)
} }
@ -1763,7 +1766,7 @@ func TestInitializeHeadTimestamp(t *testing.T) {
// First added sample initializes the writable range. // First added sample initializes the writable range.
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err = app.Add(labels.FromStrings("a", "b"), 1000, 1) _, err = app.Append(0, labels.FromStrings("a", "b"), 1000, 1)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, int64(1000), db.head.MinTime()) require.Equal(t, int64(1000), db.head.MinTime())
@ -1880,11 +1883,11 @@ func TestNoEmptyBlocks(t *testing.T) {
t.Run("Test no blocks after deleting all samples from head.", func(t *testing.T) { t.Run("Test no blocks after deleting all samples from head.", func(t *testing.T) {
app := db.Appender(ctx) app := db.Appender(ctx)
_, err := app.Add(defaultLabel, 1, 0) _, err := app.Append(0, defaultLabel, 1, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, 2, 0) _, err = app.Append(0, defaultLabel, 2, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, 3+rangeToTriggerCompaction, 0) _, err = app.Append(0, defaultLabel, 3+rangeToTriggerCompaction, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.NoError(t, db.Delete(math.MinInt64, math.MaxInt64, defaultMatcher)) require.NoError(t, db.Delete(math.MinInt64, math.MaxInt64, defaultMatcher))
@ -1897,16 +1900,16 @@ func TestNoEmptyBlocks(t *testing.T) {
require.Equal(t, 0, len(actBlocks)) require.Equal(t, 0, len(actBlocks))
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(defaultLabel, 1, 0) _, err = app.Append(0, defaultLabel, 1, 0)
require.Equal(t, storage.ErrOutOfBounds, err, "the head should be truncated so no samples in the past should be allowed") require.Equal(t, storage.ErrOutOfBounds, err, "the head should be truncated so no samples in the past should be allowed")
// Adding new blocks. // Adding new blocks.
currentTime := db.Head().MaxTime() currentTime := db.Head().MaxTime()
_, err = app.Add(defaultLabel, currentTime, 0) _, err = app.Append(0, defaultLabel, currentTime, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, currentTime+1, 0) _, err = app.Append(0, defaultLabel, currentTime+1, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, currentTime+rangeToTriggerCompaction, 0) _, err = app.Append(0, defaultLabel, currentTime+rangeToTriggerCompaction, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1923,11 +1926,11 @@ func TestNoEmptyBlocks(t *testing.T) {
oldBlocks := db.Blocks() oldBlocks := db.Blocks()
app := db.Appender(ctx) app := db.Appender(ctx)
currentTime := db.Head().MaxTime() currentTime := db.Head().MaxTime()
_, err := app.Add(defaultLabel, currentTime, 0) _, err := app.Append(0, defaultLabel, currentTime, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, currentTime+1, 0) _, err = app.Append(0, defaultLabel, currentTime+1, 0)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(defaultLabel, currentTime+rangeToTriggerCompaction, 0) _, err = app.Append(0, defaultLabel, currentTime+rangeToTriggerCompaction, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.NoError(t, db.head.Delete(math.MinInt64, math.MaxInt64, defaultMatcher)) require.NoError(t, db.head.Delete(math.MinInt64, math.MaxInt64, defaultMatcher))
@ -2009,7 +2012,7 @@ func TestDB_LabelNames(t *testing.T) {
for i := mint; i <= maxt; i++ { for i := mint; i <= maxt; i++ {
for _, tuple := range sampleLabels { for _, tuple := range sampleLabels {
label := labels.FromStrings(tuple[0], tuple[1]) label := labels.FromStrings(tuple[0], tuple[1])
_, err := app.Add(label, i*blockRange, 0) _, err := app.Append(0, label, i*blockRange, 0)
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -2076,7 +2079,7 @@ func TestCorrectNumTombstones(t *testing.T) {
app := db.Appender(ctx) app := db.Appender(ctx)
for i := int64(0); i < 3; i++ { for i := int64(0); i < 3; i++ {
for j := int64(0); j < 15; j++ { for j := int64(0); j < 15; j++ {
_, err := app.Add(defaultLabel, i*blockRange+j, 0) _, err := app.Append(0, defaultLabel, i*blockRange+j, 0)
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -2129,16 +2132,16 @@ func TestBlockRanges(t *testing.T) {
}() }()
app := db.Appender(ctx) app := db.Appender(ctx)
lbl := labels.Labels{{Name: "a", Value: "b"}} lbl := labels.Labels{{Name: "a", Value: "b"}}
_, err = app.Add(lbl, firstBlockMaxT-1, rand.Float64()) _, err = app.Append(0, lbl, firstBlockMaxT-1, rand.Float64())
if err == nil { if err == nil {
t.Fatalf("appending a sample with a timestamp covered by a previous block shouldn't be possible") t.Fatalf("appending a sample with a timestamp covered by a previous block shouldn't be possible")
} }
_, err = app.Add(lbl, firstBlockMaxT+1, rand.Float64()) _, err = app.Append(0, lbl, firstBlockMaxT+1, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(lbl, firstBlockMaxT+2, rand.Float64()) _, err = app.Append(0, lbl, firstBlockMaxT+2, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
secondBlockMaxt := firstBlockMaxT + rangeToTriggerCompaction secondBlockMaxt := firstBlockMaxT + rangeToTriggerCompaction
_, err = app.Add(lbl, secondBlockMaxt, rand.Float64()) // Add samples to trigger a new compaction _, err = app.Append(0, lbl, secondBlockMaxt, rand.Float64()) // Add samples to trigger a new compaction
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -2158,13 +2161,13 @@ func TestBlockRanges(t *testing.T) {
// and compaction doesn't create an overlapping block. // and compaction doesn't create an overlapping block.
app = db.Appender(ctx) app = db.Appender(ctx)
db.DisableCompactions() db.DisableCompactions()
_, err = app.Add(lbl, secondBlockMaxt+1, rand.Float64()) _, err = app.Append(0, lbl, secondBlockMaxt+1, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(lbl, secondBlockMaxt+2, rand.Float64()) _, err = app.Append(0, lbl, secondBlockMaxt+2, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(lbl, secondBlockMaxt+3, rand.Float64()) _, err = app.Append(0, lbl, secondBlockMaxt+3, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(lbl, secondBlockMaxt+4, rand.Float64()) _, err = app.Append(0, lbl, secondBlockMaxt+4, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.NoError(t, db.Close()) require.NoError(t, db.Close())
@ -2180,7 +2183,7 @@ func TestBlockRanges(t *testing.T) {
require.Equal(t, db.Blocks()[2].Meta().MaxTime, thirdBlockMaxt, "unexpected maxt of the last block") require.Equal(t, db.Blocks()[2].Meta().MaxTime, thirdBlockMaxt, "unexpected maxt of the last block")
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(lbl, thirdBlockMaxt+rangeToTriggerCompaction, rand.Float64()) // Trigger a compaction _, err = app.Append(0, lbl, thirdBlockMaxt+rangeToTriggerCompaction, rand.Float64()) // Trigger a compaction
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
for x := 0; x < 100; x++ { for x := 0; x < 100; x++ {
@ -2247,7 +2250,7 @@ func TestDBReadOnly(t *testing.T) {
dbSizeBeforeAppend, err := fileutil.DirSize(dbWritable.Dir()) dbSizeBeforeAppend, err := fileutil.DirSize(dbWritable.Dir())
require.NoError(t, err) require.NoError(t, err)
app := dbWritable.Appender(context.Background()) app := dbWritable.Appender(context.Background())
_, err = app.Add(labels.FromStrings("foo", "bar"), dbWritable.Head().MaxTime()+1, 0) _, err = app.Append(0, labels.FromStrings("foo", "bar"), dbWritable.Head().MaxTime()+1, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -2348,7 +2351,7 @@ func TestDBReadOnly_FlushWAL(t *testing.T) {
app := db.Appender(ctx) app := db.Appender(ctx)
maxt = 1000 maxt = 1000
for i := 0; i < maxt; i++ { for i := 0; i < maxt; i++ {
_, err := app.Add(labels.FromStrings(defaultLabelName, "flush"), int64(i), 1.0) _, err := app.Append(0, labels.FromStrings(defaultLabelName, "flush"), int64(i), 1.0)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -2418,7 +2421,7 @@ func TestDBCannotSeePartialCommits(t *testing.T) {
app := db.Appender(ctx) app := db.Appender(ctx)
for j := 0; j < 100; j++ { for j := 0; j < 100; j++ {
_, err := app.Add(labels.FromStrings("foo", "bar", "a", strconv.Itoa(j)), int64(iter), float64(iter)) _, err := app.Append(0, labels.FromStrings("foo", "bar", "a", strconv.Itoa(j)), int64(iter), float64(iter))
require.NoError(t, err) require.NoError(t, err)
} }
err = app.Commit() err = app.Commit()
@ -2483,7 +2486,7 @@ func TestDBQueryDoesntSeeAppendsAfterCreation(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
_, err = app.Add(labels.FromStrings("foo", "bar"), 0, 0) _, err = app.Append(0, labels.FromStrings("foo", "bar"), 0, 0)
require.NoError(t, err) require.NoError(t, err)
querierAfterAddButBeforeCommit, err := db.Querier(context.Background(), 0, 1000000) querierAfterAddButBeforeCommit, err := db.Querier(context.Background(), 0, 1000000)
@ -2808,7 +2811,7 @@ func TestCompactHead(t *testing.T) {
maxt := 100 maxt := 100
for i := 0; i < maxt; i++ { for i := 0; i < maxt; i++ {
val := rand.Float64() val := rand.Float64()
_, err := app.Add(labels.FromStrings("a", "b"), int64(i), val) _, err := app.Append(0, labels.FromStrings("a", "b"), int64(i), val)
require.NoError(t, err) require.NoError(t, err)
expSamples = append(expSamples, sample{int64(i), val}) expSamples = append(expSamples, sample{int64(i), val})
} }
@ -3008,9 +3011,9 @@ func TestOneCheckpointPerCompactCall(t *testing.T) {
// Append samples spanning 59 block ranges. // Append samples spanning 59 block ranges.
app := db.Appender(context.Background()) app := db.Appender(context.Background())
for i := int64(0); i < 60; i++ { for i := int64(0); i < 60; i++ {
_, err := app.Add(lbls, blockRange*i, rand.Float64()) _, err := app.Append(0, lbls, blockRange*i, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(lbls, (blockRange*i)+blockRange/2, rand.Float64()) _, err = app.Append(0, lbls, (blockRange*i)+blockRange/2, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
// Rotate the WAL file so that there is >3 files for checkpoint to happen. // Rotate the WAL file so that there is >3 files for checkpoint to happen.
require.NoError(t, db.head.wal.NextSegment()) require.NoError(t, db.head.wal.NextSegment())
@ -3067,7 +3070,7 @@ func TestOneCheckpointPerCompactCall(t *testing.T) {
// Adding sample way into the future. // Adding sample way into the future.
app = db.Appender(context.Background()) app = db.Appender(context.Background())
_, err = app.Add(lbls, blockRange*120, rand.Float64()) _, err = app.Append(0, lbls, blockRange*120, rand.Float64())
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())

View file

@ -1052,21 +1052,14 @@ type initAppender struct {
head *Head head *Head
} }
func (a *initAppender) Add(lset labels.Labels, t int64, v float64) (uint64, error) { func (a *initAppender) Append(ref uint64, lset labels.Labels, t int64, v float64) (uint64, error) {
if a.app != nil { if a.app != nil {
return a.app.Add(lset, t, v) return a.app.Append(ref, lset, t, v)
} }
a.head.initTime(t) a.head.initTime(t)
a.app = a.head.appender() a.app = a.head.appender()
return a.app.Append(ref, lset, t, v)
return a.app.Add(lset, t, v)
}
func (a *initAppender) AddFast(ref uint64, t int64, v float64) error {
if a.app == nil {
return storage.ErrNotFound
}
return a.app.AddFast(ref, t, v)
} }
func (a *initAppender) Commit() error { func (a *initAppender) Commit() error {
@ -1178,54 +1171,45 @@ type headAppender struct {
closed bool closed bool
} }
func (a *headAppender) Add(lset labels.Labels, t int64, v float64) (uint64, error) { func (a *headAppender) Append(ref uint64, lset labels.Labels, t int64, v float64) (uint64, error) {
if t < a.minValidTime { if t < a.minValidTime {
a.head.metrics.outOfBoundSamples.Inc() a.head.metrics.outOfBoundSamples.Inc()
return 0, storage.ErrOutOfBounds return 0, storage.ErrOutOfBounds
} }
// Ensure no empty labels have gotten through.
lset = lset.WithoutEmpty()
if len(lset) == 0 {
return 0, errors.Wrap(ErrInvalidSample, "empty labelset")
}
if l, dup := lset.HasDuplicateLabelNames(); dup {
return 0, errors.Wrap(ErrInvalidSample, fmt.Sprintf(`label name "%s" is not unique`, l))
}
s, created, err := a.head.getOrCreate(lset.Hash(), lset)
if err != nil {
return 0, err
}
if created {
a.series = append(a.series, record.RefSeries{
Ref: s.ref,
Labels: lset,
})
}
return s.ref, a.AddFast(s.ref, t, v)
}
func (a *headAppender) AddFast(ref uint64, t int64, v float64) error {
if t < a.minValidTime {
a.head.metrics.outOfBoundSamples.Inc()
return storage.ErrOutOfBounds
}
s := a.head.series.getByID(ref) s := a.head.series.getByID(ref)
if s == nil { if s == nil {
return errors.Wrap(storage.ErrNotFound, "unknown series") // Ensure no empty labels have gotten through.
lset = lset.WithoutEmpty()
if len(lset) == 0 {
return 0, errors.Wrap(ErrInvalidSample, "empty labelset")
}
if l, dup := lset.HasDuplicateLabelNames(); dup {
return 0, errors.Wrap(ErrInvalidSample, fmt.Sprintf(`label name "%s" is not unique`, l))
}
var created bool
var err error
s, created, err = a.head.getOrCreate(lset.Hash(), lset)
if err != nil {
return 0, err
}
if created {
a.series = append(a.series, record.RefSeries{
Ref: s.ref,
Labels: lset,
})
}
} }
s.Lock() s.Lock()
if err := s.appendable(t, v); err != nil { if err := s.appendable(t, v); err != nil {
s.Unlock() s.Unlock()
if err == storage.ErrOutOfOrderSample { if err == storage.ErrOutOfOrderSample {
a.head.metrics.outOfOrderSamples.Inc() a.head.metrics.outOfOrderSamples.Inc()
} }
return err return 0, err
} }
s.pendingCommit = true s.pendingCommit = true
s.Unlock() s.Unlock()
@ -1238,12 +1222,12 @@ func (a *headAppender) AddFast(ref uint64, t int64, v float64) error {
} }
a.samples = append(a.samples, record.RefSample{ a.samples = append(a.samples, record.RefSample{
Ref: ref, Ref: s.ref,
T: t, T: t,
V: v, V: v,
}) })
a.sampleSeries = append(a.sampleSeries, s) a.sampleSeries = append(a.sampleSeries, s)
return nil return s.ref, nil
} }
func (a *headAppender) log() error { func (a *headAppender) log() error {

View file

@ -275,14 +275,14 @@ func TestHead_WALMultiRef(t *testing.T) {
require.NoError(t, head.Init(0)) require.NoError(t, head.Init(0))
app := head.Appender(context.Background()) app := head.Appender(context.Background())
ref1, err := app.Add(labels.FromStrings("foo", "bar"), 100, 1) ref1, err := app.Append(0, labels.FromStrings("foo", "bar"), 100, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Equal(t, 1.0, prom_testutil.ToFloat64(head.metrics.chunksCreated)) require.Equal(t, 1.0, prom_testutil.ToFloat64(head.metrics.chunksCreated))
// Add another sample outside chunk range to mmap a chunk. // Add another sample outside chunk range to mmap a chunk.
app = head.Appender(context.Background()) app = head.Appender(context.Background())
_, err = app.Add(labels.FromStrings("foo", "bar"), 1500, 2) _, err = app.Append(0, labels.FromStrings("foo", "bar"), 1500, 2)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Equal(t, 2.0, prom_testutil.ToFloat64(head.metrics.chunksCreated)) require.Equal(t, 2.0, prom_testutil.ToFloat64(head.metrics.chunksCreated))
@ -290,14 +290,14 @@ func TestHead_WALMultiRef(t *testing.T) {
require.NoError(t, head.Truncate(1600)) require.NoError(t, head.Truncate(1600))
app = head.Appender(context.Background()) app = head.Appender(context.Background())
ref2, err := app.Add(labels.FromStrings("foo", "bar"), 1700, 3) ref2, err := app.Append(0, labels.FromStrings("foo", "bar"), 1700, 3)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Equal(t, 3.0, prom_testutil.ToFloat64(head.metrics.chunksCreated)) require.Equal(t, 3.0, prom_testutil.ToFloat64(head.metrics.chunksCreated))
// Add another sample outside chunk range to mmap a chunk. // Add another sample outside chunk range to mmap a chunk.
app = head.Appender(context.Background()) app = head.Appender(context.Background())
_, err = app.Add(labels.FromStrings("foo", "bar"), 2000, 4) _, err = app.Append(0, labels.FromStrings("foo", "bar"), 2000, 4)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Equal(t, 4.0, prom_testutil.ToFloat64(head.metrics.chunksCreated)) require.Equal(t, 4.0, prom_testutil.ToFloat64(head.metrics.chunksCreated))
@ -569,7 +569,7 @@ func TestHeadDeleteSimple(t *testing.T) {
app := head.Appender(context.Background()) app := head.Appender(context.Background())
for _, smpl := range smplsAll { for _, smpl := range smplsAll {
_, err := app.Add(labels.Labels{lblDefault}, smpl.t, smpl.v) _, err := app.Append(0, labels.Labels{lblDefault}, smpl.t, smpl.v)
require.NoError(t, err) require.NoError(t, err)
} }
@ -583,7 +583,7 @@ func TestHeadDeleteSimple(t *testing.T) {
// Add more samples. // Add more samples.
app = head.Appender(context.Background()) app = head.Appender(context.Background())
for _, smpl := range c.addSamples { for _, smpl := range c.addSamples {
_, err := app.Add(labels.Labels{lblDefault}, smpl.t, smpl.v) _, err := app.Append(0, labels.Labels{lblDefault}, smpl.t, smpl.v)
require.NoError(t, err) require.NoError(t, err)
} }
@ -655,7 +655,7 @@ func TestDeleteUntilCurMax(t *testing.T) {
smpls := make([]float64, numSamples) smpls := make([]float64, numSamples)
for i := int64(0); i < numSamples; i++ { for i := int64(0); i < numSamples; i++ {
smpls[i] = rand.Float64() smpls[i] = rand.Float64()
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i]) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, i, smpls[i])
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -676,7 +676,7 @@ func TestDeleteUntilCurMax(t *testing.T) {
// Add again and test for presence. // Add again and test for presence.
app = hb.Appender(context.Background()) app = hb.Appender(context.Background())
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 11, 1) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 11, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
q, err = NewBlockQuerier(hb, 0, 100000) q, err = NewBlockQuerier(hb, 0, 100000)
@ -702,7 +702,7 @@ func TestDeletedSamplesAndSeriesStillInWALAfterCheckpoint(t *testing.T) {
for i := 0; i < numSamples; i++ { for i := 0; i < numSamples; i++ {
app := hb.Appender(context.Background()) app := hb.Appender(context.Background())
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, int64(i), 0) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, int64(i), 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
} }
@ -800,7 +800,7 @@ func TestDelete_e2e(t *testing.T) {
ts := rand.Int63n(300) ts := rand.Int63n(300)
for i := 0; i < numDatapoints; i++ { for i := 0; i < numDatapoints; i++ {
v := rand.Float64() v := rand.Float64()
_, err := app.Add(ls, ts, v) _, err := app.Append(0, ls, ts, v)
require.NoError(t, err) require.NoError(t, err)
series = append(series, sample{ts, v}) series = append(series, sample{ts, v})
ts += rand.Int63n(timeInterval) + 1 ts += rand.Int63n(timeInterval) + 1
@ -1145,7 +1145,7 @@ func TestUncommittedSamplesNotLostOnTruncate(t *testing.T) {
app := h.appender() app := h.appender()
lset := labels.FromStrings("a", "1") lset := labels.FromStrings("a", "1")
_, err := app.Add(lset, 2100, 1) _, err := app.Append(0, lset, 2100, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, h.Truncate(2000)) require.NoError(t, h.Truncate(2000))
@ -1175,7 +1175,7 @@ func TestRemoveSeriesAfterRollbackAndTruncate(t *testing.T) {
app := h.appender() app := h.appender()
lset := labels.FromStrings("a", "1") lset := labels.FromStrings("a", "1")
_, err := app.Add(lset, 2100, 1) _, err := app.Append(0, lset, 2100, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, h.Truncate(2000)) require.NoError(t, h.Truncate(2000))
@ -1205,7 +1205,7 @@ func TestHead_LogRollback(t *testing.T) {
}() }()
app := h.Appender(context.Background()) app := h.Appender(context.Background())
_, err := app.Add(labels.FromStrings("a", "b"), 1, 2) _, err := app.Append(0, labels.FromStrings("a", "b"), 1, 2)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Rollback()) require.NoError(t, app.Rollback())
@ -1397,7 +1397,7 @@ func TestNewWalSegmentOnTruncate(t *testing.T) {
}() }()
add := func(ts int64) { add := func(ts int64) {
app := h.Appender(context.Background()) app := h.Appender(context.Background())
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, ts, 0) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, ts, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
} }
@ -1428,7 +1428,7 @@ func TestAddDuplicateLabelName(t *testing.T) {
add := func(labels labels.Labels, labelName string) { add := func(labels labels.Labels, labelName string) {
app := h.Appender(context.Background()) app := h.Appender(context.Background())
_, err := app.Add(labels, 0, 0) _, err := app.Append(0, labels, 0, 0)
require.Error(t, err) require.Error(t, err)
require.Equal(t, fmt.Sprintf(`label name "%s" is not unique: invalid sample`, labelName), err.Error()) require.Equal(t, fmt.Sprintf(`label name "%s" is not unique: invalid sample`, labelName), err.Error())
} }
@ -1489,7 +1489,7 @@ func TestMemSeriesIsolation(t *testing.T) {
app = a app = a
} }
_, err := app.Add(labels.FromStrings("foo", "bar"), int64(i), float64(i)) _, err := app.Append(0, labels.FromStrings("foo", "bar"), int64(i), float64(i))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
} }
@ -1517,7 +1517,7 @@ func TestMemSeriesIsolation(t *testing.T) {
// Cleanup appendIDs below 500. // Cleanup appendIDs below 500.
app := hb.appender() app := hb.appender()
app.cleanupAppendIDsBelow = 500 app.cleanupAppendIDsBelow = 500
_, err := app.Add(labels.FromStrings("foo", "bar"), int64(i), float64(i)) _, err := app.Append(0, labels.FromStrings("foo", "bar"), int64(i), float64(i))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
i++ i++
@ -1536,7 +1536,7 @@ func TestMemSeriesIsolation(t *testing.T) {
// the only thing with appendIDs. // the only thing with appendIDs.
app = hb.appender() app = hb.appender()
app.cleanupAppendIDsBelow = 1000 app.cleanupAppendIDsBelow = 1000
_, err = app.Add(labels.FromStrings("foo", "bar"), int64(i), float64(i)) _, err = app.Append(0, labels.FromStrings("foo", "bar"), int64(i), float64(i))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Equal(t, 999, lastValue(hb, 998)) require.Equal(t, 999, lastValue(hb, 998))
@ -1550,7 +1550,7 @@ func TestMemSeriesIsolation(t *testing.T) {
// Cleanup appendIDs below 1001, but with a rollback. // Cleanup appendIDs below 1001, but with a rollback.
app = hb.appender() app = hb.appender()
app.cleanupAppendIDsBelow = 1001 app.cleanupAppendIDsBelow = 1001
_, err = app.Add(labels.FromStrings("foo", "bar"), int64(i), float64(i)) _, err = app.Append(0, labels.FromStrings("foo", "bar"), int64(i), float64(i))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Rollback()) require.NoError(t, app.Rollback())
require.Equal(t, 1000, lastValue(hb, 999)) require.Equal(t, 1000, lastValue(hb, 999))
@ -1586,7 +1586,7 @@ func TestMemSeriesIsolation(t *testing.T) {
// Cleanup appendIDs below 1000, which means the sample buffer is // Cleanup appendIDs below 1000, which means the sample buffer is
// the only thing with appendIDs. // the only thing with appendIDs.
app = hb.appender() app = hb.appender()
_, err = app.Add(labels.FromStrings("foo", "bar"), int64(i), float64(i)) _, err = app.Append(0, labels.FromStrings("foo", "bar"), int64(i), float64(i))
i++ i++
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1599,7 +1599,7 @@ func TestMemSeriesIsolation(t *testing.T) {
// Cleanup appendIDs below 1002, but with a rollback. // Cleanup appendIDs below 1002, but with a rollback.
app = hb.appender() app = hb.appender()
_, err = app.Add(labels.FromStrings("foo", "bar"), int64(i), float64(i)) _, err = app.Append(0, labels.FromStrings("foo", "bar"), int64(i), float64(i))
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Rollback()) require.NoError(t, app.Rollback())
require.Equal(t, 1001, lastValue(hb, 999)) require.Equal(t, 1001, lastValue(hb, 999))
@ -1617,21 +1617,21 @@ func TestIsolationRollback(t *testing.T) {
}() }()
app := hb.Appender(context.Background()) app := hb.Appender(context.Background())
_, err := app.Add(labels.FromStrings("foo", "bar"), 0, 0) _, err := app.Append(0, labels.FromStrings("foo", "bar"), 0, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Equal(t, uint64(1), hb.iso.lowWatermark()) require.Equal(t, uint64(1), hb.iso.lowWatermark())
app = hb.Appender(context.Background()) app = hb.Appender(context.Background())
_, err = app.Add(labels.FromStrings("foo", "bar"), 1, 1) _, err = app.Append(0, labels.FromStrings("foo", "bar"), 1, 1)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.FromStrings("foo", "bar", "foo", "baz"), 2, 2) _, err = app.Append(0, labels.FromStrings("foo", "bar", "foo", "baz"), 2, 2)
require.Error(t, err) require.Error(t, err)
require.NoError(t, app.Rollback()) require.NoError(t, app.Rollback())
require.Equal(t, uint64(2), hb.iso.lowWatermark()) require.Equal(t, uint64(2), hb.iso.lowWatermark())
app = hb.Appender(context.Background()) app = hb.Appender(context.Background())
_, err = app.Add(labels.FromStrings("foo", "bar"), 3, 3) _, err = app.Append(0, labels.FromStrings("foo", "bar"), 3, 3)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Equal(t, uint64(3), hb.iso.lowWatermark(), "Low watermark should proceed to 3 even if append #2 was rolled back.") require.Equal(t, uint64(3), hb.iso.lowWatermark(), "Low watermark should proceed to 3 even if append #2 was rolled back.")
@ -1644,18 +1644,18 @@ func TestIsolationLowWatermarkMonotonous(t *testing.T) {
}() }()
app1 := hb.Appender(context.Background()) app1 := hb.Appender(context.Background())
_, err := app1.Add(labels.FromStrings("foo", "bar"), 0, 0) _, err := app1.Append(0, labels.FromStrings("foo", "bar"), 0, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app1.Commit()) require.NoError(t, app1.Commit())
require.Equal(t, uint64(1), hb.iso.lowWatermark(), "Low watermark should by 1 after 1st append.") require.Equal(t, uint64(1), hb.iso.lowWatermark(), "Low watermark should by 1 after 1st append.")
app1 = hb.Appender(context.Background()) app1 = hb.Appender(context.Background())
_, err = app1.Add(labels.FromStrings("foo", "bar"), 1, 1) _, err = app1.Append(0, labels.FromStrings("foo", "bar"), 1, 1)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, uint64(2), hb.iso.lowWatermark(), "Low watermark should be two, even if append is not committed yet.") require.Equal(t, uint64(2), hb.iso.lowWatermark(), "Low watermark should be two, even if append is not committed yet.")
app2 := hb.Appender(context.Background()) app2 := hb.Appender(context.Background())
_, err = app2.Add(labels.FromStrings("foo", "baz"), 1, 1) _, err = app2.Append(0, labels.FromStrings("foo", "baz"), 1, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app2.Commit()) require.NoError(t, app2.Commit())
require.Equal(t, uint64(2), hb.iso.lowWatermark(), "Low watermark should stay two because app1 is not committed yet.") require.Equal(t, uint64(2), hb.iso.lowWatermark(), "Low watermark should stay two because app1 is not committed yet.")
@ -1701,7 +1701,7 @@ func TestIsolationWithoutAdd(t *testing.T) {
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
app = hb.Appender(context.Background()) app = hb.Appender(context.Background())
_, err := app.Add(labels.FromStrings("foo", "baz"), 1, 1) _, err := app.Append(0, labels.FromStrings("foo", "baz"), 1, 1)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1725,7 +1725,7 @@ func TestOutOfOrderSamplesMetric(t *testing.T) {
ctx := context.Background() ctx := context.Background()
app := db.Appender(ctx) app := db.Appender(ctx)
for i := 1; i <= 5; i++ { for i := 1; i <= 5; i++ {
_, err = app.Add(labels.FromStrings("a", "b"), int64(i), 99) _, err = app.Append(0, labels.FromStrings("a", "b"), int64(i), 99)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1733,22 +1733,22 @@ func TestOutOfOrderSamplesMetric(t *testing.T) {
// Test out of order metric. // Test out of order metric.
require.Equal(t, 0.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples)) require.Equal(t, 0.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples))
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.FromStrings("a", "b"), 2, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), 2, 99)
require.Equal(t, storage.ErrOutOfOrderSample, err) require.Equal(t, storage.ErrOutOfOrderSample, err)
require.Equal(t, 1.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples)) require.Equal(t, 1.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples))
_, err = app.Add(labels.FromStrings("a", "b"), 3, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), 3, 99)
require.Equal(t, storage.ErrOutOfOrderSample, err) require.Equal(t, storage.ErrOutOfOrderSample, err)
require.Equal(t, 2.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples)) require.Equal(t, 2.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples))
_, err = app.Add(labels.FromStrings("a", "b"), 4, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), 4, 99)
require.Equal(t, storage.ErrOutOfOrderSample, err) require.Equal(t, storage.ErrOutOfOrderSample, err)
require.Equal(t, 3.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples)) require.Equal(t, 3.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples))
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
// Compact Head to test out of bound metric. // Compact Head to test out of bound metric.
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.FromStrings("a", "b"), DefaultBlockDuration*2, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), DefaultBlockDuration*2, 99)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1757,11 +1757,11 @@ func TestOutOfOrderSamplesMetric(t *testing.T) {
require.Greater(t, db.head.minValidTime.Load(), int64(0)) require.Greater(t, db.head.minValidTime.Load(), int64(0))
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.FromStrings("a", "b"), db.head.minValidTime.Load()-2, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), db.head.minValidTime.Load()-2, 99)
require.Equal(t, storage.ErrOutOfBounds, err) require.Equal(t, storage.ErrOutOfBounds, err)
require.Equal(t, 1.0, prom_testutil.ToFloat64(db.head.metrics.outOfBoundSamples)) require.Equal(t, 1.0, prom_testutil.ToFloat64(db.head.metrics.outOfBoundSamples))
_, err = app.Add(labels.FromStrings("a", "b"), db.head.minValidTime.Load()-1, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), db.head.minValidTime.Load()-1, 99)
require.Equal(t, storage.ErrOutOfBounds, err) require.Equal(t, storage.ErrOutOfBounds, err)
require.Equal(t, 2.0, prom_testutil.ToFloat64(db.head.metrics.outOfBoundSamples)) require.Equal(t, 2.0, prom_testutil.ToFloat64(db.head.metrics.outOfBoundSamples))
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1769,22 +1769,22 @@ func TestOutOfOrderSamplesMetric(t *testing.T) {
// Some more valid samples for out of order. // Some more valid samples for out of order.
app = db.Appender(ctx) app = db.Appender(ctx)
for i := 1; i <= 5; i++ { for i := 1; i <= 5; i++ {
_, err = app.Add(labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+int64(i), 99) _, err = app.Append(0, labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+int64(i), 99)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
// Test out of order metric. // Test out of order metric.
app = db.Appender(ctx) app = db.Appender(ctx)
_, err = app.Add(labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+2, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+2, 99)
require.Equal(t, storage.ErrOutOfOrderSample, err) require.Equal(t, storage.ErrOutOfOrderSample, err)
require.Equal(t, 4.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples)) require.Equal(t, 4.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples))
_, err = app.Add(labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+3, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+3, 99)
require.Equal(t, storage.ErrOutOfOrderSample, err) require.Equal(t, storage.ErrOutOfOrderSample, err)
require.Equal(t, 5.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples)) require.Equal(t, 5.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples))
_, err = app.Add(labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+4, 99) _, err = app.Append(0, labels.FromStrings("a", "b"), db.head.minValidTime.Load()+DefaultBlockDuration+4, 99)
require.Equal(t, storage.ErrOutOfOrderSample, err) require.Equal(t, storage.ErrOutOfOrderSample, err)
require.Equal(t, 6.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples)) require.Equal(t, 6.0, prom_testutil.ToFloat64(db.head.metrics.outOfOrderSamples))
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1798,10 +1798,10 @@ func testHeadSeriesChunkRace(t *testing.T) {
require.NoError(t, h.Init(0)) require.NoError(t, h.Init(0))
app := h.Appender(context.Background()) app := h.Appender(context.Background())
s2, err := app.Add(labels.FromStrings("foo2", "bar"), 5, 0) s2, err := app.Append(0, labels.FromStrings("foo2", "bar"), 5, 0)
require.NoError(t, err) require.NoError(t, err)
for ts := int64(6); ts < 11; ts++ { for ts := int64(6); ts < 11; ts++ {
err = app.AddFast(s2, ts, 0) _, err = app.Append(s2, nil, ts, 0)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1847,7 +1847,7 @@ func TestHeadLabelNamesValuesWithMinMaxRange(t *testing.T) {
app := head.Appender(context.Background()) app := head.Appender(context.Background())
for i, name := range expectedLabelNames { for i, name := range expectedLabelNames {
_, err := app.Add(labels.Labels{{Name: name, Value: expectedLabelValues[i]}}, seriesTimestamps[i], 0) _, err := app.Append(0, labels.Labels{{Name: name, Value: expectedLabelValues[i]}}, seriesTimestamps[i], 0)
require.NoError(t, err) require.NoError(t, err)
} }
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -1892,7 +1892,7 @@ func TestHeadLabelValuesWithMatchers(t *testing.T) {
app := head.Appender(context.Background()) app := head.Appender(context.Background())
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
_, err := app.Add(labels.Labels{ _, err := app.Append(0, labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)}, {Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/10)}, {Name: "tens", Value: fmt.Sprintf("value%d", i/10)},
}, 100, 0) }, 100, 0)
@ -1952,28 +1952,28 @@ func TestErrReuseAppender(t *testing.T) {
}() }()
app := head.Appender(context.Background()) app := head.Appender(context.Background())
_, err := app.Add(labels.Labels{{Name: "test", Value: "test"}}, 0, 0) _, err := app.Append(0, labels.Labels{{Name: "test", Value: "test"}}, 0, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Error(t, app.Commit()) require.Error(t, app.Commit())
require.Error(t, app.Rollback()) require.Error(t, app.Rollback())
app = head.Appender(context.Background()) app = head.Appender(context.Background())
_, err = app.Add(labels.Labels{{Name: "test", Value: "test"}}, 1, 0) _, err = app.Append(0, labels.Labels{{Name: "test", Value: "test"}}, 1, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Rollback()) require.NoError(t, app.Rollback())
require.Error(t, app.Rollback()) require.Error(t, app.Rollback())
require.Error(t, app.Commit()) require.Error(t, app.Commit())
app = head.Appender(context.Background()) app = head.Appender(context.Background())
_, err = app.Add(labels.Labels{{Name: "test", Value: "test"}}, 2, 0) _, err = app.Append(0, labels.Labels{{Name: "test", Value: "test"}}, 2, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
require.Error(t, app.Rollback()) require.Error(t, app.Rollback())
require.Error(t, app.Commit()) require.Error(t, app.Commit())
app = head.Appender(context.Background()) app = head.Appender(context.Background())
_, err = app.Add(labels.Labels{{Name: "test", Value: "test"}}, 3, 0) _, err = app.Append(0, labels.Labels{{Name: "test", Value: "test"}}, 3, 0)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Rollback()) require.NoError(t, app.Rollback())
require.Error(t, app.Commit()) require.Error(t, app.Commit())
@ -1985,11 +1985,11 @@ func TestHeadMintAfterTruncation(t *testing.T) {
head, _ := newTestHead(t, chunkRange, false) head, _ := newTestHead(t, chunkRange, false)
app := head.Appender(context.Background()) app := head.Appender(context.Background())
_, err := app.Add(labels.Labels{{Name: "a", Value: "b"}}, 100, 100) _, err := app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 100, 100)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 4000, 200) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 4000, 200)
require.NoError(t, err) require.NoError(t, err)
_, err = app.Add(labels.Labels{{Name: "a", Value: "b"}}, 8000, 300) _, err = app.Append(0, labels.Labels{{Name: "a", Value: "b"}}, 8000, 300)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
@ -2023,7 +2023,7 @@ func BenchmarkHeadLabelValuesWithMatchers(b *testing.B) {
metricCount := 1000000 metricCount := 1000000
for i := 0; i < metricCount; i++ { for i := 0; i < metricCount; i++ {
_, err := app.Add(labels.Labels{ _, err := app.Append(0, labels.Labels{
{Name: "unique", Value: fmt.Sprintf("value%d", i)}, {Name: "unique", Value: fmt.Sprintf("value%d", i)},
{Name: "tens", Value: fmt.Sprintf("value%d", i/(metricCount/10))}, {Name: "tens", Value: fmt.Sprintf("value%d", i/(metricCount/10))},
{Name: "ninety", Value: fmt.Sprintf("value%d", i/(metricCount/10)/9)}, // "0" for the first 90%, then "1" {Name: "ninety", Value: fmt.Sprintf("value%d", i/(metricCount/10)/9)}, // "0" for the first 90%, then "1"

View file

@ -48,7 +48,7 @@ func BenchmarkPostingsForMatchers(b *testing.B) {
app := h.Appender(context.Background()) app := h.Appender(context.Background())
addSeries := func(l labels.Labels) { addSeries := func(l labels.Labels) {
app.Add(l, 0, 0) app.Append(0, l, 0, 0)
} }
for n := 0; n < 10; n++ { for n := 0; n < 10; n++ {
@ -158,7 +158,7 @@ func BenchmarkQuerierSelect(b *testing.B) {
app := h.Appender(context.Background()) app := h.Appender(context.Background())
numSeries := 1000000 numSeries := 1000000
for i := 0; i < numSeries; i++ { for i := 0; i < numSeries; i++ {
app.Add(labels.FromStrings("foo", "bar", "i", fmt.Sprintf("%d%s", i, postingsBenchSuffix)), int64(i), 0) app.Append(0, labels.FromStrings("foo", "bar", "i", fmt.Sprintf("%d%s", i, postingsBenchSuffix)), int64(i), 0)
} }
require.NoError(b, app.Commit()) require.NoError(b, app.Commit())

View file

@ -417,7 +417,7 @@ func TestBlockQuerier_AgainstHeadWithOpenChunks(t *testing.T) {
for _, s := range testData { for _, s := range testData {
for _, chk := range s.chunks { for _, chk := range s.chunks {
for _, sample := range chk { for _, sample := range chk {
_, err = app.Add(labels.FromMap(s.lset), sample.t, sample.v) _, err = app.Append(0, labels.FromMap(s.lset), sample.t, sample.v)
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -1579,11 +1579,11 @@ func TestPostingsForMatchers(t *testing.T) {
}() }()
app := h.Appender(context.Background()) app := h.Appender(context.Background())
app.Add(labels.FromStrings("n", "1"), 0, 0) app.Append(0, labels.FromStrings("n", "1"), 0, 0)
app.Add(labels.FromStrings("n", "1", "i", "a"), 0, 0) app.Append(0, labels.FromStrings("n", "1", "i", "a"), 0, 0)
app.Add(labels.FromStrings("n", "1", "i", "b"), 0, 0) app.Append(0, labels.FromStrings("n", "1", "i", "b"), 0, 0)
app.Add(labels.FromStrings("n", "2"), 0, 0) app.Append(0, labels.FromStrings("n", "2"), 0, 0)
app.Add(labels.FromStrings("n", "2.5"), 0, 0) app.Append(0, labels.FromStrings("n", "2.5"), 0, 0)
require.NoError(t, app.Commit()) require.NoError(t, app.Commit())
cases := []struct { cases := []struct {

View file

@ -50,14 +50,10 @@ func CreateBlock(series []storage.Series, dir string, chunkRange int64, logger l
for _, s := range series { for _, s := range series {
ref := uint64(0) ref := uint64(0)
it := s.Iterator() it := s.Iterator()
lset := s.Labels()
for it.Next() { for it.Next() {
t, v := it.At() t, v := it.At()
if ref != 0 { ref, err = app.Append(ref, lset, t, v)
if err := app.AddFast(ref, t, v); err == nil {
continue
}
}
ref, err = app.Add(s.Labels(), t, v)
if err != nil { if err != nil {
return "", err return "", err
} }