diff --git a/pkg/storage/stores/tsdb/builder.go b/pkg/storage/stores/tsdb/builder.go index 3bfb2802ceda..6fcb3f63d347 100644 --- a/pkg/storage/stores/tsdb/builder.go +++ b/pkg/storage/stores/tsdb/builder.go @@ -81,9 +81,14 @@ func (b *Builder) Build( for _, s := range b.streams { streams = append(streams, s) } + + // Use the supplied fingerprints instead of hashing labels for two reasons: + // 1) Correctness: fingerprints differ from label hashes because + // we add a synthesized __loki_tennat__ label, which is eventually compacted away. + // 2) Speed: No hashing required sort.Slice(streams, func(i, j int) bool { - if a, b := streams[i].labels.Hash(), streams[j].labels.Hash(); a != b { - return a < b + if streams[i].fp != streams[j].fp { + return streams[i].fp < streams[j].fp } return labels.Compare(streams[i].labels, streams[j].labels) < 0 }) diff --git a/pkg/storage/stores/tsdb/index/index.go b/pkg/storage/stores/tsdb/index/index.go index 9e90461a8bd1..d2d9f7b2f73d 100644 --- a/pkg/storage/stores/tsdb/index/index.go +++ b/pkg/storage/stores/tsdb/index/index.go @@ -446,7 +446,12 @@ func (w *Writer) AddSeries(ref storage.SeriesRef, lset labels.Labels, fp model.F return err } + // Put the supplied fingerprint instead of the calculated hash. + // This allows us to have a synthetic label (__loki_tenant__) in + // the pre-compacted TSDBs which map to fingerprints (and chunks) + // without this label in storage. labelHash := uint64(fp) + lastHash := w.lastSeriesHash // Ensure series are sorted by the priorities: [`hash(labels)`, `labels`] if (labelHash < lastHash && len(w.lastSeries) > 0) || labelHash == lastHash && labels.Compare(lset, w.lastSeries) < 0 {