From 8ab0a6e2add1a9e40350a32b6e709bdc87eb4080 Mon Sep 17 00:00:00 2001 From: Jerome Meyer Date: Thu, 30 Jan 2020 11:41:57 -0500 Subject: [PATCH 01/55] Added externalURL and pathPrefix functions to Template reference documentation Signed-off-by: Jerome Meyer --- docs/configuration/template_reference.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/configuration/template_reference.md b/docs/configuration/template_reference.md index fe2b60b233..475946923b 100644 --- a/docs/configuration/template_reference.md +++ b/docs/configuration/template_reference.md @@ -82,6 +82,8 @@ versions. | args | []interface{} | map[string]interface{} | This converts a list of objects to a map with keys arg0, arg1 etc. This is intended to allow multiple arguments to be passed to templates. | | tmpl | string, []interface{} | nothing | Like the built-in `template`, but allows non-literals as the template name. Note that the result is assumed to be safe, and will not be auto-escaped. Only available in consoles. | | safeHtml | string | string | Marks string as HTML not requiring auto-escaping. | +| externalURL | none | string | The URL under which Prometheus is externally reachable (set with `--web.external-url`). | +| pathPrefix | none | string | Path portion of the external URL. | ## Template type differences From c7c7847b6f12fa11821ab2927ba4b8d8888d9f07 Mon Sep 17 00:00:00 2001 From: Jinwook Jeong Date: Sat, 9 Apr 2022 01:03:54 +0900 Subject: [PATCH 02/55] Fix discovery managers to be properly cancelled Signed-off-by: Jinwook Jeong --- discovery/legacymanager/manager.go | 8 +++----- discovery/manager.go | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/discovery/legacymanager/manager.go b/discovery/legacymanager/manager.go index 7a3d6b3b82..2c8ba18a03 100644 --- a/discovery/legacymanager/manager.go +++ b/discovery/legacymanager/manager.go @@ -140,11 +140,9 @@ type Manager struct { // Run starts the background processing func (m *Manager) Run() error { go m.sender() - for range m.ctx.Done() { - m.cancelDiscoverers() - return m.ctx.Err() - } - return nil + <-m.ctx.Done() + m.cancelDiscoverers() + return m.ctx.Err() } // SyncCh returns a read only channel used by all the clients to receive target updates. diff --git a/discovery/manager.go b/discovery/manager.go index 088b9722cb..6747c56908 100644 --- a/discovery/manager.go +++ b/discovery/manager.go @@ -166,11 +166,9 @@ type Manager struct { // Run starts the background processing. func (m *Manager) Run() error { go m.sender() - for range m.ctx.Done() { - m.cancelDiscoverers() - return m.ctx.Err() - } - return nil + <-m.ctx.Done() + m.cancelDiscoverers() + return m.ctx.Err() } // SyncCh returns a read only channel used by all the clients to receive target updates. From a018a7ef5379cd8969dee4f36b091d0088286502 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 17 Aug 2023 07:42:18 +0100 Subject: [PATCH 03/55] storage: simplify Seek on BufferedSeriesIterator Small tweak to call a simpler method Signed-off-by: Bryan Boreham --- storage/buffer.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/storage/buffer.go b/storage/buffer.go index 38f5591039..50810b8189 100644 --- a/storage/buffer.go +++ b/storage/buffer.go @@ -92,12 +92,8 @@ func (b *BufferedSeriesIterator) Seek(t int64) chunkenc.ValueType { switch b.valueType { case chunkenc.ValNone: return chunkenc.ValNone - case chunkenc.ValFloat: - b.lastTime, _ = b.At() - case chunkenc.ValHistogram: - b.lastTime, _ = b.AtHistogram() - case chunkenc.ValFloatHistogram: - b.lastTime, _ = b.AtFloatHistogram() + case chunkenc.ValFloat, chunkenc.ValHistogram, chunkenc.ValFloatHistogram: + b.lastTime = b.AtT() default: panic(fmt.Errorf("BufferedSeriesIterator: unknown value type %v", b.valueType)) } From bdc7983956310b4ea75b645ea4dd96ed99ef3a69 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sat, 26 Aug 2023 14:01:15 +0000 Subject: [PATCH 04/55] TSDB: re-use iterator when moving between series Signed-off-by: Bryan Boreham --- tsdb/querier.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsdb/querier.go b/tsdb/querier.go index 965707547e..5d37497b30 100644 --- a/tsdb/querier.go +++ b/tsdb/querier.go @@ -622,7 +622,7 @@ func (p *populateWithDelGenericSeriesIterator) reset(blockID ulid.ULID, cr Chunk p.chks = chks p.i = -1 p.err = nil - p.bufIter.Iter = nil + // Note we don't touch p.bufIter.Iter; it is holding on to an iterator we might reuse in next(). p.bufIter.Intervals = p.bufIter.Intervals[:0] p.intervals = intervals p.currDelIter = nil From 86729d4d7b8659e2b90fa65ae2d42ecddc3657bc Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Thu, 21 Sep 2023 22:53:51 +0200 Subject: [PATCH 05/55] Update exp package (#12650) --- cmd/promtool/tsdb.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- model/labels/labels.go | 9 +++++---- model/labels/labels_stringlabels.go | 7 ++++--- promql/quantile.go | 11 +++++++++-- rules/manager.go | 21 ++++++++++++++------- scrape/scrape.go | 4 ++-- storage/remote/codec.go | 4 ++-- storage/remote/read_handler.go | 5 +++-- tsdb/compact.go | 8 ++++---- tsdb/db.go | 12 ++++++------ tsdb/exemplar.go | 4 ++-- tsdb/head_read.go | 4 ++-- tsdb/index/postings.go | 12 ++++++++---- tsdb/index/postingsstats.go | 4 +--- tsdb/ooo_head_read.go | 12 ++++++------ tsdb/querier.go | 8 ++++++-- tsdb/wlog/checkpoint.go | 4 ++-- tsdb/wlog/wlog.go | 4 ++-- util/stats/timer.go | 4 +--- web/federate.go | 5 +++-- 22 files changed, 86 insertions(+), 64 deletions(-) diff --git a/cmd/promtool/tsdb.go b/cmd/promtool/tsdb.go index 5aa7e9bfe7..85aeacc11e 100644 --- a/cmd/promtool/tsdb.go +++ b/cmd/promtool/tsdb.go @@ -459,7 +459,7 @@ func analyzeBlock(ctx context.Context, path, blockID string, limit int, runExten postingInfos := []postingInfo{} printInfo := func(postingInfos []postingInfo) { - slices.SortFunc(postingInfos, func(a, b postingInfo) bool { return a.metric > b.metric }) + slices.SortFunc(postingInfos, func(a, b postingInfo) int { return int(b.metric) - int(a.metric) }) for i, pc := range postingInfos { if i >= limit { diff --git a/go.mod b/go.mod index ada0572684..1cdca0f989 100644 --- a/go.mod +++ b/go.mod @@ -185,7 +185,7 @@ require ( go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect golang.org/x/crypto v0.11.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 + golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b golang.org/x/mod v0.12.0 // indirect golang.org/x/term v0.10.0 // indirect golang.org/x/text v0.11.0 // indirect diff --git a/go.sum b/go.sum index 04824f3c29..bdf4f59477 100644 --- a/go.sum +++ b/go.sum @@ -853,8 +853,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b h1:r+vk0EmXNmekl0S0BascoeeoHk/L7wmaW2QF90K+kYI= +golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/model/labels/labels.go b/model/labels/labels.go index 0c27e15c72..3dc3049b1c 100644 --- a/model/labels/labels.go +++ b/model/labels/labels.go @@ -19,6 +19,7 @@ import ( "bytes" "encoding/json" "strconv" + "strings" "github.com/cespare/xxhash/v2" "github.com/prometheus/common/model" @@ -362,7 +363,7 @@ func EmptyLabels() Labels { func New(ls ...Label) Labels { set := make(Labels, 0, len(ls)) set = append(set, ls...) - slices.SortFunc(set, func(a, b Label) bool { return a.Name < b.Name }) + slices.SortFunc(set, func(a, b Label) int { return strings.Compare(a.Name, b.Name) }) return set } @@ -386,7 +387,7 @@ func FromStrings(ss ...string) Labels { res = append(res, Label{Name: ss[i], Value: ss[i+1]}) } - slices.SortFunc(res, func(a, b Label) bool { return a.Name < b.Name }) + slices.SortFunc(res, func(a, b Label) int { return strings.Compare(a.Name, b.Name) }) return res } @@ -591,7 +592,7 @@ func (b *Builder) Labels() Labels { } if len(b.add) > 0 { // Base is already in order, so we only need to sort if we add to it. res = append(res, b.add...) - slices.SortFunc(res, func(a, b Label) bool { return a.Name < b.Name }) + slices.SortFunc(res, func(a, b Label) int { return strings.Compare(a.Name, b.Name) }) } return res } @@ -618,7 +619,7 @@ func (b *ScratchBuilder) Add(name, value string) { // Sort the labels added so far by name. func (b *ScratchBuilder) Sort() { - slices.SortFunc(b.add, func(a, b Label) bool { return a.Name < b.Name }) + slices.SortFunc(b.add, func(a, b Label) int { return strings.Compare(a.Name, b.Name) }) } // Assign is for when you already have a Labels which you want this ScratchBuilder to return. diff --git a/model/labels/labels_stringlabels.go b/model/labels/labels_stringlabels.go index a87545a26b..cc6bfcc700 100644 --- a/model/labels/labels_stringlabels.go +++ b/model/labels/labels_stringlabels.go @@ -20,6 +20,7 @@ import ( "encoding/json" "reflect" "strconv" + "strings" "unsafe" "github.com/cespare/xxhash/v2" @@ -412,7 +413,7 @@ func yoloBytes(s string) (b []byte) { // New returns a sorted Labels from the given labels. // The caller has to guarantee that all label names are unique. func New(ls ...Label) Labels { - slices.SortFunc(ls, func(a, b Label) bool { return a.Name < b.Name }) + slices.SortFunc(ls, func(a, b Label) int { return strings.Compare(a.Name, b.Name) }) size := labelsSize(ls) buf := make([]byte, size) marshalLabelsToSizedBuffer(ls, buf) @@ -671,7 +672,7 @@ func (b *Builder) Labels() Labels { return b.base } - slices.SortFunc(b.add, func(a, b Label) bool { return a.Name < b.Name }) + slices.SortFunc(b.add, func(a, b Label) int { return strings.Compare(a.Name, b.Name) }) slices.Sort(b.del) a, d := 0, 0 @@ -830,7 +831,7 @@ func (b *ScratchBuilder) Add(name, value string) { // Sort the labels added so far by name. func (b *ScratchBuilder) Sort() { - slices.SortFunc(b.add, func(a, b Label) bool { return a.Name < b.Name }) + slices.SortFunc(b.add, func(a, b Label) int { return strings.Compare(a.Name, b.Name) }) } // Assign is for when you already have a Labels which you want this ScratchBuilder to return. diff --git a/promql/quantile.go b/promql/quantile.go index 7f48b5945c..06a02a8d42 100644 --- a/promql/quantile.go +++ b/promql/quantile.go @@ -81,8 +81,15 @@ func bucketQuantile(q float64, buckets buckets) float64 { if q > 1 { return math.Inf(+1) } - slices.SortFunc(buckets, func(a, b bucket) bool { - return a.upperBound < b.upperBound + slices.SortFunc(buckets, func(a, b bucket) int { + // We don't expect the bucket boundary to be a NaN. + if a.upperBound < b.upperBound { + return -1 + } + if a.upperBound > b.upperBound { + return +1 + } + return 0 }) if !math.IsInf(buckets[len(buckets)-1].upperBound, +1) { return math.NaN() diff --git a/rules/manager.go b/rules/manager.go index e5e248cded..4e10d39c7d 100644 --- a/rules/manager.go +++ b/rules/manager.go @@ -19,6 +19,7 @@ import ( "fmt" "math" "net/url" + "strings" "sync" "time" @@ -490,9 +491,11 @@ func (g *Group) AlertingRules() []*AlertingRule { alerts = append(alerts, alertingRule) } } - slices.SortFunc(alerts, func(a, b *AlertingRule) bool { - return a.State() > b.State() || - (a.State() == b.State() && a.Name() < b.Name()) + slices.SortFunc(alerts, func(a, b *AlertingRule) int { + if a.State() == b.State() { + return strings.Compare(a.Name(), b.Name()) + } + return int(b.State() - a.State()) }) return alerts } @@ -1203,11 +1206,15 @@ func (m *Manager) RuleGroups() []*Group { rgs = append(rgs, g) } - slices.SortFunc(rgs, func(a, b *Group) bool { - if a.file != b.file { - return a.file < b.file + slices.SortFunc(rgs, func(a, b *Group) int { + fileCompare := strings.Compare(a.file, b.file) + + // If its 0, then the file names are the same. + // Lets look at the group names in that case. + if fileCompare != 0 { + return fileCompare } - return a.name < b.name + return strings.Compare(a.name, b.name) }) return rgs diff --git a/scrape/scrape.go b/scrape/scrape.go index b52616a01a..4d13d7f6b1 100644 --- a/scrape/scrape.go +++ b/scrape/scrape.go @@ -732,8 +732,8 @@ func mutateSampleLabels(lset labels.Labels, target *Target, honor bool, rc []*re } func resolveConflictingExposedLabels(lb *labels.Builder, conflictingExposedLabels []labels.Label) { - slices.SortStableFunc(conflictingExposedLabels, func(a, b labels.Label) bool { - return len(a.Name) < len(b.Name) + slices.SortStableFunc(conflictingExposedLabels, func(a, b labels.Label) int { + return len(a.Name) - len(b.Name) }) for _, l := range conflictingExposedLabels { diff --git a/storage/remote/codec.go b/storage/remote/codec.go index 4e0166d17e..4c190f2a4e 100644 --- a/storage/remote/codec.go +++ b/storage/remote/codec.go @@ -187,8 +187,8 @@ func FromQueryResult(sortSeries bool, res *prompb.QueryResult) storage.SeriesSet } if sortSeries { - slices.SortFunc(series, func(a, b storage.Series) bool { - return labels.Compare(a.Labels(), b.Labels()) < 0 + slices.SortFunc(series, func(a, b storage.Series) int { + return labels.Compare(a.Labels(), b.Labels()) }) } return &concreteSeriesSet{ diff --git a/storage/remote/read_handler.go b/storage/remote/read_handler.go index 5cb4d39774..e2702c9f77 100644 --- a/storage/remote/read_handler.go +++ b/storage/remote/read_handler.go @@ -16,6 +16,7 @@ package remote import ( "context" "net/http" + "strings" "sync" "github.com/go-kit/log" @@ -93,8 +94,8 @@ func (h *readHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Value: value, }) } - slices.SortFunc(sortedExternalLabels, func(a, b prompb.Label) bool { - return a.Name < b.Name + slices.SortFunc(sortedExternalLabels, func(a, b prompb.Label) int { + return strings.Compare(a.Name, b.Name) }) responseType, err := NegotiateResponseType(req.AcceptedResponseTypes) diff --git a/tsdb/compact.go b/tsdb/compact.go index 7f5c307638..ca3a950960 100644 --- a/tsdb/compact.go +++ b/tsdb/compact.go @@ -200,8 +200,8 @@ func (c *LeveledCompactor) Plan(dir string) ([]string, error) { } func (c *LeveledCompactor) plan(dms []dirMeta) ([]string, error) { - slices.SortFunc(dms, func(a, b dirMeta) bool { - return a.meta.MinTime < b.meta.MinTime + slices.SortFunc(dms, func(a, b dirMeta) int { + return int(a.meta.MinTime - b.meta.MinTime) }) res := c.selectOverlappingDirs(dms) @@ -380,8 +380,8 @@ func CompactBlockMetas(uid ulid.ULID, blocks ...*BlockMeta) *BlockMeta { for s := range sources { res.Compaction.Sources = append(res.Compaction.Sources, s) } - slices.SortFunc(res.Compaction.Sources, func(a, b ulid.ULID) bool { - return a.Compare(b) < 0 + slices.SortFunc(res.Compaction.Sources, func(a, b ulid.ULID) int { + return a.Compare(b) }) res.MinTime = mint diff --git a/tsdb/db.go b/tsdb/db.go index 8a1c084f20..5c7040703a 100644 --- a/tsdb/db.go +++ b/tsdb/db.go @@ -579,8 +579,8 @@ func (db *DBReadOnly) Blocks() ([]BlockReader, error) { return nil, nil } - slices.SortFunc(loadable, func(a, b *Block) bool { - return a.Meta().MinTime < b.Meta().MinTime + slices.SortFunc(loadable, func(a, b *Block) int { + return int(a.Meta().MinTime - b.Meta().MinTime) }) blockMetas := make([]BlockMeta, 0, len(loadable)) @@ -1447,8 +1447,8 @@ func (db *DB) reloadBlocks() (err error) { } db.metrics.blocksBytes.Set(float64(blocksSize)) - slices.SortFunc(toLoad, func(a, b *Block) bool { - return a.Meta().MinTime < b.Meta().MinTime + slices.SortFunc(toLoad, func(a, b *Block) int { + return int(a.Meta().MinTime - b.Meta().MinTime) }) // Swap new blocks first for subsequently created readers to be seen. @@ -1517,8 +1517,8 @@ func deletableBlocks(db *DB, blocks []*Block) map[ulid.ULID]struct{} { // Sort the blocks by time - newest to oldest (largest to smallest timestamp). // This ensures that the retentions will remove the oldest blocks. - slices.SortFunc(blocks, func(a, b *Block) bool { - return a.Meta().MaxTime > b.Meta().MaxTime + slices.SortFunc(blocks, func(a, b *Block) int { + return int(b.Meta().MaxTime - a.Meta().MaxTime) }) for _, block := range blocks { diff --git a/tsdb/exemplar.go b/tsdb/exemplar.go index d4c0505cc1..904fc7c2bd 100644 --- a/tsdb/exemplar.go +++ b/tsdb/exemplar.go @@ -185,8 +185,8 @@ func (ce *CircularExemplarStorage) Select(start, end int64, matchers ...[]*label } } - slices.SortFunc(ret, func(a, b exemplar.QueryResult) bool { - return labels.Compare(a.SeriesLabels, b.SeriesLabels) < 0 + slices.SortFunc(ret, func(a, b exemplar.QueryResult) int { + return labels.Compare(a.SeriesLabels, b.SeriesLabels) }) return ret, nil diff --git a/tsdb/head_read.go b/tsdb/head_read.go index f7c04991ad..6964d5472b 100644 --- a/tsdb/head_read.go +++ b/tsdb/head_read.go @@ -136,8 +136,8 @@ func (h *headIndexReader) SortedPostings(p index.Postings) index.Postings { return index.ErrPostings(errors.Wrap(err, "expand postings")) } - slices.SortFunc(series, func(a, b *memSeries) bool { - return labels.Compare(a.lset, b.lset) < 0 + slices.SortFunc(series, func(a, b *memSeries) int { + return labels.Compare(a.lset, b.lset) }) // Convert back to list. diff --git a/tsdb/index/postings.go b/tsdb/index/postings.go index 97fc04d4f1..e5fa5fc540 100644 --- a/tsdb/index/postings.go +++ b/tsdb/index/postings.go @@ -19,6 +19,7 @@ import ( "encoding/binary" "runtime" "sort" + "strings" "sync" "github.com/pkg/errors" @@ -108,11 +109,14 @@ func (p *MemPostings) SortedKeys() []labels.Label { } p.mtx.RUnlock() - slices.SortFunc(keys, func(a, b labels.Label) bool { - if a.Name != b.Name { - return a.Name < b.Name + slices.SortFunc(keys, func(a, b labels.Label) int { + nameCompare := strings.Compare(a.Name, b.Name) + // If names are the same, compare values. + if nameCompare != 0 { + return nameCompare } - return a.Value < b.Value + + return strings.Compare(a.Value, b.Value) }) return keys } diff --git a/tsdb/index/postingsstats.go b/tsdb/index/postingsstats.go index 8e5f62dbac..70622b3d27 100644 --- a/tsdb/index/postingsstats.go +++ b/tsdb/index/postingsstats.go @@ -63,8 +63,6 @@ func (m *maxHeap) push(item Stat) { } func (m *maxHeap) get() []Stat { - slices.SortFunc(m.Items, func(a, b Stat) bool { - return a.Count > b.Count - }) + slices.SortFunc(m.Items, func(a, b Stat) int { return int(b.Count - a.Count) }) return m.Items } diff --git a/tsdb/ooo_head_read.go b/tsdb/ooo_head_read.go index 792fc4c8be..198bc4f2f4 100644 --- a/tsdb/ooo_head_read.go +++ b/tsdb/ooo_head_read.go @@ -177,18 +177,18 @@ type chunkMetaAndChunkDiskMapperRef struct { origMaxT int64 } -func refLessByMinTimeAndMinRef(a, b chunkMetaAndChunkDiskMapperRef) bool { +func refLessByMinTimeAndMinRef(a, b chunkMetaAndChunkDiskMapperRef) int { if a.meta.MinTime == b.meta.MinTime { - return a.meta.Ref < b.meta.Ref + return int(a.meta.Ref - b.meta.Ref) } - return a.meta.MinTime < b.meta.MinTime + return int(a.meta.MinTime - b.meta.MinTime) } -func lessByMinTimeAndMinRef(a, b chunks.Meta) bool { +func lessByMinTimeAndMinRef(a, b chunks.Meta) int { if a.MinTime == b.MinTime { - return a.Ref < b.Ref + return int(a.Ref - b.Ref) } - return a.MinTime < b.MinTime + return int(a.MinTime - b.MinTime) } func (oh *OOOHeadIndexReader) Postings(ctx context.Context, name string, values ...string) (index.Postings, error) { diff --git a/tsdb/querier.go b/tsdb/querier.go index f957ad2536..96406f1bdf 100644 --- a/tsdb/querier.go +++ b/tsdb/querier.go @@ -279,8 +279,12 @@ func PostingsForMatchers(ctx context.Context, ix IndexReader, ms ...*labels.Matc // there is no chance that the set we subtract from // contains postings of series that didn't exist when // we constructed the set we subtract by. - slices.SortStableFunc(ms, func(i, j *labels.Matcher) bool { - return !isSubtractingMatcher(i) && isSubtractingMatcher(j) + slices.SortStableFunc(ms, func(i, j *labels.Matcher) int { + if !isSubtractingMatcher(i) && isSubtractingMatcher(j) { + return -1 + } + + return +1 }) for _, m := range ms { diff --git a/tsdb/wlog/checkpoint.go b/tsdb/wlog/checkpoint.go index dd52ea2e3d..d64599c276 100644 --- a/tsdb/wlog/checkpoint.go +++ b/tsdb/wlog/checkpoint.go @@ -374,8 +374,8 @@ func listCheckpoints(dir string) (refs []checkpointRef, err error) { refs = append(refs, checkpointRef{name: fi.Name(), index: idx}) } - slices.SortFunc(refs, func(a, b checkpointRef) bool { - return a.index < b.index + slices.SortFunc(refs, func(a, b checkpointRef) int { + return a.index - b.index }) return refs, nil diff --git a/tsdb/wlog/wlog.go b/tsdb/wlog/wlog.go index d898ebd7ac..fd65fca07a 100644 --- a/tsdb/wlog/wlog.go +++ b/tsdb/wlog/wlog.go @@ -909,8 +909,8 @@ func listSegments(dir string) (refs []segmentRef, err error) { } refs = append(refs, segmentRef{name: fn, index: k}) } - slices.SortFunc(refs, func(a, b segmentRef) bool { - return a.index < b.index + slices.SortFunc(refs, func(a, b segmentRef) int { + return a.index - b.index }) for i := 0; i < len(refs)-1; i++ { if refs[i].index+1 != refs[i+1].index { diff --git a/util/stats/timer.go b/util/stats/timer.go index df1e2f931c..b7d79f4121 100644 --- a/util/stats/timer.go +++ b/util/stats/timer.go @@ -85,9 +85,7 @@ func (t *TimerGroup) String() string { for _, timer := range t.timers { timers = append(timers, timer) } - slices.SortFunc(timers, func(a, b *Timer) bool { - return a.created < b.created - }) + slices.SortFunc(timers, func(a, b *Timer) int { return a.created - b.created }) result := &bytes.Buffer{} for _, timer := range timers { fmt.Fprintf(result, "%s\n", timer) diff --git a/web/federate.go b/web/federate.go index fde1942bb2..babc97e55d 100644 --- a/web/federate.go +++ b/web/federate.go @@ -17,6 +17,7 @@ import ( "fmt" "net/http" "sort" + "strings" "github.com/go-kit/log/level" "github.com/gogo/protobuf/proto" @@ -169,10 +170,10 @@ Loop: return } - slices.SortFunc(vec, func(a, b promql.Sample) bool { + slices.SortFunc(vec, func(a, b promql.Sample) int { ni := a.Metric.Get(labels.MetricName) nj := b.Metric.Get(labels.MetricName) - return ni < nj + return strings.Compare(ni, nj) }) externalLabels := h.config.GlobalConfig.ExternalLabels.Map() From 5d233df7ef392ff0883ee7c962a0087b3de116cb Mon Sep 17 00:00:00 2001 From: ouyang1204 Date: Mon, 25 Sep 2023 15:48:05 +0800 Subject: [PATCH 06/55] Fix rule check broken (#12715) Signed-off-by: DrAuYueng --- cmd/promtool/main.go | 72 +++++++++++++++--------- cmd/promtool/main_test.go | 85 +++++++++++++++++++++++++++++ cmd/promtool/testdata/rules-bad.yml | 28 ++++++++++ 3 files changed, 160 insertions(+), 25 deletions(-) create mode 100644 cmd/promtool/testdata/rules-bad.yml diff --git a/cmd/promtool/main.go b/cmd/promtool/main.go index d539ce08f9..4ff48ce25c 100644 --- a/cmd/promtool/main.go +++ b/cmd/promtool/main.go @@ -733,30 +733,7 @@ func CheckRules(ls lintConfig, files ...string) int { failed := false hasErrors := false if len(files) == 0 { - fmt.Println("Checking standard input") - data, err := io.ReadAll(os.Stdin) - if err != nil { - fmt.Fprintln(os.Stderr, " FAILED:", err) - return failureExitCode - } - rgs, errs := rulefmt.Parse(data) - for _, e := range errs { - fmt.Fprintln(os.Stderr, e.Error()) - return failureExitCode - } - if n, errs := checkRuleGroups(rgs, ls); errs != nil { - fmt.Fprintln(os.Stderr, " FAILED:") - for _, e := range errs { - fmt.Fprintln(os.Stderr, e.Error()) - } - failed = true - for _, err := range errs { - hasErrors = hasErrors || !errors.Is(err, lintError) - } - } else { - fmt.Printf(" SUCCESS: %d rules found\n", n) - } - fmt.Println() + failed, hasErrors = checkRulesFromStdin(ls) } else { failed, hasErrors = checkRules(files, ls) } @@ -771,6 +748,44 @@ func CheckRules(ls lintConfig, files ...string) int { return successExitCode } +// checkRulesFromStdin validates rule from stdin. +func checkRulesFromStdin(ls lintConfig) (bool, bool) { + failed := false + hasErrors := false + fmt.Println("Checking standard input") + data, err := io.ReadAll(os.Stdin) + if err != nil { + fmt.Fprintln(os.Stderr, " FAILED:", err) + return true, true + } + rgs, errs := rulefmt.Parse(data) + if errs != nil { + failed = true + fmt.Fprintln(os.Stderr, " FAILED:") + for _, e := range errs { + fmt.Fprintln(os.Stderr, e.Error()) + hasErrors = hasErrors || !errors.Is(e, lintError) + } + if hasErrors { + return failed, hasErrors + } + } + if n, errs := checkRuleGroups(rgs, ls); errs != nil { + fmt.Fprintln(os.Stderr, " FAILED:") + for _, e := range errs { + fmt.Fprintln(os.Stderr, e.Error()) + } + failed = true + for _, err := range errs { + hasErrors = hasErrors || !errors.Is(err, lintError) + } + } else { + fmt.Printf(" SUCCESS: %d rules found\n", n) + } + fmt.Println() + return failed, hasErrors +} + // checkRules validates rule files. func checkRules(files []string, ls lintConfig) (bool, bool) { failed := false @@ -780,7 +795,14 @@ func checkRules(files []string, ls lintConfig) (bool, bool) { rgs, errs := rulefmt.ParseFile(f) if errs != nil { failed = true - continue + fmt.Fprintln(os.Stderr, " FAILED:") + for _, e := range errs { + fmt.Fprintln(os.Stderr, e.Error()) + hasErrors = hasErrors || !errors.Is(e, lintError) + } + if hasErrors { + continue + } } if n, errs := checkRuleGroups(rgs, ls); errs != nil { fmt.Fprintln(os.Stderr, " FAILED:") diff --git a/cmd/promtool/main_test.go b/cmd/promtool/main_test.go index 6cfa48798e..5ba08bdc18 100644 --- a/cmd/promtool/main_test.go +++ b/cmd/promtool/main_test.go @@ -464,3 +464,88 @@ func TestDocumentation(t *testing.T) { require.Equal(t, string(expectedContent), generatedContent, "Generated content does not match documentation. Hint: run `make cli-documentation`.") } + +func TestCheckRules(t *testing.T) { + t.Run("rules-good", func(t *testing.T) { + data, err := os.ReadFile("./testdata/rules.yml") + require.NoError(t, err) + r, w, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + + _, err = w.Write(data) + if err != nil { + t.Error(err) + } + w.Close() + + // Restore stdin right after the test. + defer func(v *os.File) { os.Stdin = v }(os.Stdin) + os.Stdin = r + + exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, false)) + require.Equal(t, successExitCode, exitCode, "") + }) + + t.Run("rules-bad", func(t *testing.T) { + data, err := os.ReadFile("./testdata/rules-bad.yml") + require.NoError(t, err) + r, w, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + + _, err = w.Write(data) + if err != nil { + t.Error(err) + } + w.Close() + + // Restore stdin right after the test. + defer func(v *os.File) { os.Stdin = v }(os.Stdin) + os.Stdin = r + + exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, false)) + require.Equal(t, failureExitCode, exitCode, "") + }) + + t.Run("rules-lint-fatal", func(t *testing.T) { + data, err := os.ReadFile("./testdata/prometheus-rules.lint.yml") + require.NoError(t, err) + r, w, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + + _, err = w.Write(data) + if err != nil { + t.Error(err) + } + w.Close() + + // Restore stdin right after the test. + defer func(v *os.File) { os.Stdin = v }(os.Stdin) + os.Stdin = r + + exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, true)) + require.Equal(t, lintErrExitCode, exitCode, "") + }) +} + +func TestCheckRulesWithRuleFiles(t *testing.T) { + t.Run("rules-good", func(t *testing.T) { + exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, false), "./testdata/rules.yml") + require.Equal(t, successExitCode, exitCode, "") + }) + + t.Run("rules-bad", func(t *testing.T) { + exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, false), "./testdata/rules-bad.yml") + require.Equal(t, failureExitCode, exitCode, "") + }) + + t.Run("rules-lint-fatal", func(t *testing.T) { + exitCode := CheckRules(newLintConfig(lintOptionDuplicateRules, true), "./testdata/prometheus-rules.lint.yml") + require.Equal(t, lintErrExitCode, exitCode, "") + }) +} diff --git a/cmd/promtool/testdata/rules-bad.yml b/cmd/promtool/testdata/rules-bad.yml new file mode 100644 index 0000000000..9548a3a67b --- /dev/null +++ b/cmd/promtool/testdata/rules-bad.yml @@ -0,0 +1,28 @@ +# This is the rules file. + +groups: + - name: alerts + rules: + - alert: InstanceDown + expr: up == 0 + for: 5m + labels: + severity: page + annotations: + summary: "Instance {{ $label.foo }} down" + description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes." + - alert: AlwaysFiring + expr: 1 + + - name: rules + rules: + - record: job:test:count_over_time1m + expr: sum without(instance) (count_over_time(test[1m])) + + # A recording rule that doesn't depend on input series. + - record: fixed_data + expr: 1 + + # Subquery with default resolution test. + - record: suquery_interval_test + expr: count_over_time(up[5m:]) From a15e884e7a925a3af5cbef7129ecb97a642b89c1 Mon Sep 17 00:00:00 2001 From: Alan Protasio Date: Mon, 25 Sep 2023 12:15:41 -0700 Subject: [PATCH 07/55] Prevent Prometheus from overallocating memory on subquery with large amount of steps. (#12734) * change initial points slice size Signed-off-by: Alan Protasio * refactor on the steps calculation and moving the getXPoint/putXPoint method to the evaluator Signed-off-by: Alan Protasio * prevent potential panic Signed-off-by: Alan Protasio * Update promql/engine.go Co-authored-by: Bartlomiej Plotka Signed-off-by: Alan Protasio * Update promql/engine.go Co-authored-by: Bartlomiej Plotka Signed-off-by: Alan Protasio * Update promql/engine.go Co-authored-by: Bartlomiej Plotka Signed-off-by: Alan Protasio * Update promql/engine.go Co-authored-by: Bartlomiej Plotka Signed-off-by: Alan Protasio * Allocating slice with maximum size of 5k Signed-off-by: Alan Protasio * adding comments Signed-off-by: Alan Protasio --------- Signed-off-by: Alan Protasio Co-authored-by: Bartlomiej Plotka --- promql/engine.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/promql/engine.go b/promql/engine.go index 4a894fe72d..161aa85acb 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -60,6 +60,11 @@ const ( maxInt64 = 9223372036854774784 // The smallest SampleValue that can be converted to an int64 without underflow. minInt64 = -9223372036854775808 + + // Max initial size for the pooled points slices. + // The getHPointSlice and getFPointSlice functions are called with an estimated size which often can be + // over-estimated. + maxPointsSliceSize = 5000 ) type engineMetrics struct { @@ -1910,19 +1915,33 @@ func getFPointSlice(sz int) []FPoint { if p := fPointPool.Get(); p != nil { return p } + + if sz > maxPointsSliceSize { + sz = maxPointsSliceSize + } + return make([]FPoint, 0, sz) } +// putFPointSlice will return a FPoint slice of size max(maxPointsSliceSize, sz). +// This function is called with an estimated size which often can be over-estimated. func putFPointSlice(p []FPoint) { if p != nil { fPointPool.Put(p[:0]) } } +// getHPointSlice will return a HPoint slice of size max(maxPointsSliceSize, sz). +// This function is called with an estimated size which often can be over-estimated. func getHPointSlice(sz int) []HPoint { if p := hPointPool.Get(); p != nil { return p } + + if sz > maxPointsSliceSize { + sz = maxPointsSliceSize + } + return make([]HPoint, 0, sz) } From 6dcbd653e9a62304db603d2aaa7a0d317231ca7b Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 25 Sep 2023 13:57:08 -0700 Subject: [PATCH 08/55] tsdb: register metrics after Head is initialized (#12876) This avoids situations where metrics are scraped before the data they are trying to look at is initialized. Signed-off-by: Bryan Boreham --- tsdb/head.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsdb/head.go b/tsdb/head.go index f66a686e60..ea71b27181 100644 --- a/tsdb/head.go +++ b/tsdb/head.go @@ -258,7 +258,6 @@ func NewHead(r prometheus.Registerer, l log.Logger, wal, wbl *wlog.WL, opts *Hea if err := h.resetInMemoryState(); err != nil { return nil, err } - h.metrics = newHeadMetrics(h, r) if opts.ChunkPool == nil { opts.ChunkPool = chunkenc.NewPool() @@ -278,6 +277,7 @@ func NewHead(r prometheus.Registerer, l log.Logger, wal, wbl *wlog.WL, opts *Hea if err != nil { return nil, err } + h.metrics = newHeadMetrics(h, r) return h, nil } From 1aad4004c32b117979532345a49ef83f3f99a872 Mon Sep 17 00:00:00 2001 From: Linas Medziunas Date: Wed, 27 Sep 2023 09:34:43 +0300 Subject: [PATCH 09/55] Additional test case for ValidateHistogram Signed-off-by: Linas Medziunas --- tsdb/head_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tsdb/head_test.go b/tsdb/head_test.go index 3d271e93bb..a9179af62c 100644 --- a/tsdb/head_test.go +++ b/tsdb/head_test.go @@ -4836,6 +4836,16 @@ func TestHistogramValidation(t *testing.T) { "valid histogram": { h: tsdbutil.GenerateTestHistograms(1)[0], }, + "valid histogram that has its Count (4) higher than the actual total of buckets (2 + 1)": { + // This case is possible if NaN values (which do not fall into any bucket) are observed. + h: &histogram.Histogram{ + ZeroCount: 2, + Count: 4, + Sum: math.NaN(), + PositiveSpans: []histogram.Span{{Offset: 0, Length: 1}}, + PositiveBuckets: []int64{1}, + }, + }, "rejects histogram that has too few negative buckets": { h: &histogram.Histogram{ NegativeSpans: []histogram.Span{{Offset: 0, Length: 1}}, From 67dcca500505452ab8a3e4547198c996bcf050da Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Wed, 27 Sep 2023 23:34:18 +0200 Subject: [PATCH 10/55] ci(lint): enable errorlint linter on cmd Signed-off-by: Matthieu MOREL --- .github/workflows/ci.yml | 1 + .golangci.yml | 22 ++++++++++++++++++++++ cmd/prometheus/main_test.go | 7 +++---- cmd/promtool/main_test.go | 7 +++---- cmd/promtool/unittest.go | 2 +- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab12876674..768efe195c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -142,6 +142,7 @@ jobs: - name: Install Go uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 with: + cache: false go-version: 1.20.x - name: Install snmp_exporter/generator dependencies run: sudo apt-get update && sudo apt-get -y install libsnmp-dev diff --git a/.golangci.yml b/.golangci.yml index 5aa01e48aa..57c6895b95 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -13,6 +13,7 @@ output: linters: enable: - depguard + - errorlint - gocritic - gofumpt - goimports @@ -31,6 +32,27 @@ issues: - path: _test.go linters: - errcheck + - path: discovery/ + linters: + - errorlint + - path: model/ + linters: + - errorlint + - path: scrape/ + linters: + - errorlint + - path: storage/ + linters: + - errorlint + - path: tsdb/ + linters: + - errorlint + - path: util/ + linters: + - errorlint + - path: web/ + linters: + - errorlint linters-settings: depguard: diff --git a/cmd/prometheus/main_test.go b/cmd/prometheus/main_test.go index 21447d0369..e4f831939f 100644 --- a/cmd/prometheus/main_test.go +++ b/cmd/prometheus/main_test.go @@ -498,10 +498,9 @@ func TestDocumentation(t *testing.T) { cmd.Stdout = &stdout if err := cmd.Run(); err != nil { - if exitError, ok := err.(*exec.ExitError); ok { - if exitError.ExitCode() != 0 { - fmt.Println("Command failed with non-zero exit code") - } + var exitError *exec.ExitError + if errors.As(err, &exitError) && exitError.ExitCode() != 0 { + fmt.Println("Command failed with non-zero exit code") } } diff --git a/cmd/promtool/main_test.go b/cmd/promtool/main_test.go index 5ba08bdc18..09c91f92a5 100644 --- a/cmd/promtool/main_test.go +++ b/cmd/promtool/main_test.go @@ -450,10 +450,9 @@ func TestDocumentation(t *testing.T) { cmd.Stdout = &stdout if err := cmd.Run(); err != nil { - if exitError, ok := err.(*exec.ExitError); ok { - if exitError.ExitCode() != 0 { - fmt.Println("Command failed with non-zero exit code") - } + var exitError *exec.ExitError + if errors.As(err, &exitError) && exitError.ExitCode() != 0 { + fmt.Println("Command failed with non-zero exit code") } } diff --git a/cmd/promtool/unittest.go b/cmd/promtool/unittest.go index 575480b032..5bec5c60b0 100644 --- a/cmd/promtool/unittest.go +++ b/cmd/promtool/unittest.go @@ -241,7 +241,7 @@ func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]i g.Eval(suite.Context(), ts) for _, r := range g.Rules() { if r.LastError() != nil { - evalErrs = append(evalErrs, fmt.Errorf(" rule: %s, time: %s, err: %v", + evalErrs = append(evalErrs, fmt.Errorf(" rule: %s, time: %s, err: %w", r.Name(), ts.Sub(time.Unix(0, 0).UTC()), r.LastError())) } } From f15f0ac16a295b448e65c17e742375f702fd3aba Mon Sep 17 00:00:00 2001 From: lasea75 Date: Thu, 28 Sep 2023 12:26:46 -0500 Subject: [PATCH 11/55] Update functions.md Signed-off-by: lasea75 --- docs/querying/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/querying/functions.md b/docs/querying/functions.md index 6b3a77e973..68036d882f 100644 --- a/docs/querying/functions.md +++ b/docs/querying/functions.md @@ -14,7 +14,7 @@ vector, which if not provided it will default to the value of the expression _Notes about the experimental native histograms:_ * Ingesting native histograms has to be enabled via a [feature - flag](../../feature_flags.md#native-histograms). As long as no native histograms + flag](https://prometheus.io/docs/prometheus/latest/feature_flags/). As long as no native histograms have been ingested into the TSDB, all functions will behave as usual. * Functions that do not explicitly mention native histograms in their documentation (see below) will ignore histogram samples. From 5d68ebb2076f2776e5c553b56f92b57e99a8fe61 Mon Sep 17 00:00:00 2001 From: johncming Date: Sat, 21 Mar 2020 21:34:00 +0800 Subject: [PATCH 12/55] pkg/rulefmt: fix bug of validate. Signed-off-by: johncming --- model/rulefmt/rulefmt.go | 18 +- .../record_and_alert.both_set.bad.yaml | 6 + .../record_and_alert.both_unset.bad.yaml | 4 + pkg/rulefmt/rulefmt_test.go | 175 ++++++++++++++++++ 4 files changed, 191 insertions(+), 12 deletions(-) create mode 100644 model/rulefmt/testdata/record_and_alert.both_set.bad.yaml create mode 100644 model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml create mode 100644 pkg/rulefmt/rulefmt_test.go diff --git a/model/rulefmt/rulefmt.go b/model/rulefmt/rulefmt.go index 30b3face0d..6be93f6428 100644 --- a/model/rulefmt/rulefmt.go +++ b/model/rulefmt/rulefmt.go @@ -173,17 +173,11 @@ func (r *RuleNode) Validate() (nodes []WrappedError) { }) } if r.Record.Value == "" && r.Alert.Value == "" { - if r.Record.Value == "0" { - nodes = append(nodes, WrappedError{ - err: fmt.Errorf("one of 'record' or 'alert' must be set"), - node: &r.Alert, - }) - } else { - nodes = append(nodes, WrappedError{ - err: fmt.Errorf("one of 'record' or 'alert' must be set"), - node: &r.Record, - }) - } + nodes = append(nodes, WrappedError{ + err: fmt.Errorf("one of 'record' or 'alert' must be set"), + node: &r.Record, + nodeAlt: &r.Alert, + }) } if r.Expr.Value == "" { @@ -250,7 +244,7 @@ func (r *RuleNode) Validate() (nodes []WrappedError) { nodes = append(nodes, WrappedError{err: err}) } - return + return nodes } // testTemplateParsing checks if the templates used in labels and annotations diff --git a/model/rulefmt/testdata/record_and_alert.both_set.bad.yaml b/model/rulefmt/testdata/record_and_alert.both_set.bad.yaml new file mode 100644 index 0000000000..0ba81b7423 --- /dev/null +++ b/model/rulefmt/testdata/record_and_alert.both_set.bad.yaml @@ -0,0 +1,6 @@ +groups: +- name: yolo + rules: + - record: Hi + alert: Hello + expr: 1 diff --git a/model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml b/model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml new file mode 100644 index 0000000000..64d2e8f20d --- /dev/null +++ b/model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml @@ -0,0 +1,4 @@ +groups: + - name: yolo + rules: + - expr: 1 diff --git a/pkg/rulefmt/rulefmt_test.go b/pkg/rulefmt/rulefmt_test.go new file mode 100644 index 0000000000..58b5d5ad36 --- /dev/null +++ b/pkg/rulefmt/rulefmt_test.go @@ -0,0 +1,175 @@ +// Copyright 2017 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rulefmt + +import ( + "path/filepath" + "strings" + "testing" + + "github.com/prometheus/prometheus/util/testutil" +) + +func TestParseFileSuccess(t *testing.T) { + if _, errs := ParseFile("testdata/test.yaml"); len(errs) > 0 { + t.Errorf("unexpected errors parsing file") + for _, err := range errs { + t.Error(err) + } + } +} + +func TestParseFileFailure(t *testing.T) { + table := []struct { + filename string + errMsg string + }{ + { + filename: "duplicate_grp.bad.yaml", + errMsg: "groupname: \"yolo\" is repeated in the same file", + }, + { + filename: "bad_expr.bad.yaml", + errMsg: "parse error", + }, + { + filename: "record_and_alert.both_set.bad.yaml", + errMsg: "'alert' and 'record' cannot be set at the same time", + }, + { + filename: "record_and_alert.both_unset.bad.yaml", + errMsg: "one of 'record' or 'alert' must be set", + }, + { + filename: "no_rec_alert.bad.yaml", + errMsg: "one of 'record' or 'alert' must be set", + }, + { + filename: "noexpr.bad.yaml", + errMsg: "field 'expr' must be set in rule", + }, + { + filename: "bad_lname.bad.yaml", + errMsg: "invalid label name", + }, + { + filename: "bad_annotation.bad.yaml", + errMsg: "invalid annotation name", + }, + { + filename: "invalid_record_name.bad.yaml", + errMsg: "invalid recording rule name", + }, + { + filename: "bad_field.bad.yaml", + errMsg: "field annotation not found", + }, + { + filename: "invalid_label_name.bad.yaml", + errMsg: "invalid label name", + }, + } + + for _, c := range table { + _, errs := ParseFile(filepath.Join("testdata", c.filename)) + if errs == nil { + t.Errorf("Expected error parsing %s but got none", c.filename) + continue + } + if !strings.Contains(errs[0].Error(), c.errMsg) { + t.Errorf("Expected error for %s to contain %q but got: %s", c.filename, c.errMsg, errs) + } + } + +} + +func TestTemplateParsing(t *testing.T) { + tests := []struct { + ruleString string + shouldPass bool + }{ + { + ruleString: ` +groups: +- name: example + rules: + - alert: InstanceDown + expr: up == 0 + for: 5m + labels: + severity: "page" + annotations: + summary: "Instance {{ $labels.instance }} down" +`, + shouldPass: true, + }, + { + // `$label` instead of `$labels`. + ruleString: ` +groups: +- name: example + rules: + - alert: InstanceDown + expr: up == 0 + for: 5m + labels: + severity: "page" + annotations: + summary: "Instance {{ $label.instance }} down" +`, + shouldPass: false, + }, + { + // `$this_is_wrong`. + ruleString: ` +groups: +- name: example + rules: + - alert: InstanceDown + expr: up == 0 + for: 5m + labels: + severity: "{{$this_is_wrong}}" + annotations: + summary: "Instance {{ $labels.instance }} down" +`, + shouldPass: false, + }, + { + // `$labels.quantile * 100`. + ruleString: ` +groups: +- name: example + rules: + - alert: InstanceDown + expr: up == 0 + for: 5m + labels: + severity: "page" + annotations: + summary: "Instance {{ $labels.instance }} down" + description: "{{$labels.quantile * 100}}" +`, + shouldPass: false, + }, + } + + for _, tst := range tests { + rgs, errs := Parse([]byte(tst.ruleString)) + testutil.Assert(t, rgs != nil, "Rule parsing, rule=\n"+tst.ruleString) + passed := (tst.shouldPass && len(errs) == 0) || (!tst.shouldPass && len(errs) > 0) + testutil.Assert(t, passed, "Rule validation failed, rule=\n"+tst.ruleString) + } + +} From c52db2b196238e376dba6d580d95373ba794a226 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 10:38:10 +0200 Subject: [PATCH 13/55] Remove duplicate tests Signed-off-by: Julien Pivotto --- model/rulefmt/rulefmt.go | 2 +- .../record_and_alert.both_set.bad.yaml | 6 - .../record_and_alert.both_unset.bad.yaml | 4 - pkg/rulefmt/rulefmt_test.go | 175 ------------------ 4 files changed, 1 insertion(+), 186 deletions(-) delete mode 100644 model/rulefmt/testdata/record_and_alert.both_set.bad.yaml delete mode 100644 model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml delete mode 100644 pkg/rulefmt/rulefmt_test.go diff --git a/model/rulefmt/rulefmt.go b/model/rulefmt/rulefmt.go index 6be93f6428..03cbd8849c 100644 --- a/model/rulefmt/rulefmt.go +++ b/model/rulefmt/rulefmt.go @@ -244,7 +244,7 @@ func (r *RuleNode) Validate() (nodes []WrappedError) { nodes = append(nodes, WrappedError{err: err}) } - return nodes + return } // testTemplateParsing checks if the templates used in labels and annotations diff --git a/model/rulefmt/testdata/record_and_alert.both_set.bad.yaml b/model/rulefmt/testdata/record_and_alert.both_set.bad.yaml deleted file mode 100644 index 0ba81b7423..0000000000 --- a/model/rulefmt/testdata/record_and_alert.both_set.bad.yaml +++ /dev/null @@ -1,6 +0,0 @@ -groups: -- name: yolo - rules: - - record: Hi - alert: Hello - expr: 1 diff --git a/model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml b/model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml deleted file mode 100644 index 64d2e8f20d..0000000000 --- a/model/rulefmt/testdata/record_and_alert.both_unset.bad.yaml +++ /dev/null @@ -1,4 +0,0 @@ -groups: - - name: yolo - rules: - - expr: 1 diff --git a/pkg/rulefmt/rulefmt_test.go b/pkg/rulefmt/rulefmt_test.go deleted file mode 100644 index 58b5d5ad36..0000000000 --- a/pkg/rulefmt/rulefmt_test.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package rulefmt - -import ( - "path/filepath" - "strings" - "testing" - - "github.com/prometheus/prometheus/util/testutil" -) - -func TestParseFileSuccess(t *testing.T) { - if _, errs := ParseFile("testdata/test.yaml"); len(errs) > 0 { - t.Errorf("unexpected errors parsing file") - for _, err := range errs { - t.Error(err) - } - } -} - -func TestParseFileFailure(t *testing.T) { - table := []struct { - filename string - errMsg string - }{ - { - filename: "duplicate_grp.bad.yaml", - errMsg: "groupname: \"yolo\" is repeated in the same file", - }, - { - filename: "bad_expr.bad.yaml", - errMsg: "parse error", - }, - { - filename: "record_and_alert.both_set.bad.yaml", - errMsg: "'alert' and 'record' cannot be set at the same time", - }, - { - filename: "record_and_alert.both_unset.bad.yaml", - errMsg: "one of 'record' or 'alert' must be set", - }, - { - filename: "no_rec_alert.bad.yaml", - errMsg: "one of 'record' or 'alert' must be set", - }, - { - filename: "noexpr.bad.yaml", - errMsg: "field 'expr' must be set in rule", - }, - { - filename: "bad_lname.bad.yaml", - errMsg: "invalid label name", - }, - { - filename: "bad_annotation.bad.yaml", - errMsg: "invalid annotation name", - }, - { - filename: "invalid_record_name.bad.yaml", - errMsg: "invalid recording rule name", - }, - { - filename: "bad_field.bad.yaml", - errMsg: "field annotation not found", - }, - { - filename: "invalid_label_name.bad.yaml", - errMsg: "invalid label name", - }, - } - - for _, c := range table { - _, errs := ParseFile(filepath.Join("testdata", c.filename)) - if errs == nil { - t.Errorf("Expected error parsing %s but got none", c.filename) - continue - } - if !strings.Contains(errs[0].Error(), c.errMsg) { - t.Errorf("Expected error for %s to contain %q but got: %s", c.filename, c.errMsg, errs) - } - } - -} - -func TestTemplateParsing(t *testing.T) { - tests := []struct { - ruleString string - shouldPass bool - }{ - { - ruleString: ` -groups: -- name: example - rules: - - alert: InstanceDown - expr: up == 0 - for: 5m - labels: - severity: "page" - annotations: - summary: "Instance {{ $labels.instance }} down" -`, - shouldPass: true, - }, - { - // `$label` instead of `$labels`. - ruleString: ` -groups: -- name: example - rules: - - alert: InstanceDown - expr: up == 0 - for: 5m - labels: - severity: "page" - annotations: - summary: "Instance {{ $label.instance }} down" -`, - shouldPass: false, - }, - { - // `$this_is_wrong`. - ruleString: ` -groups: -- name: example - rules: - - alert: InstanceDown - expr: up == 0 - for: 5m - labels: - severity: "{{$this_is_wrong}}" - annotations: - summary: "Instance {{ $labels.instance }} down" -`, - shouldPass: false, - }, - { - // `$labels.quantile * 100`. - ruleString: ` -groups: -- name: example - rules: - - alert: InstanceDown - expr: up == 0 - for: 5m - labels: - severity: "page" - annotations: - summary: "Instance {{ $labels.instance }} down" - description: "{{$labels.quantile * 100}}" -`, - shouldPass: false, - }, - } - - for _, tst := range tests { - rgs, errs := Parse([]byte(tst.ruleString)) - testutil.Assert(t, rgs != nil, "Rule parsing, rule=\n"+tst.ruleString) - passed := (tst.shouldPass && len(errs) == 0) || (!tst.shouldPass && len(errs) > 0) - testutil.Assert(t, passed, "Rule validation failed, rule=\n"+tst.ruleString) - } - -} From a1c1fc8244364114e6f21d08a94c17a31bad9044 Mon Sep 17 00:00:00 2001 From: Gabriela Gutierrez Date: Fri, 23 Sep 2022 15:42:20 -0300 Subject: [PATCH 14/55] Create scorecards.yml Signed-off-by: Gabriela Gutierrez --- .github/workflows/scorecards.yml | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/scorecards.yml diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml new file mode 100644 index 0000000000..fb7acf66af --- /dev/null +++ b/.github/workflows/scorecards.yml @@ -0,0 +1,51 @@ +name: Scorecards supply-chain security +on: + # Only the default branch is supported. + branch_protection_rule: + schedule: + - cron: '25 18 * * 5' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecards analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Used to receive a badge. + id-token: write + + steps: + - name: "Checkout code" + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # tag=v3.0.0 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@865b4092859256271290c77adbd10a43f4779972 # tag=v2.0.3 + with: + results_file: results.sarif + results_format: sarif + # Publish the results for public repositories to enable scorecard badges. For more details, see + # https://github.com/ossf/scorecard-action#publishing-results. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # tag=v3.0.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # tag=v1.0.26 + with: + sarif_file: results.sarif From 9a628bb1c8511fc166ac102f25209b1931e1a1b6 Mon Sep 17 00:00:00 2001 From: Gabriela Gutierrez Date: Fri, 23 Sep 2022 17:07:46 -0300 Subject: [PATCH 15/55] Add OpenSSF Scorecard badge to README.md Signed-off-by: Gabriela Gutierrez --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8b89bb01e5..5fa6cc49e5 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ examples and guides.

[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/486/badge)](https://bestpractices.coreinfrastructure.org/projects/486) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/prometheus/prometheus) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/prometheus.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:prometheus) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/prometheus/prometheus/badge)](https://api.securityscorecards.dev/projects/github.com/prometheus/prometheus) From 17caa505b1b6caff26b17d11ddbfb90c6763a54a Mon Sep 17 00:00:00 2001 From: Gabriela Gutierrez Date: Fri, 23 Sep 2022 17:28:30 -0300 Subject: [PATCH 16/55] Add Google copyright notice Signed-off-by: Gabriela Gutierrez --- .github/workflows/scorecards.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index fb7acf66af..66ef760e8b 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -1,3 +1,5 @@ +# Copyright 2022 Google LLC + name: Scorecards supply-chain security on: # Only the default branch is supported. From 6237aba7c4d79c793530bf119078f60cd96fec97 Mon Sep 17 00:00:00 2001 From: Gabriela Gutierrez Date: Fri, 23 Sep 2022 17:49:51 -0300 Subject: [PATCH 17/55] Fix trailing spaces Signed-off-by: Gabriela Gutierrez --- .github/workflows/scorecards.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 66ef760e8b..ef784e1fbe 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -21,7 +21,7 @@ jobs: security-events: write # Used to receive a badge. id-token: write - + steps: - name: "Checkout code" uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # tag=v3.0.0 @@ -34,7 +34,7 @@ jobs: results_file: results.sarif results_format: sarif # Publish the results for public repositories to enable scorecard badges. For more details, see - # https://github.com/ossf/scorecard-action#publishing-results. + # https://github.com/ossf/scorecard-action#publishing-results. publish_results: true # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF @@ -45,7 +45,7 @@ jobs: name: SARIF file path: results.sarif retention-days: 5 - + # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # tag=v1.0.26 From 19b4cb2f48d585c8d6371f1e5f9579035eac978c Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 13:20:32 +0200 Subject: [PATCH 18/55] OpenSSF: Run on main and PR's Signed-off-by: Julien Pivotto --- .github/workflows/scorecards.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index ef784e1fbe..716555e8a9 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -2,10 +2,7 @@ name: Scorecards supply-chain security on: - # Only the default branch is supported. - branch_protection_rule: - schedule: - - cron: '25 18 * * 5' + pull_request: push: branches: [ "main" ] @@ -29,13 +26,13 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@865b4092859256271290c77adbd10a43f4779972 # tag=v2.0.3 + uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # tag=v2.2.0 with: results_file: results.sarif results_format: sarif # Publish the results for public repositories to enable scorecard badges. For more details, see # https://github.com/ossf/scorecard-action#publishing-results. - publish_results: true + publish_results: ${{ github.event_name != 'pull_request' }} # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. From b6fbda0c8a1f62688a26b87ba899d5e1b0587660 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 13:47:06 +0200 Subject: [PATCH 19/55] UI: Update Webpack (GHSA-hc6q-2mpp-qw7j) Signed-off-by: Julien Pivotto --- web/ui/package-lock.json | 528 +++++++++++++++++++-------------------- 1 file changed, 258 insertions(+), 270 deletions(-) diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 04c1a3eddc..a9e9e3d165 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -3464,9 +3464,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", @@ -3474,9 +3474,9 @@ } }, "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", @@ -3494,13 +3494,13 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@leichtgewicht/ip-codec": { @@ -4899,148 +4899,148 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -5116,9 +5116,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -5150,9 +5150,9 @@ } }, "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, "peerDependencies": { "acorn": "^8" @@ -7647,9 +7647,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -7802,9 +7802,9 @@ "dev": true }, "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, "node_modules/es-shim-unscopables": { @@ -18146,9 +18146,9 @@ } }, "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -18236,9 +18236,9 @@ "dev": true }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, "dependencies": { "randombytes": "^2.1.0" @@ -19194,13 +19194,13 @@ } }, "node_modules/terser": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", - "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", + "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -19212,16 +19212,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "engines": { "node": ">= 10.13.0" @@ -19886,22 +19886,22 @@ } }, "node_modules/webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", + "acorn-import-assertions": "^1.9.0", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -19910,9 +19910,9 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, @@ -20175,12 +20175,6 @@ "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -23243,9 +23237,9 @@ "dev": true }, "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.0", @@ -23253,9 +23247,9 @@ }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", @@ -23272,13 +23266,13 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@leichtgewicht/ip-codec": { @@ -24450,148 +24444,148 @@ } }, "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", "dev": true }, "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -24650,9 +24644,9 @@ } }, "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true }, "acorn-globals": { @@ -24674,9 +24668,9 @@ } }, "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, "requires": {} }, @@ -26542,9 +26536,9 @@ "dev": true }, "enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -26672,9 +26666,9 @@ "dev": true }, "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, "es-shim-unscopables": { @@ -34379,9 +34373,9 @@ } }, "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "requires": { "@types/json-schema": "^7.0.8", @@ -34457,9 +34451,9 @@ } }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -35207,13 +35201,13 @@ } }, "terser": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", - "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", + "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", "dev": true, "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -35227,16 +35221,16 @@ } }, "terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" } }, "test-exclude": { @@ -35719,22 +35713,22 @@ "dev": true }, "webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", + "acorn-import-assertions": "^1.9.0", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -35743,19 +35737,13 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", From ca12cb8909936fbc2000dd7849672efcca7fa3ff Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 13:47:31 +0200 Subject: [PATCH 20/55] UI: Update tough-cookie (GHSA-72xf-g2v4-qvf3 GHSA-76p3-8jx3-jpfq) Signed-off-by: Julien Pivotto --- web/ui/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index a9e9e3d165..7c60c12087 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -19342,9 +19342,9 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", - "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, "dependencies": { "psl": "^1.1.33", @@ -35309,9 +35309,9 @@ "dev": true }, "tough-cookie": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", - "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, "requires": { "psl": "^1.1.33", From f24dc17fcc0c7943b3edeffa36f8dba77fda0db7 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 13:48:29 +0200 Subject: [PATCH 21/55] UI: Update semver (GHSA-c2qf-rxjj-qqgw) Signed-off-by: Julien Pivotto --- web/ui/package-lock.json | 120 +++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 7c60c12087..64c3febca4 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -4676,9 +4676,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -4821,9 +4821,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -6819,9 +6819,9 @@ } }, "node_modules/css-loader/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -9149,9 +9149,9 @@ } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -11714,9 +11714,9 @@ } }, "node_modules/jest-jasmine2/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -12646,9 +12646,9 @@ "peer": true }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "peer": true, "dependencies": { @@ -14924,9 +14924,9 @@ } }, "node_modules/postcss-loader/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -17358,9 +17358,9 @@ "dev": true }, "node_modules/react-scripts/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -18182,9 +18182,9 @@ } }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -19444,9 +19444,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -24316,9 +24316,9 @@ }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -24391,9 +24391,9 @@ }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -25918,9 +25918,9 @@ }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -27666,9 +27666,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -29623,9 +29623,9 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -30369,9 +30369,9 @@ "peer": true }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "peer": true, "requires": { @@ -32005,9 +32005,9 @@ }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -33790,9 +33790,9 @@ "dev": true }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -34399,9 +34399,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, "send": { @@ -35374,9 +35374,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" From d50c7d3bfc466d144db0666c7d5efa0a17a6be69 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 13:49:10 +0200 Subject: [PATCH 22/55] UI: Update loader-utils (GHSA-hhq3-ff78-jv3g GHSA-3rfm-jhwj-7488) Signed-off-by: Julien Pivotto --- web/ui/package-lock.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 64c3febca4..ab37a977c6 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -13108,9 +13108,9 @@ } }, "node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -16105,9 +16105,9 @@ } }, "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "dev": true, "engines": { "node": ">= 12.13.0" @@ -30743,9 +30743,9 @@ "dev": true }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "requires": { "big.js": "^5.2.2", @@ -32811,9 +32811,9 @@ }, "dependencies": { "loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "dev": true } } From 3d80cb1325f47898ea55abc08390886565531561 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 13:49:55 +0200 Subject: [PATCH 23/55] UI: Update json5 (GHSA-9c47-m6qq-7p4h) Signed-off-by: Julien Pivotto --- web/ui/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index ab37a977c6..18af99c40b 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -19471,9 +19471,9 @@ } }, "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { "minimist": "^1.2.0" @@ -35397,9 +35397,9 @@ }, "dependencies": { "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" From 76ebd621d688a96cfe663b56cc66b58a2d7be666 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 13:54:30 +0200 Subject: [PATCH 24/55] UI: Update word-wrap (GHSA-j8xg-fqg3-53r7) Signed-off-by: Julien Pivotto --- web/ui/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 18af99c40b..eabb75cb1f 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -20299,9 +20299,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -36012,9 +36012,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "workbox-background-sync": { From ac0919d48cd59e6b1d53b72a122c36a895de37d9 Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Fri, 29 Sep 2023 19:10:41 +0200 Subject: [PATCH 25/55] Update docs/querying/functions.md Signed-off-by: Julien Pivotto --- docs/querying/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/querying/functions.md b/docs/querying/functions.md index 68036d882f..6838bb72b6 100644 --- a/docs/querying/functions.md +++ b/docs/querying/functions.md @@ -14,7 +14,7 @@ vector, which if not provided it will default to the value of the expression _Notes about the experimental native histograms:_ * Ingesting native histograms has to be enabled via a [feature - flag](https://prometheus.io/docs/prometheus/latest/feature_flags/). As long as no native histograms + flag](../feature_flags.md#native-histograms). As long as no native histograms have been ingested into the TSDB, all functions will behave as usual. * Functions that do not explicitly mention native histograms in their documentation (see below) will ignore histogram samples. From 0a513f827d31c769736f41d45535176d65c33194 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Fri, 29 Sep 2023 22:50:30 +0200 Subject: [PATCH 26/55] ci(lint): enable errorlint linter on model Signed-off-by: Matthieu MOREL --- .golangci.yml | 3 --- model/textparse/openmetricsparse.go | 6 +++--- model/textparse/promparse.go | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 57c6895b95..6e46812c8f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -35,9 +35,6 @@ issues: - path: discovery/ linters: - errorlint - - path: model/ - linters: - - errorlint - path: scrape/ linters: - errorlint diff --git a/model/textparse/openmetricsparse.go b/model/textparse/openmetricsparse.go index e0833636f1..5623e6833f 100644 --- a/model/textparse/openmetricsparse.go +++ b/model/textparse/openmetricsparse.go @@ -338,7 +338,7 @@ func (p *OpenMetricsParser) Next() (Entry, error) { var ts float64 // A float is enough to hold what we need for millisecond resolution. if ts, err = parseFloat(yoloString(p.l.buf()[1:])); err != nil { - return EntryInvalid, fmt.Errorf("%v while parsing: %q", err, p.l.b[p.start:p.l.i]) + return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) } if math.IsNaN(ts) || math.IsInf(ts, 0) { return EntryInvalid, fmt.Errorf("invalid timestamp %f", ts) @@ -391,7 +391,7 @@ func (p *OpenMetricsParser) parseComment() error { var ts float64 // A float is enough to hold what we need for millisecond resolution. if ts, err = parseFloat(yoloString(p.l.buf()[1:])); err != nil { - return fmt.Errorf("%v while parsing: %q", err, p.l.b[p.start:p.l.i]) + return fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) } if math.IsNaN(ts) || math.IsInf(ts, 0) { return fmt.Errorf("invalid exemplar timestamp %f", ts) @@ -461,7 +461,7 @@ func (p *OpenMetricsParser) getFloatValue(t token, after string) (float64, error } val, err := parseFloat(yoloString(p.l.buf()[1:])) if err != nil { - return 0, fmt.Errorf("%v while parsing: %q", err, p.l.b[p.start:p.l.i]) + return 0, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) } // Ensure canonical NaN value. if math.IsNaN(p.exemplarVal) { diff --git a/model/textparse/promparse.go b/model/textparse/promparse.go index 94338a6660..04c295dd00 100644 --- a/model/textparse/promparse.go +++ b/model/textparse/promparse.go @@ -348,7 +348,7 @@ func (p *PromParser) Next() (Entry, error) { return EntryInvalid, p.parseError("expected value after metric", t2) } if p.val, err = parseFloat(yoloString(p.l.buf())); err != nil { - return EntryInvalid, fmt.Errorf("%v while parsing: %q", err, p.l.b[p.start:p.l.i]) + return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) } // Ensure canonical NaN value. if math.IsNaN(p.val) { @@ -361,7 +361,7 @@ func (p *PromParser) Next() (Entry, error) { case tTimestamp: p.hasTS = true if p.ts, err = strconv.ParseInt(yoloString(p.l.buf()), 10, 64); err != nil { - return EntryInvalid, fmt.Errorf("%v while parsing: %q", err, p.l.b[p.start:p.l.i]) + return EntryInvalid, fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) } if t2 := p.nextToken(); t2 != tLinebreak { return EntryInvalid, p.parseError("expected next entry after timestamp", t2) From 5027863c40d318ae68894c0908aacb2a476ac338 Mon Sep 17 00:00:00 2001 From: Jennifer Villa Date: Sat, 30 Sep 2023 10:23:54 -0400 Subject: [PATCH 27/55] Clarify what happens when a rule group takes too long to execute Namely, call out that all subsequent evaluations will be skipped until the initial evaluation completes. Signed-off-by: Jennifer Villa --- docs/configuration/recording_rules.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/configuration/recording_rules.md b/docs/configuration/recording_rules.md index eda0214b35..6ccde040d8 100644 --- a/docs/configuration/recording_rules.md +++ b/docs/configuration/recording_rules.md @@ -147,3 +147,7 @@ by the rule are discarded, and if it's an alerting rule, _all_ alerts for the rule, active, pending, or inactive, are cleared as well. The event will be recorded as an error in the evaluation, and as such no stale markers are written. + +# Failed rule evaluations due to slow evaluation + +If a rule group hasn't finished evaluating before the next evaluation is supposed to start, the next evaluation will be skipped. Subsequent evaluations of the rule group will continue to be skipped until the initial evaluation either completes or times out. When this happens, there will be a gap in the recording rule metric. The `rule_group_iterations_missed_total` metric will be incremented for each missed iteration. From 601e5b902844f9fb02c422ec516dee642277c6a0 Mon Sep 17 00:00:00 2001 From: Jennifer Villa Date: Sat, 30 Sep 2023 10:26:29 -0400 Subject: [PATCH 28/55] Update recording_rules.md specified the evaluation interval defines when the next evaluation should start. Signed-off-by: Jennifer Villa --- docs/configuration/recording_rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/recording_rules.md b/docs/configuration/recording_rules.md index 6ccde040d8..0c8aef6377 100644 --- a/docs/configuration/recording_rules.md +++ b/docs/configuration/recording_rules.md @@ -150,4 +150,4 @@ written. # Failed rule evaluations due to slow evaluation -If a rule group hasn't finished evaluating before the next evaluation is supposed to start, the next evaluation will be skipped. Subsequent evaluations of the rule group will continue to be skipped until the initial evaluation either completes or times out. When this happens, there will be a gap in the recording rule metric. The `rule_group_iterations_missed_total` metric will be incremented for each missed iteration. +If a rule group hasn't finished evaluating before its next evaluation is supposed to start (as defined by the `evaluation_interval`), the next evaluation will be skipped. Subsequent evaluations of the rule group will continue to be skipped until the initial evaluation either completes or times out. When this happens, there will be a gap in the recording rule metric. The `rule_group_iterations_missed_total` metric will be incremented for each missed iteration. From 216cf6046ea61194d691be31443ed26de7f6968a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:43:34 +0000 Subject: [PATCH 29/55] build(deps): bump actions/checkout from 4.0.0 to 4.1.0 in /scripts Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/3df4ab11eba7bda6032a0b82a6bb43b11571feac...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- scripts/golangci-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/golangci-lint.yml b/scripts/golangci-lint.yml index 8ace97bde1..15cf547be1 100644 --- a/scripts/golangci-lint.yml +++ b/scripts/golangci-lint.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: install Go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: From 5d8f0e0582abb03624c1fd3a0bde0d04a8d360a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:48:39 +0000 Subject: [PATCH 30/55] build(deps): bump github.com/hashicorp/consul/api from 1.22.0 to 1.25.1 Bumps [github.com/hashicorp/consul/api](https://github.com/hashicorp/consul) from 1.22.0 to 1.25.1. - [Release notes](https://github.com/hashicorp/consul/releases) - [Changelog](https://github.com/hashicorp/consul/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/consul/compare/api/v1.22.0...api/v1.25.1) --- updated-dependencies: - dependency-name: github.com/hashicorp/consul/api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 1cdca0f989..3fb42ceaa6 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/gophercloud/gophercloud v1.5.0 github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/hashicorp/consul/api v1.22.0 + github.com/hashicorp/consul/api v1.25.1 github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e github.com/hetznercloud/hcloud-go/v2 v2.0.0 github.com/ionos-cloud/sdk-go/v6 v6.1.8 diff --git a/go.sum b/go.sum index bdf4f59477..2f837a09de 100644 --- a/go.sum +++ b/go.sum @@ -403,10 +403,10 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.22.0 h1:ydEvDooB/A0c/xpsBd8GSt7P2/zYPBui4KrNip0xGjE= -github.com/hashicorp/consul/api v1.22.0/go.mod h1:zHpYgZ7TeYqS6zaszjwSt128OwESRpnhU9aGa6ue3Eg= +github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE= +github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.14.0 h1:Hly+BMNMssVzoWddbBnBFi3W+Fzytvm0haSkihhj3GU= +github.com/hashicorp/consul/sdk v0.14.1 h1:ZiwE2bKb+zro68sWzZ1SgHF3kRMBZ94TwOCFRF4ylPs= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= From 754fcc265e47700fe4788e21bbe19c77bb5ef000 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:53:21 +0000 Subject: [PATCH 31/55] build(deps): bump github.com/prometheus/client_golang Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.16.0 to 1.17.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.16.0...v1.17.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- documentation/examples/remote_storage/go.mod | 10 ++++----- documentation/examples/remote_storage/go.sum | 22 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/documentation/examples/remote_storage/go.mod b/documentation/examples/remote_storage/go.mod index b4c8e077d6..1800dfef25 100644 --- a/documentation/examples/remote_storage/go.mod +++ b/documentation/examples/remote_storage/go.mod @@ -8,7 +8,7 @@ require ( github.com/gogo/protobuf v1.3.2 github.com/golang/snappy v0.0.4 github.com/influxdata/influxdb v1.11.2 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 github.com/prometheus/common v0.44.0 github.com/prometheus/prometheus v0.45.0 github.com/stretchr/testify v1.8.4 @@ -42,9 +42,9 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect @@ -56,11 +56,11 @@ require ( golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.8.0 // indirect + golang.org/x/sys v0.11.0 // indirect golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/documentation/examples/remote_storage/go.sum b/documentation/examples/remote_storage/go.sum index 2ade3a1b7c..e0070d9663 100644 --- a/documentation/examples/remote_storage/go.sum +++ b/documentation/examples/remote_storage/go.sum @@ -194,13 +194,13 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= @@ -213,8 +213,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/prometheus/prometheus v0.45.0 h1:O/uG+Nw4kNxx/jDPxmjsSDd+9Ohql6E7ZSY1x5x/0KI= github.com/prometheus/prometheus v0.45.0/go.mod h1:jC5hyO8ItJBnDWGecbEucMyXjzxGv9cxsxsjS9u5s1w= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -292,7 +292,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -312,8 +312,8 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -352,8 +352,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 4ba8430299cae194f7579d1adb5bb724f90cbce4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:57:36 +0000 Subject: [PATCH 32/55] build(deps): bump actions/upload-artifact from 3.0.0 to 3.1.3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.0.0 to 3.1.3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...a8a3f3ad30e3422c9c7b888a15615d19a852ae32) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 716555e8a9..84f732ee66 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -37,7 +37,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # tag=v3.0.0 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3.1.3 with: name: SARIF file path: results.sarif From de7e057d3c8f21d31bd98fd1499ccb2d392fe9e9 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Mon, 2 Oct 2023 12:16:37 +0200 Subject: [PATCH 33/55] tsdb: Tighten up sub-benchmark scope in BenchmarkQuerier (#12718) Signed-off-by: Arve Knudsen --- tsdb/querier_bench_test.go | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/tsdb/querier_bench_test.go b/tsdb/querier_bench_test.go index 206b41fde8..e2e281db8b 100644 --- a/tsdb/querier_bench_test.go +++ b/tsdb/querier_bench_test.go @@ -31,10 +31,9 @@ const ( ) func BenchmarkQuerier(b *testing.B) { - chunkDir := b.TempDir() opts := DefaultHeadOptions() opts.ChunkRange = 1000 - opts.ChunkDirRoot = chunkDir + opts.ChunkDirRoot = b.TempDir() h, err := NewHead(nil, nil, nil, nil, opts, nil) require.NoError(b, err) defer func() { @@ -58,9 +57,13 @@ func BenchmarkQuerier(b *testing.B) { } require.NoError(b, app.Commit()) - ir, err := h.Index() - require.NoError(b, err) b.Run("Head", func(b *testing.B) { + ir, err := h.Index() + require.NoError(b, err) + defer func() { + require.NoError(b, ir.Close()) + }() + b.Run("PostingsForMatchers", func(b *testing.B) { benchmarkPostingsForMatchers(b, ir) }) @@ -69,18 +72,20 @@ func BenchmarkQuerier(b *testing.B) { }) }) - tmpdir := b.TempDir() - - blockdir := createBlockFromHead(b, tmpdir, h) - block, err := OpenBlock(nil, blockdir, nil) - require.NoError(b, err) - defer func() { - require.NoError(b, block.Close()) - }() - ir, err = block.Index() - require.NoError(b, err) - defer ir.Close() b.Run("Block", func(b *testing.B) { + blockdir := createBlockFromHead(b, b.TempDir(), h) + block, err := OpenBlock(nil, blockdir, nil) + require.NoError(b, err) + defer func() { + require.NoError(b, block.Close()) + }() + + ir, err := block.Index() + require.NoError(b, err) + defer func() { + require.NoError(b, ir.Close()) + }() + b.Run("PostingsForMatchers", func(b *testing.B) { benchmarkPostingsForMatchers(b, ir) }) @@ -239,10 +244,9 @@ func BenchmarkMergedStringIter(b *testing.B) { } func BenchmarkQuerierSelect(b *testing.B) { - chunkDir := b.TempDir() opts := DefaultHeadOptions() opts.ChunkRange = 1000 - opts.ChunkDirRoot = chunkDir + opts.ChunkDirRoot = b.TempDir() h, err := NewHead(nil, nil, nil, nil, opts, nil) require.NoError(b, err) defer h.Close() From 1492031ef2e04e94bf1d50a7d46eb881aa2b0c0a Mon Sep 17 00:00:00 2001 From: Oleg Zaytsev Date: Mon, 2 Oct 2023 16:24:25 +0200 Subject: [PATCH 34/55] Optimize ListPostings Next() (#12906) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Next() call of ListPostings() was updating two values, while we can just update the position. This is up to 30% faster for high number of Postings. goos: linux goarch: amd64 pkg: github.com/prometheus/prometheus/tsdb/index cpu: 11th Gen Intel(R) Core(TM) i7-11700K @ 3.60GHz │ old │ new │ │ sec/op │ sec/op vs base │ ListPostings/count=100-16 819.2n ± 0% 732.6n ± 0% -10.58% (p=0.000 n=20) ListPostings/count=1000-16 2.685µ ± 1% 2.017µ ± 0% -24.88% (p=0.000 n=20) ListPostings/count=10000-16 21.43µ ± 1% 14.81µ ± 0% -30.91% (p=0.000 n=20) ListPostings/count=100000-16 209.4µ ± 1% 143.3µ ± 0% -31.55% (p=0.000 n=20) ListPostings/count=1000000-16 2.086m ± 1% 1.436m ± 1% -31.18% (p=0.000 n=20) geomean 29.02µ 21.41µ -26.22% We're talking about microseconds here, but they just keep adding. Signed-off-by: Oleg Zaytsev --- tsdb/index/postings.go | 35 ++++----- tsdb/index/postings_test.go | 144 ++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 20 deletions(-) diff --git a/tsdb/index/postings.go b/tsdb/index/postings.go index e5fa5fc540..5f24dbfe1a 100644 --- a/tsdb/index/postings.go +++ b/tsdb/index/postings.go @@ -747,7 +747,7 @@ func (rp *removedPostings) Err() error { // ListPostings implements the Postings interface over a plain list. type ListPostings struct { list []storage.SeriesRef - cur storage.SeriesRef + pos int } func NewListPostings(list []storage.SeriesRef) Postings { @@ -759,39 +759,34 @@ func newListPostings(list ...storage.SeriesRef) *ListPostings { } func (it *ListPostings) At() storage.SeriesRef { - return it.cur + return it.list[it.pos-1] } func (it *ListPostings) Next() bool { - if len(it.list) > 0 { - it.cur = it.list[0] - it.list = it.list[1:] + if it.pos < len(it.list) { + it.pos++ return true } - it.cur = 0 return false } func (it *ListPostings) Seek(x storage.SeriesRef) bool { - // If the current value satisfies, then return. - if it.cur >= x { - return true + if it.pos == 0 { + it.pos++ } - if len(it.list) == 0 { + if it.pos > len(it.list) { return false } + // If the current value satisfies, then return. + if it.list[it.pos-1] >= x { + return true + } // Do binary search between current position and end. - i := sort.Search(len(it.list), func(i int) bool { - return it.list[i] >= x - }) - if i < len(it.list) { - it.cur = it.list[i] - it.list = it.list[i+1:] - return true - } - it.list = nil - return false + it.pos = sort.Search(len(it.list[it.pos-1:]), func(i int) bool { + return it.list[i+it.pos-1] >= x + }) + it.pos + return it.pos-1 < len(it.list) } func (it *ListPostings) Err() error { diff --git a/tsdb/index/postings_test.go b/tsdb/index/postings_test.go index b2ed1064d2..f0f3bb75a8 100644 --- a/tsdb/index/postings_test.go +++ b/tsdb/index/postings_test.go @@ -1118,3 +1118,147 @@ func TestPostingsWithIndexHeap(t *testing.T) { require.Equal(t, storage.SeriesRef(25), node.p.At()) }) } + +func TestListPostings(t *testing.T) { + t.Run("empty list", func(t *testing.T) { + p := NewListPostings(nil) + require.False(t, p.Next()) + require.False(t, p.Seek(10)) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + + t.Run("one posting", func(t *testing.T) { + t.Run("next", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10}) + require.True(t, p.Next()) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + t.Run("seek less", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10}) + require.True(t, p.Seek(5)) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.True(t, p.Seek(5)) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + t.Run("seek equal", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10}) + require.True(t, p.Seek(10)) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + t.Run("seek more", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10}) + require.False(t, p.Seek(15)) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + t.Run("seek after next", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10}) + require.True(t, p.Next()) + require.False(t, p.Seek(15)) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + }) + + t.Run("multiple postings", func(t *testing.T) { + t.Run("next", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10, 20}) + require.True(t, p.Next()) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.True(t, p.Next()) + require.Equal(t, storage.SeriesRef(20), p.At()) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + t.Run("seek", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10, 20}) + require.True(t, p.Seek(5)) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.True(t, p.Seek(5)) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.True(t, p.Seek(10)) + require.Equal(t, storage.SeriesRef(10), p.At()) + require.True(t, p.Next()) + require.Equal(t, storage.SeriesRef(20), p.At()) + require.True(t, p.Seek(10)) + require.Equal(t, storage.SeriesRef(20), p.At()) + require.True(t, p.Seek(20)) + require.Equal(t, storage.SeriesRef(20), p.At()) + require.False(t, p.Next()) + require.NoError(t, p.Err()) + }) + t.Run("seek lest than last", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10, 20, 30, 40, 50}) + require.True(t, p.Seek(45)) + require.Equal(t, storage.SeriesRef(50), p.At()) + require.False(t, p.Next()) + }) + t.Run("seek exactly last", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10, 20, 30, 40, 50}) + require.True(t, p.Seek(50)) + require.Equal(t, storage.SeriesRef(50), p.At()) + require.False(t, p.Next()) + }) + t.Run("seek more than last", func(t *testing.T) { + p := NewListPostings([]storage.SeriesRef{10, 20, 30, 40, 50}) + require.False(t, p.Seek(60)) + require.False(t, p.Next()) + }) + }) + + t.Run("seek", func(t *testing.T) { + for _, c := range []int{2, 8, 9, 10} { + t.Run(fmt.Sprintf("count=%d", c), func(t *testing.T) { + list := make([]storage.SeriesRef, c) + for i := 0; i < c; i++ { + list[i] = storage.SeriesRef(i * 10) + } + + t.Run("all one by one", func(t *testing.T) { + p := NewListPostings(list) + for i := 0; i < c; i++ { + require.True(t, p.Seek(storage.SeriesRef(i*10))) + require.Equal(t, storage.SeriesRef(i*10), p.At()) + } + require.False(t, p.Seek(storage.SeriesRef(c*10))) + }) + + t.Run("each one", func(t *testing.T) { + for _, ref := range list { + p := NewListPostings(list) + require.True(t, p.Seek(ref)) + require.Equal(t, ref, p.At()) + } + }) + }) + } + }) +} + +func BenchmarkListPostings(b *testing.B) { + const maxCount = 1e6 + input := make([]storage.SeriesRef, maxCount) + for i := 0; i < maxCount; i++ { + input[i] = storage.SeriesRef(i << 2) + } + + for _, count := range []int{100, 1e3, 10e3, 100e3, maxCount} { + b.Run(fmt.Sprintf("count=%d", count), func(b *testing.B) { + for i := 0; i < b.N; i++ { + p := NewListPostings(input[:count]) + var sum storage.SeriesRef + for p.Next() { + sum += p.At() + } + require.NotZero(b, sum) + } + }) + } +} From 65ffa0c511f3eef8c813680b7e43740bb8a1705d Mon Sep 17 00:00:00 2001 From: Jennifer Villa Date: Mon, 2 Oct 2023 21:37:29 -0400 Subject: [PATCH 35/55] Update recording_rules.md adding Josh's suggestion Signed-off-by: Jennifer Villa --- docs/configuration/recording_rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/recording_rules.md b/docs/configuration/recording_rules.md index 0c8aef6377..90bd3df730 100644 --- a/docs/configuration/recording_rules.md +++ b/docs/configuration/recording_rules.md @@ -150,4 +150,4 @@ written. # Failed rule evaluations due to slow evaluation -If a rule group hasn't finished evaluating before its next evaluation is supposed to start (as defined by the `evaluation_interval`), the next evaluation will be skipped. Subsequent evaluations of the rule group will continue to be skipped until the initial evaluation either completes or times out. When this happens, there will be a gap in the recording rule metric. The `rule_group_iterations_missed_total` metric will be incremented for each missed iteration. +If a rule group hasn't finished evaluating before its next evaluation is supposed to start (as defined by the `evaluation_interval`), the next evaluation will be skipped. Subsequent evaluations of the rule group will continue to be skipped until the initial evaluation either completes or times out. When this happens, there will be a gap in the recording rule metric. The `rule_group_iterations_missed_total` metric will be incremented for each missed iteration of the rule group. From ea7bec4cc7dd8984d86996e7e711e6884c38425b Mon Sep 17 00:00:00 2001 From: Jennifer Villa Date: Mon, 2 Oct 2023 21:44:54 -0400 Subject: [PATCH 36/55] Update recording_rules.md updated language to be a bit more clear Signed-off-by: Jennifer Villa --- docs/configuration/recording_rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/recording_rules.md b/docs/configuration/recording_rules.md index 90bd3df730..48ab951f94 100644 --- a/docs/configuration/recording_rules.md +++ b/docs/configuration/recording_rules.md @@ -150,4 +150,4 @@ written. # Failed rule evaluations due to slow evaluation -If a rule group hasn't finished evaluating before its next evaluation is supposed to start (as defined by the `evaluation_interval`), the next evaluation will be skipped. Subsequent evaluations of the rule group will continue to be skipped until the initial evaluation either completes or times out. When this happens, there will be a gap in the recording rule metric. The `rule_group_iterations_missed_total` metric will be incremented for each missed iteration of the rule group. +If a rule group hasn't finished evaluating before its next evaluation is supposed to start (as defined by the `evaluation_interval`), the next evaluation will be skipped. Subsequent evaluations of the rule group will continue to be skipped until the initial evaluation either completes or times out. When this happens, there will be a gap in the metric produced by the recording rule. The `rule_group_iterations_missed_total` metric will be incremented for each missed iteration of the rule group. From ec9170b8bf6dd8595c42b57d211f3567aa3bd0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Rabenstein?= Date: Wed, 20 Sep 2023 18:01:21 +0200 Subject: [PATCH 37/55] Merge pull request #12874 from krajorama/outof-order-chunks Fix duplicate sample detection at chunk size limit Signed-off-by: SuperQ --- tsdb/head_append.go | 9 ++++++--- tsdb/head_test.go | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/tsdb/head_append.go b/tsdb/head_append.go index 9016943756..d1f4d3035e 100644 --- a/tsdb/head_append.go +++ b/tsdb/head_append.go @@ -1282,9 +1282,6 @@ func (s *memSeries) appendPreprocessor(t int64, e chunkenc.Encoding, o chunkOpts // There is no head chunk in this series yet, create the first chunk for the sample. c = s.cutNewHeadChunk(t, e, o.chunkRange) chunkCreated = true - } else if len(c.chunk.Bytes()) > maxBytesPerXORChunk { - c = s.cutNewHeadChunk(t, e, o.chunkRange) - chunkCreated = true } // Out of order sample. @@ -1292,6 +1289,12 @@ func (s *memSeries) appendPreprocessor(t int64, e chunkenc.Encoding, o chunkOpts return c, false, chunkCreated } + // Check the chunk size, unless we just created it and if the chunk is too large, cut a new one. + if !chunkCreated && len(c.chunk.Bytes()) > maxBytesPerXORChunk { + c = s.cutNewHeadChunk(t, e, o.chunkRange) + chunkCreated = true + } + if c.chunk.Encoding() != e { // The chunk encoding expected by this append is different than the head chunk's // encoding. So we cut a new chunk with the expected encoding. diff --git a/tsdb/head_test.go b/tsdb/head_test.go index b501f5f3f3..cd9ab65108 100644 --- a/tsdb/head_test.go +++ b/tsdb/head_test.go @@ -5399,3 +5399,49 @@ func TestCuttingNewHeadChunks(t *testing.T) { }) } } + +// TestHeadDetectsDuplcateSampleAtSizeLimit tests a regression where a duplicate sample +// is appended to the head, right when the head chunk is at the size limit. +// The test adds all samples as duplicate, thus expecting that the result has +// exactly half of the samples. +func TestHeadDetectsDuplicateSampleAtSizeLimit(t *testing.T) { + numSamples := 1000 + baseTS := int64(1695209650) + + h, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + defer func() { + require.NoError(t, h.Close()) + }() + + a := h.Appender(context.Background()) + var err error + vals := []float64{math.MaxFloat64, 0x00} // Use the worst case scenario for the XOR encoding. Otherwise we hit the sample limit before the size limit. + for i := 0; i < numSamples; i++ { + ts := baseTS + int64(i/2)*10000 + a.Append(0, labels.FromStrings("foo", "bar"), ts, vals[(i/2)%len(vals)]) + err = a.Commit() + require.NoError(t, err) + a = h.Appender(context.Background()) + } + + indexReader, err := h.Index() + require.NoError(t, err) + + var ( + chunks []chunks.Meta + builder labels.ScratchBuilder + ) + require.NoError(t, indexReader.Series(1, &builder, &chunks)) + + chunkReader, err := h.Chunks() + require.NoError(t, err) + + storedSampleCount := 0 + for _, chunkMeta := range chunks { + chunk, err := chunkReader.Chunk(chunkMeta) + require.NoError(t, err) + storedSampleCount += chunk.NumSamples() + } + + require.Equal(t, numSamples/2, storedSampleCount) +} From 64130d7909e2ce5a2e35f2fbb39eb5bc5e09fc92 Mon Sep 17 00:00:00 2001 From: SuperQ Date: Wed, 4 Oct 2023 09:46:57 +0200 Subject: [PATCH 38/55] Release 2.47.1 * [BUGFIX] Fix duplicate sample detection at chunk size limit #12874 Signed-off-by: SuperQ --- CHANGELOG.md | 4 ++++ VERSION | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a9d4521a1..7ad9c69dc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.47.1 / 2023-10-04 + +* [BUGFIX] Fix duplicate sample detection at chunk size limit #12874 + ## 2.47.0 / 2023-09-06 This release adds an experimental OpenTelemetry (OTLP) Ingestion feature, diff --git a/VERSION b/VERSION index bb13a7e354..24c6ede7ad 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.47.0 +2.47.1 From b43358fd43cda5e19fc138a557b11bcf5bc7e408 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Wed, 4 Oct 2023 10:36:55 +0200 Subject: [PATCH 39/55] API: Add tests for query timeout parameter (#12927) Add unit tests for Web API's query endpoint (GET/POST). Also modify the endpoint handler to use context.WithDeadline instead of context.WithTimeout, so the deadline is deterministic for the tests. Signed-off-by: Arve Knudsen --- web/api/v1/api.go | 2 +- web/api/v1/api_test.go | 106 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 62a376b0ba..1a54f23a61 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -436,7 +436,7 @@ func (api *API) query(r *http.Request) (result apiFuncResult) { return invalidParamError(err, "timeout") } - ctx, cancel = context.WithTimeout(ctx, timeout) + ctx, cancel = context.WithDeadline(ctx, api.now().Add(timeout)) defer cancel() } diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index c86165b780..475b4bab54 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -404,7 +404,7 @@ func TestEndpoints(t *testing.T) { testEndpoints(t, api, testTargetRetriever, storage, true) }) - // Run all the API tests against a API that is wired to forward queries via + // Run all the API tests against an API that is wired to forward queries via // the remote read client to a test server, which in turn sends them to the // data from the test storage. t.Run("remote", func(t *testing.T) { @@ -3660,3 +3660,107 @@ func TestExtractQueryOpts(t *testing.T) { }) } } + +// Test query timeout parameter. +func TestQueryTimeout(t *testing.T) { + storage := promql.LoadedStorage(t, ` + load 1m + test_metric1{foo="bar"} 0+100x100 + `) + t.Cleanup(func() { + _ = storage.Close() + }) + + now := time.Now() + + for _, tc := range []struct { + name string + method string + }{ + { + name: "GET method", + method: http.MethodGet, + }, + { + name: "POST method", + method: http.MethodPost, + }, + } { + t.Run(tc.name, func(t *testing.T) { + engine := &fakeEngine{} + api := &API{ + Queryable: storage, + QueryEngine: engine, + ExemplarQueryable: storage.ExemplarQueryable(), + alertmanagerRetriever: testAlertmanagerRetriever{}.toFactory(), + flagsMap: sampleFlagMap, + now: func() time.Time { return now }, + config: func() config.Config { return samplePrometheusCfg }, + ready: func(f http.HandlerFunc) http.HandlerFunc { return f }, + } + + query := url.Values{ + "query": []string{"2"}, + "timeout": []string{"1s"}, + } + ctx := context.Background() + req, err := http.NewRequest(tc.method, fmt.Sprintf("http://example.com?%s", query.Encode()), nil) + require.NoError(t, err) + req.RemoteAddr = "127.0.0.1:20201" + + res := api.query(req.WithContext(ctx)) + assertAPIError(t, res.err, errorNone) + + require.Len(t, engine.query.execCalls, 1) + deadline, ok := engine.query.execCalls[0].Deadline() + require.True(t, ok) + require.Equal(t, now.Add(time.Second), deadline) + }) + } +} + +// fakeEngine is a fake QueryEngine implementation. +type fakeEngine struct { + query fakeQuery +} + +func (e *fakeEngine) SetQueryLogger(promql.QueryLogger) {} + +func (e *fakeEngine) NewInstantQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, ts time.Time) (promql.Query, error) { + return &e.query, nil +} + +func (e *fakeEngine) NewRangeQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, start, end time.Time, interval time.Duration) (promql.Query, error) { + return &e.query, nil +} + +// fakeQuery is a fake Query implementation. +type fakeQuery struct { + query string + execCalls []context.Context +} + +func (q *fakeQuery) Exec(ctx context.Context) *promql.Result { + q.execCalls = append(q.execCalls, ctx) + return &promql.Result{ + Value: &parser.StringLiteral{ + Val: "test", + }, + } +} + +func (q *fakeQuery) Close() {} + +func (q *fakeQuery) Statement() parser.Statement { + return nil +} + +func (q *fakeQuery) Stats() *stats.Statistics { + return nil +} + +func (q *fakeQuery) Cancel() {} + +func (q *fakeQuery) String() string { + return q.query +} From feaa93da7796e3e8dd3e35ef96808a253982f296 Mon Sep 17 00:00:00 2001 From: Jeanette Tan Date: Wed, 4 Oct 2023 18:53:55 +0800 Subject: [PATCH 40/55] Add warning when monotonicity is forced in the input to histogram_quantile Signed-off-by: Jeanette Tan --- promql/functions.go | 6 +++++- promql/quantile.go | 32 +++++++++++++++++++------------- util/annotations/annotations.go | 18 ++++++++++++++---- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/promql/functions.go b/promql/functions.go index b1245f5a13..2a1a0b0300 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -1168,10 +1168,14 @@ func funcHistogramQuantile(vals []parser.Value, args parser.Expressions, enh *Ev for _, mb := range enh.signatureToMetricWithBuckets { if len(mb.buckets) > 0 { + res, forcedMonotonicity := bucketQuantile(q, mb.buckets) enh.Out = append(enh.Out, Sample{ Metric: mb.metric, - F: bucketQuantile(q, mb.buckets), + F: res, }) + if forcedMonotonicity { + annos.Add(annotations.NewHistogramQuantileForcedMonotonicityWarning(mb.metric.Get(labels.MetricName), args[1].PositionRange())) + } } } diff --git a/promql/quantile.go b/promql/quantile.go index 06a02a8d42..1ebc39aa28 100644 --- a/promql/quantile.go +++ b/promql/quantile.go @@ -71,15 +71,17 @@ type metricWithBuckets struct { // If q<0, -Inf is returned. // // If q>1, +Inf is returned. -func bucketQuantile(q float64, buckets buckets) float64 { +// +// We also return a bool to indicate if monotonicity needed to be forced. +func bucketQuantile(q float64, buckets buckets) (float64, bool) { if math.IsNaN(q) { - return math.NaN() + return math.NaN(), false } if q < 0 { - return math.Inf(-1) + return math.Inf(-1), false } if q > 1 { - return math.Inf(+1) + return math.Inf(+1), false } slices.SortFunc(buckets, func(a, b bucket) int { // We don't expect the bucket boundary to be a NaN. @@ -92,27 +94,27 @@ func bucketQuantile(q float64, buckets buckets) float64 { return 0 }) if !math.IsInf(buckets[len(buckets)-1].upperBound, +1) { - return math.NaN() + return math.NaN(), false } buckets = coalesceBuckets(buckets) - ensureMonotonic(buckets) + forcedMonotonic := ensureMonotonic(buckets) if len(buckets) < 2 { - return math.NaN() + return math.NaN(), false } observations := buckets[len(buckets)-1].count if observations == 0 { - return math.NaN() + return math.NaN(), false } rank := q * observations b := sort.Search(len(buckets)-1, func(i int) bool { return buckets[i].count >= rank }) if b == len(buckets)-1 { - return buckets[len(buckets)-2].upperBound + return buckets[len(buckets)-2].upperBound, forcedMonotonic } if b == 0 && buckets[0].upperBound <= 0 { - return buckets[0].upperBound + return buckets[0].upperBound, forcedMonotonic } var ( bucketStart float64 @@ -124,7 +126,7 @@ func bucketQuantile(q float64, buckets buckets) float64 { count -= buckets[b-1].count rank -= buckets[b-1].count } - return bucketStart + (bucketEnd-bucketStart)*(rank/count) + return bucketStart + (bucketEnd-bucketStart)*(rank/count), forcedMonotonic } // histogramQuantile calculates the quantile 'q' based on the given histogram. @@ -370,9 +372,11 @@ func coalesceBuckets(buckets buckets) buckets { // // As a somewhat hacky solution until ingestion is atomic per scrape, we // calculate the "envelope" of the histogram buckets, essentially removing -// any decreases in the count between successive buckets. +// any decreases in the count between successive buckets. We return a bool +// to indicate if this monotonicity was forced or not. -func ensureMonotonic(buckets buckets) { +func ensureMonotonic(buckets buckets) bool { + forced := false max := buckets[0].count for i := 1; i < len(buckets); i++ { switch { @@ -380,8 +384,10 @@ func ensureMonotonic(buckets buckets) { max = buckets[i].count case buckets[i].count < max: buckets[i].count = max + forced = true } } + return forced } // quantile calculates the given quantile of a vector of samples. diff --git a/util/annotations/annotations.go b/util/annotations/annotations.go index e8b59dc7f6..bff0100d91 100644 --- a/util/annotations/annotations.go +++ b/util/annotations/annotations.go @@ -100,10 +100,11 @@ var ( PromQLInfo = errors.New("PromQL info") PromQLWarning = errors.New("PromQL warning") - InvalidQuantileWarning = fmt.Errorf("%w: quantile value should be between 0 and 1", PromQLWarning) - BadBucketLabelWarning = fmt.Errorf("%w: bucket label %q is missing or has a malformed value", PromQLWarning, model.BucketLabel) - MixedFloatsHistogramsWarning = fmt.Errorf("%w: encountered a mix of histograms and floats for metric name", PromQLWarning) - MixedClassicNativeHistogramsWarning = fmt.Errorf("%w: vector contains a mix of classic and native histograms for metric name", PromQLWarning) + InvalidQuantileWarning = fmt.Errorf("%w: quantile value should be between 0 and 1", PromQLWarning) + BadBucketLabelWarning = fmt.Errorf("%w: bucket label %q is missing or has a malformed value", PromQLWarning, model.BucketLabel) + MixedFloatsHistogramsWarning = fmt.Errorf("%w: encountered a mix of histograms and floats for metric name", PromQLWarning) + MixedClassicNativeHistogramsWarning = fmt.Errorf("%w: vector contains a mix of classic and native histograms for metric name", PromQLWarning) + HistogramQuantileForcedMonotonicityWarning = fmt.Errorf("%w: input to histogram_quantile needed to be fixed for monotonicity (and may give inaccurate results) for metric name", PromQLWarning) PossibleNonCounterInfo = fmt.Errorf("%w: metric might not be a counter, name does not end in _total/_sum/_count:", PromQLInfo) ) @@ -155,6 +156,15 @@ func NewMixedClassicNativeHistogramsWarning(metricName string, pos posrange.Posi } } +// NewHistogramQuantileForcedMonotonicityWarning is used when the input (classic histograms) to +// histogram_quantile needs to be forced to be monotonic. +func NewHistogramQuantileForcedMonotonicityWarning(metricName string, pos posrange.PositionRange) annoErr { + return annoErr{ + PositionRange: pos, + Err: fmt.Errorf("%w %q", HistogramQuantileForcedMonotonicityWarning, metricName), + } +} + // NewPossibleNonCounterInfo is used when a counter metric does not have the suffixes // _total, _sum or _count. func NewPossibleNonCounterInfo(metricName string, pos posrange.PositionRange) annoErr { From cdad64002a41aadbb821ce39e1b396cf5154dd7e Mon Sep 17 00:00:00 2001 From: rakshith210 <56937390+rakshith210@users.noreply.github.com> Date: Wed, 4 Oct 2023 19:16:36 -0700 Subject: [PATCH 41/55] Added Azure OAuth support (#12572) * Added Azure OAuth support Signed-off-by: rakshith210 * Added missing comment Signed-off-by: rakshith210 * Addressing comment Signed-off-by: rakshith210 * Fixed lint issue Signed-off-by: rakshith210 * Fix test Signed-off-by: rakshith210 * Addressing comments Signed-off-by: rakshith210 * Added documentation and updated unit tests Signed-off-by: rakshith210 * Addressing comments Signed-off-by: rakshith210 --------- Signed-off-by: rakshith210 --- docs/configuration/configuration.md | 8 +- storage/remote/azuread/azuread.go | 116 +++++- storage/remote/azuread/azuread_test.go | 333 ++++++++++-------- ...ng.yaml => azuread_bad_configmissing.yaml} | 0 .../azuread_bad_invalidoauthconfig.yaml | 4 + .../testdata/azuread_bad_twoconfig.yaml | 7 + ...yaml => azuread_good_managedidentity.yaml} | 0 .../azuread/testdata/azuread_good_oauth.yaml | 5 + 8 files changed, 318 insertions(+), 155 deletions(-) rename storage/remote/azuread/testdata/{azuread_bad_clientidmissing.yaml => azuread_bad_configmissing.yaml} (100%) create mode 100644 storage/remote/azuread/testdata/azuread_bad_invalidoauthconfig.yaml create mode 100644 storage/remote/azuread/testdata/azuread_bad_twoconfig.yaml rename storage/remote/azuread/testdata/{azuread_good.yaml => azuread_good_managedidentity.yaml} (100%) create mode 100644 storage/remote/azuread/testdata/azuread_good_oauth.yaml diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index c9e9415490..b55bb7d721 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -3537,7 +3537,13 @@ azuread: # Azure User-assigned Managed identity. [ managed_identity: - [ client_id: ] + [ client_id: ] ] + + # Azure OAuth. + [ oauth: + [ client_id: ] + [ client_secret: ] + [ tenant_id: ] ] # Configures the remote write request's TLS settings. tls_config: diff --git a/storage/remote/azuread/azuread.go b/storage/remote/azuread/azuread.go index 94b6144da1..cb4587b02a 100644 --- a/storage/remote/azuread/azuread.go +++ b/storage/remote/azuread/azuread.go @@ -22,7 +22,10 @@ import ( "sync" "time" + "github.com/grafana/regexp" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/google/uuid" @@ -46,11 +49,26 @@ type ManagedIdentityConfig struct { ClientID string `yaml:"client_id,omitempty"` } +// OAuthConfig is used to store azure oauth config values. +type OAuthConfig struct { + // ClientID is the clientId of the azure active directory application that is being used to authenticate. + ClientID string `yaml:"client_id,omitempty"` + + // ClientSecret is the clientSecret of the azure active directory application that is being used to authenticate. + ClientSecret string `yaml:"client_secret,omitempty"` + + // TenantID is the tenantId of the azure active directory application that is being used to authenticate. + TenantID string `yaml:"tenant_id,omitempty"` +} + // AzureADConfig is used to store the config values. type AzureADConfig struct { // nolint:revive // ManagedIdentity is the managed identity that is being used to authenticate. ManagedIdentity *ManagedIdentityConfig `yaml:"managed_identity,omitempty"` + // OAuth is the oauth config that is being used to authenticate. + OAuth *OAuthConfig `yaml:"oauth,omitempty"` + // Cloud is the Azure cloud in which the service is running. Example: AzurePublic/AzureGovernment/AzureChina. Cloud string `yaml:"cloud,omitempty"` } @@ -84,18 +102,47 @@ func (c *AzureADConfig) Validate() error { return fmt.Errorf("must provide a cloud in the Azure AD config") } - if c.ManagedIdentity == nil { - return fmt.Errorf("must provide an Azure Managed Identity in the Azure AD config") + if c.ManagedIdentity == nil && c.OAuth == nil { + return fmt.Errorf("must provide an Azure Managed Identity or Azure OAuth in the Azure AD config") } - if c.ManagedIdentity.ClientID == "" { - return fmt.Errorf("must provide an Azure Managed Identity client_id in the Azure AD config") + if c.ManagedIdentity != nil && c.OAuth != nil { + return fmt.Errorf("cannot provide both Azure Managed Identity and Azure OAuth in the Azure AD config") } - _, err := uuid.Parse(c.ManagedIdentity.ClientID) - if err != nil { - return fmt.Errorf("the provided Azure Managed Identity client_id provided is invalid") + if c.ManagedIdentity != nil { + if c.ManagedIdentity.ClientID == "" { + return fmt.Errorf("must provide an Azure Managed Identity client_id in the Azure AD config") + } + + _, err := uuid.Parse(c.ManagedIdentity.ClientID) + if err != nil { + return fmt.Errorf("the provided Azure Managed Identity client_id is invalid") + } } + + if c.OAuth != nil { + if c.OAuth.ClientID == "" { + return fmt.Errorf("must provide an Azure OAuth client_id in the Azure AD config") + } + if c.OAuth.ClientSecret == "" { + return fmt.Errorf("must provide an Azure OAuth client_secret in the Azure AD config") + } + if c.OAuth.TenantID == "" { + return fmt.Errorf("must provide an Azure OAuth tenant_id in the Azure AD config") + } + + var err error + _, err = uuid.Parse(c.OAuth.ClientID) + if err != nil { + return fmt.Errorf("the provided Azure OAuth client_id is invalid") + } + _, err = regexp.MatchString("^[0-9a-zA-Z-.]+$", c.OAuth.TenantID) + if err != nil { + return fmt.Errorf("the provided Azure OAuth tenant_id is invalid") + } + } + return nil } @@ -146,21 +193,54 @@ func (rt *azureADRoundTripper) RoundTrip(req *http.Request) (*http.Response, err // newTokenCredential returns a TokenCredential of different kinds like Azure Managed Identity and Azure AD application. func newTokenCredential(cfg *AzureADConfig) (azcore.TokenCredential, error) { - cred, err := newManagedIdentityTokenCredential(cfg.ManagedIdentity.ClientID) + var cred azcore.TokenCredential + var err error + cloudConfiguration, err := getCloudConfiguration(cfg.Cloud) if err != nil { return nil, err } + clientOpts := &azcore.ClientOptions{ + Cloud: cloudConfiguration, + } + + if cfg.ManagedIdentity != nil { + managedIdentityConfig := &ManagedIdentityConfig{ + ClientID: cfg.ManagedIdentity.ClientID, + } + cred, err = newManagedIdentityTokenCredential(clientOpts, managedIdentityConfig) + if err != nil { + return nil, err + } + } + + if cfg.OAuth != nil { + oAuthConfig := &OAuthConfig{ + ClientID: cfg.OAuth.ClientID, + ClientSecret: cfg.OAuth.ClientSecret, + TenantID: cfg.OAuth.TenantID, + } + cred, err = newOAuthTokenCredential(clientOpts, oAuthConfig) + if err != nil { + return nil, err + } + } return cred, nil } // newManagedIdentityTokenCredential returns new Managed Identity token credential. -func newManagedIdentityTokenCredential(managedIdentityClientID string) (azcore.TokenCredential, error) { - clientID := azidentity.ClientID(managedIdentityClientID) - opts := &azidentity.ManagedIdentityCredentialOptions{ID: clientID} +func newManagedIdentityTokenCredential(clientOpts *azcore.ClientOptions, managedIdentityConfig *ManagedIdentityConfig) (azcore.TokenCredential, error) { + clientID := azidentity.ClientID(managedIdentityConfig.ClientID) + opts := &azidentity.ManagedIdentityCredentialOptions{ClientOptions: *clientOpts, ID: clientID} return azidentity.NewManagedIdentityCredential(opts) } +// newOAuthTokenCredential returns new OAuth token credential +func newOAuthTokenCredential(clientOpts *azcore.ClientOptions, oAuthConfig *OAuthConfig) (azcore.TokenCredential, error) { + opts := &azidentity.ClientSecretCredentialOptions{ClientOptions: *clientOpts} + return azidentity.NewClientSecretCredential(oAuthConfig.TenantID, oAuthConfig.ClientID, oAuthConfig.ClientSecret, opts) +} + // newTokenProvider helps to fetch accessToken for different types of credential. This also takes care of // refreshing the accessToken before expiry. This accessToken is attached to the Authorization header while making requests. func newTokenProvider(cfg *AzureADConfig, cred azcore.TokenCredential) (*tokenProvider, error) { @@ -245,3 +325,17 @@ func getAudience(cloud string) (string, error) { return "", errors.New("Cloud is not specified or is incorrect: " + cloud) } } + +// getCloudConfiguration returns the cloud Configuration which contains AAD endpoint for different clouds +func getCloudConfiguration(c string) (cloud.Configuration, error) { + switch strings.ToLower(c) { + case strings.ToLower(AzureChina): + return cloud.AzureChina, nil + case strings.ToLower(AzureGovernment): + return cloud.AzureGovernment, nil + case strings.ToLower(AzurePublic): + return cloud.AzurePublic, nil + default: + return cloud.Configuration{}, errors.New("Cloud is not specified or is incorrect: " + c) + } +} diff --git a/storage/remote/azuread/azuread_test.go b/storage/remote/azuread/azuread_test.go index ebbd98958c..1143b71da7 100644 --- a/storage/remote/azuread/azuread_test.go +++ b/storage/remote/azuread/azuread_test.go @@ -26,17 +26,20 @@ import ( "github.com/google/uuid" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" "gopkg.in/yaml.v2" ) const ( - dummyAudience = "dummyAudience" - dummyClientID = "00000000-0000-0000-0000-000000000000" - testTokenString = "testTokenString" + dummyAudience = "dummyAudience" + dummyClientID = "00000000-0000-0000-0000-000000000000" + dummyClientSecret = "Cl1ent$ecret!" + dummyTenantID = "00000000-a12b-3cd4-e56f-000000000000" + testTokenString = "testTokenString" ) -var testTokenExpiry = time.Now().Add(10 * time.Second) +var testTokenExpiry = time.Now().Add(5 * time.Second) type AzureAdTestSuite struct { suite.Suite @@ -62,47 +65,64 @@ func TestAzureAd(t *testing.T) { } func (ad *AzureAdTestSuite) TestAzureAdRoundTripper() { - var gotReq *http.Request - - testToken := &azcore.AccessToken{ - Token: testTokenString, - ExpiresOn: testTokenExpiry, + cases := []struct { + cfg *AzureADConfig + }{ + // AzureAd roundtripper with Managedidentity. + { + cfg: &AzureADConfig{ + Cloud: "AzurePublic", + ManagedIdentity: &ManagedIdentityConfig{ + ClientID: dummyClientID, + }, + }, + }, + // AzureAd roundtripper with OAuth. + { + cfg: &AzureADConfig{ + Cloud: "AzurePublic", + OAuth: &OAuthConfig{ + ClientID: dummyClientID, + ClientSecret: dummyClientSecret, + TenantID: dummyTenantID, + }, + }, + }, } + for _, c := range cases { + var gotReq *http.Request - managedIdentityConfig := &ManagedIdentityConfig{ - ClientID: dummyClientID, + testToken := &azcore.AccessToken{ + Token: testTokenString, + ExpiresOn: testTokenExpiry, + } + + ad.mockCredential.On("GetToken", mock.Anything, mock.Anything).Return(*testToken, nil) + + tokenProvider, err := newTokenProvider(c.cfg, ad.mockCredential) + ad.Assert().NoError(err) + + rt := &azureADRoundTripper{ + next: promhttp.RoundTripperFunc(func(req *http.Request) (*http.Response, error) { + gotReq = req + return &http.Response{StatusCode: http.StatusOK}, nil + }), + tokenProvider: tokenProvider, + } + + cli := &http.Client{Transport: rt} + + req, err := http.NewRequest(http.MethodPost, "https://example.com", strings.NewReader("Hello, world!")) + ad.Assert().NoError(err) + + _, err = cli.Do(req) + ad.Assert().NoError(err) + ad.Assert().NotNil(gotReq) + + origReq := gotReq + ad.Assert().NotEmpty(origReq.Header.Get("Authorization")) + ad.Assert().Equal("Bearer "+testTokenString, origReq.Header.Get("Authorization")) } - - azureAdConfig := &AzureADConfig{ - Cloud: "AzurePublic", - ManagedIdentity: managedIdentityConfig, - } - - ad.mockCredential.On("GetToken", mock.Anything, mock.Anything).Return(*testToken, nil) - - tokenProvider, err := newTokenProvider(azureAdConfig, ad.mockCredential) - ad.Assert().NoError(err) - - rt := &azureADRoundTripper{ - next: promhttp.RoundTripperFunc(func(req *http.Request) (*http.Response, error) { - gotReq = req - return &http.Response{StatusCode: http.StatusOK}, nil - }), - tokenProvider: tokenProvider, - } - - cli := &http.Client{Transport: rt} - - req, err := http.NewRequest(http.MethodPost, "https://example.com", strings.NewReader("Hello, world!")) - ad.Assert().NoError(err) - - _, err = cli.Do(req) - ad.Assert().NoError(err) - ad.Assert().NotNil(gotReq) - - origReq := gotReq - ad.Assert().NotEmpty(origReq.Header.Get("Authorization")) - ad.Assert().Equal("Bearer "+testTokenString, origReq.Header.Get("Authorization")) } func loadAzureAdConfig(filename string) (*AzureADConfig, error) { @@ -117,42 +137,54 @@ func loadAzureAdConfig(filename string) (*AzureADConfig, error) { return &cfg, nil } -func testGoodConfig(t *testing.T, filename string) { - _, err := loadAzureAdConfig(filename) - if err != nil { - t.Fatalf("Unexpected error parsing %s: %s", filename, err) +func TestAzureAdConfig(t *testing.T) { + cases := []struct { + filename string + err string + }{ + // Missing managedidentiy or oauth field. + { + filename: "testdata/azuread_bad_configmissing.yaml", + err: "must provide an Azure Managed Identity or Azure OAuth in the Azure AD config", + }, + // Invalid managedidentity client id. + { + filename: "testdata/azuread_bad_invalidclientid.yaml", + err: "the provided Azure Managed Identity client_id is invalid", + }, + // Missing tenant id in oauth config. + { + filename: "testdata/azuread_bad_invalidoauthconfig.yaml", + err: "must provide an Azure OAuth tenant_id in the Azure AD config", + }, + // Invalid config when both managedidentity and oauth is provided. + { + filename: "testdata/azuread_bad_twoconfig.yaml", + err: "cannot provide both Azure Managed Identity and Azure OAuth in the Azure AD config", + }, + // Valid config with missing optionally cloud field. + { + filename: "testdata/azuread_good_cloudmissing.yaml", + }, + // Valid managed identity config. + { + filename: "testdata/azuread_good_managedidentity.yaml", + }, + // Valid Oauth config. + { + filename: "testdata/azuread_good_oauth.yaml", + }, } -} - -func TestGoodAzureAdConfig(t *testing.T) { - filename := "testdata/azuread_good.yaml" - testGoodConfig(t, filename) -} - -func TestGoodCloudMissingAzureAdConfig(t *testing.T) { - filename := "testdata/azuread_good_cloudmissing.yaml" - testGoodConfig(t, filename) -} - -func TestBadClientIdMissingAzureAdConfig(t *testing.T) { - filename := "testdata/azuread_bad_clientidmissing.yaml" - _, err := loadAzureAdConfig(filename) - if err == nil { - t.Fatalf("Did not receive expected error unmarshaling bad azuread config") - } - if !strings.Contains(err.Error(), "must provide an Azure Managed Identity in the Azure AD config") { - t.Errorf("Received unexpected error from unmarshal of %s: %s", filename, err.Error()) - } -} - -func TestBadInvalidClientIdAzureAdConfig(t *testing.T) { - filename := "testdata/azuread_bad_invalidclientid.yaml" - _, err := loadAzureAdConfig(filename) - if err == nil { - t.Fatalf("Did not receive expected error unmarshaling bad azuread config") - } - if !strings.Contains(err.Error(), "the provided Azure Managed Identity client_id provided is invalid") { - t.Errorf("Received unexpected error from unmarshal of %s: %s", filename, err.Error()) + for _, c := range cases { + _, err := loadAzureAdConfig(c.filename) + if c.err != "" { + if err == nil { + t.Fatalf("Did not receive expected error unmarshaling bad azuread config") + } + require.EqualError(t, err, c.err) + } else { + require.NoError(t, err) + } } } @@ -173,75 +205,90 @@ func TestTokenProvider(t *testing.T) { suite.Run(t, new(TokenProviderTestSuite)) } -func (s *TokenProviderTestSuite) TestNewTokenProvider_NilAudience_Fail() { - managedIdentityConfig := &ManagedIdentityConfig{ - ClientID: dummyClientID, +func (s *TokenProviderTestSuite) TestNewTokenProvider() { + cases := []struct { + cfg *AzureADConfig + err string + }{ + // Invalid tokenProvider for managedidentity. + { + cfg: &AzureADConfig{ + Cloud: "PublicAzure", + ManagedIdentity: &ManagedIdentityConfig{ + ClientID: dummyClientID, + }, + }, + err: "Cloud is not specified or is incorrect: ", + }, + // Invalid tokenProvider for oauth. + { + cfg: &AzureADConfig{ + Cloud: "PublicAzure", + OAuth: &OAuthConfig{ + ClientID: dummyClientID, + ClientSecret: dummyClientSecret, + TenantID: dummyTenantID, + }, + }, + err: "Cloud is not specified or is incorrect: ", + }, + // Valid tokenProvider for managedidentity. + { + cfg: &AzureADConfig{ + Cloud: "AzurePublic", + ManagedIdentity: &ManagedIdentityConfig{ + ClientID: dummyClientID, + }, + }, + }, + // Valid tokenProvider for oauth. + { + cfg: &AzureADConfig{ + Cloud: "AzurePublic", + OAuth: &OAuthConfig{ + ClientID: dummyClientID, + ClientSecret: dummyClientSecret, + TenantID: dummyTenantID, + }, + }, + }, } + mockGetTokenCallCounter := 1 + for _, c := range cases { + if c.err != "" { + actualTokenProvider, actualErr := newTokenProvider(c.cfg, s.mockCredential) - azureAdConfig := &AzureADConfig{ - Cloud: "PublicAzure", - ManagedIdentity: managedIdentityConfig, + s.Assert().Nil(actualTokenProvider) + s.Assert().NotNil(actualErr) + s.Assert().ErrorContains(actualErr, c.err) + } else { + testToken := &azcore.AccessToken{ + Token: testTokenString, + ExpiresOn: testTokenExpiry, + } + + s.mockCredential.On("GetToken", mock.Anything, mock.Anything).Return(*testToken, nil).Once(). + On("GetToken", mock.Anything, mock.Anything).Return(getToken(), nil) + + actualTokenProvider, actualErr := newTokenProvider(c.cfg, s.mockCredential) + + s.Assert().NotNil(actualTokenProvider) + s.Assert().Nil(actualErr) + s.Assert().NotNil(actualTokenProvider.getAccessToken(context.Background())) + + // Token set to refresh at half of the expiry time. The test tokens are set to expiry in 5s. + // Hence, the 4 seconds wait to check if the token is refreshed. + time.Sleep(4 * time.Second) + + s.Assert().NotNil(actualTokenProvider.getAccessToken(context.Background())) + + s.mockCredential.AssertNumberOfCalls(s.T(), "GetToken", 2*mockGetTokenCallCounter) + mockGetTokenCallCounter += 1 + accessToken, err := actualTokenProvider.getAccessToken(context.Background()) + s.Assert().Nil(err) + s.Assert().NotEqual(accessToken, testTokenString) + } } - - actualTokenProvider, actualErr := newTokenProvider(azureAdConfig, s.mockCredential) - - s.Assert().Nil(actualTokenProvider) - s.Assert().NotNil(actualErr) - s.Assert().Equal("Cloud is not specified or is incorrect: "+azureAdConfig.Cloud, actualErr.Error()) -} - -func (s *TokenProviderTestSuite) TestNewTokenProvider_Success() { - managedIdentityConfig := &ManagedIdentityConfig{ - ClientID: dummyClientID, - } - - azureAdConfig := &AzureADConfig{ - Cloud: "AzurePublic", - ManagedIdentity: managedIdentityConfig, - } - s.mockCredential.On("GetToken", mock.Anything, mock.Anything).Return(getToken(), nil) - - actualTokenProvider, actualErr := newTokenProvider(azureAdConfig, s.mockCredential) - - s.Assert().NotNil(actualTokenProvider) - s.Assert().Nil(actualErr) - s.Assert().NotNil(actualTokenProvider.getAccessToken(context.Background())) -} - -func (s *TokenProviderTestSuite) TestPeriodicTokenRefresh_Success() { - // setup - managedIdentityConfig := &ManagedIdentityConfig{ - ClientID: dummyClientID, - } - - azureAdConfig := &AzureADConfig{ - Cloud: "AzurePublic", - ManagedIdentity: managedIdentityConfig, - } - testToken := &azcore.AccessToken{ - Token: testTokenString, - ExpiresOn: testTokenExpiry, - } - - s.mockCredential.On("GetToken", mock.Anything, mock.Anything).Return(*testToken, nil).Once(). - On("GetToken", mock.Anything, mock.Anything).Return(getToken(), nil) - - actualTokenProvider, actualErr := newTokenProvider(azureAdConfig, s.mockCredential) - - s.Assert().NotNil(actualTokenProvider) - s.Assert().Nil(actualErr) - s.Assert().NotNil(actualTokenProvider.getAccessToken(context.Background())) - - // Token set to refresh at half of the expiry time. The test tokens are set to expiry in 10s. - // Hence, the 6 seconds wait to check if the token is refreshed. - time.Sleep(6 * time.Second) - - s.Assert().NotNil(actualTokenProvider.getAccessToken(context.Background())) - - s.mockCredential.AssertNumberOfCalls(s.T(), "GetToken", 2) - accessToken, err := actualTokenProvider.getAccessToken(context.Background()) - s.Assert().Nil(err) - s.Assert().NotEqual(accessToken, testTokenString) } func getToken() azcore.AccessToken { diff --git a/storage/remote/azuread/testdata/azuread_bad_clientidmissing.yaml b/storage/remote/azuread/testdata/azuread_bad_configmissing.yaml similarity index 100% rename from storage/remote/azuread/testdata/azuread_bad_clientidmissing.yaml rename to storage/remote/azuread/testdata/azuread_bad_configmissing.yaml diff --git a/storage/remote/azuread/testdata/azuread_bad_invalidoauthconfig.yaml b/storage/remote/azuread/testdata/azuread_bad_invalidoauthconfig.yaml new file mode 100644 index 0000000000..1b01dc2e6f --- /dev/null +++ b/storage/remote/azuread/testdata/azuread_bad_invalidoauthconfig.yaml @@ -0,0 +1,4 @@ +cloud: AzurePublic +oauth: + client_id: 00000000-0000-0000-0000-000000000000 + client_secret: Cl1ent$ecret! diff --git a/storage/remote/azuread/testdata/azuread_bad_twoconfig.yaml b/storage/remote/azuread/testdata/azuread_bad_twoconfig.yaml new file mode 100644 index 0000000000..710f6d3535 --- /dev/null +++ b/storage/remote/azuread/testdata/azuread_bad_twoconfig.yaml @@ -0,0 +1,7 @@ +cloud: AzurePublic +managed_identity: + client_id: 00000000-0000-0000-0000-000000000000 +oauth: + client_id: 00000000-0000-0000-0000-000000000000 + client_secret: Cl1ent$ecret! + tenant_id: 00000000-a12b-3cd4-e56f-000000000000 diff --git a/storage/remote/azuread/testdata/azuread_good.yaml b/storage/remote/azuread/testdata/azuread_good_managedidentity.yaml similarity index 100% rename from storage/remote/azuread/testdata/azuread_good.yaml rename to storage/remote/azuread/testdata/azuread_good_managedidentity.yaml diff --git a/storage/remote/azuread/testdata/azuread_good_oauth.yaml b/storage/remote/azuread/testdata/azuread_good_oauth.yaml new file mode 100644 index 0000000000..473297f99b --- /dev/null +++ b/storage/remote/azuread/testdata/azuread_good_oauth.yaml @@ -0,0 +1,5 @@ +cloud: AzurePublic +oauth: + client_id: 00000000-0000-0000-0000-000000000000 + client_secret: Cl1ent$ecret! + tenant_id: 00000000-a12b-3cd4-e56f-000000000000 From 7c934ae18cd02d600d2d4f40b4a42b9b53126b74 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 5 Oct 2023 11:04:59 +0000 Subject: [PATCH 42/55] scraping: hoist labels variable to save garbage `lset` escapes to heap due to being passed through the text-parser interface, so we can reduce garbage by hoisting it out of the loop so only one allocation is done for every series in a scrape. Signed-off-by: Bryan Boreham --- scrape/scrape.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scrape/scrape.go b/scrape/scrape.go index 4d13d7f6b1..e40ae81d28 100644 --- a/scrape/scrape.go +++ b/scrape/scrape.go @@ -1525,6 +1525,7 @@ func (sl *scrapeLoop) append(app storage.Appender, b []byte, contentType string, appErrs = appendErrors{} sampleLimitErr error bucketLimitErr error + lset labels.Labels // escapes to heap so hoisted out of loop e exemplar.Exemplar // escapes to heap so hoisted out of loop meta metadata.Metadata metadataChanged bool @@ -1622,7 +1623,6 @@ loop: ce, ok := sl.cache.get(met) var ( ref storage.SeriesRef - lset labels.Labels hash uint64 ) From 0cbf0c1c68b7d5590d770db13707e62fac96277c Mon Sep 17 00:00:00 2001 From: Jeanette Tan Date: Fri, 6 Oct 2023 19:09:32 +0800 Subject: [PATCH 43/55] Revise according to code review Signed-off-by: Jeanette Tan --- promql/functions.go | 2 +- promql/quantile.go | 31 ++++++++----------------------- util/annotations/annotations.go | 30 +++++++++++++++--------------- 3 files changed, 24 insertions(+), 39 deletions(-) diff --git a/promql/functions.go b/promql/functions.go index 2a1a0b0300..8eb0cad8ad 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -1174,7 +1174,7 @@ func funcHistogramQuantile(vals []parser.Value, args parser.Expressions, enh *Ev F: res, }) if forcedMonotonicity { - annos.Add(annotations.NewHistogramQuantileForcedMonotonicityWarning(mb.metric.Get(labels.MetricName), args[1].PositionRange())) + annos.Add(annotations.NewHistogramQuantileForcedMonotonicityInfo(mb.metric.Get(labels.MetricName), args[1].PositionRange())) } } } diff --git a/promql/quantile.go b/promql/quantile.go index 1ebc39aa28..f289448682 100644 --- a/promql/quantile.go +++ b/promql/quantile.go @@ -344,37 +344,22 @@ func coalesceBuckets(buckets buckets) buckets { // The assumption that bucket counts increase monotonically with increasing // upperBound may be violated during: // -// * Recording rule evaluation of histogram_quantile, especially when rate() -// has been applied to the underlying bucket timeseries. -// * Evaluation of histogram_quantile computed over federated bucket -// timeseries, especially when rate() has been applied. -// -// This is because scraped data is not made available to rule evaluation or -// federation atomically, so some buckets are computed with data from the -// most recent scrapes, but the other buckets are missing data from the most -// recent scrape. +// - Circumstances where data is already inconsistent at the target's side. +// - Ingestion via the remote write receiver that Prometheus implements. +// - Optimisation of query execution where precision is sacrificed for other +// benefits, not by Prometheus but by systems built on top of it. // // Monotonicity is usually guaranteed because if a bucket with upper bound // u1 has count c1, then any bucket with a higher upper bound u > u1 must -// have counted all c1 observations and perhaps more, so that c >= c1. -// -// Randomly interspersed partial sampling breaks that guarantee, and rate() -// exacerbates it. Specifically, suppose bucket le=1000 has a count of 10 from -// 4 samples but the bucket with le=2000 has a count of 7 from 3 samples. The -// monotonicity is broken. It is exacerbated by rate() because under normal -// operation, cumulative counting of buckets will cause the bucket counts to -// diverge such that small differences from missing samples are not a problem. -// rate() removes this divergence.) +// have counted all c1 observations and perhaps more, so that c >= c1. // // bucketQuantile depends on that monotonicity to do a binary search for the // bucket with the φ-quantile count, so breaking the monotonicity // guarantee causes bucketQuantile() to return undefined (nonsense) results. // -// As a somewhat hacky solution until ingestion is atomic per scrape, we -// calculate the "envelope" of the histogram buckets, essentially removing -// any decreases in the count between successive buckets. We return a bool -// to indicate if this monotonicity was forced or not. - +// As a somewhat hacky solution, we calculate the "envelope" of the histogram +// buckets, essentially removing any decreases in the count between successive +// buckets. We return a bool to indicate if this monotonicity was forced or not. func ensureMonotonic(buckets buckets) bool { forced := false max := buckets[0].count diff --git a/util/annotations/annotations.go b/util/annotations/annotations.go index bff0100d91..082909411c 100644 --- a/util/annotations/annotations.go +++ b/util/annotations/annotations.go @@ -100,13 +100,13 @@ var ( PromQLInfo = errors.New("PromQL info") PromQLWarning = errors.New("PromQL warning") - InvalidQuantileWarning = fmt.Errorf("%w: quantile value should be between 0 and 1", PromQLWarning) - BadBucketLabelWarning = fmt.Errorf("%w: bucket label %q is missing or has a malformed value", PromQLWarning, model.BucketLabel) - MixedFloatsHistogramsWarning = fmt.Errorf("%w: encountered a mix of histograms and floats for metric name", PromQLWarning) - MixedClassicNativeHistogramsWarning = fmt.Errorf("%w: vector contains a mix of classic and native histograms for metric name", PromQLWarning) - HistogramQuantileForcedMonotonicityWarning = fmt.Errorf("%w: input to histogram_quantile needed to be fixed for monotonicity (and may give inaccurate results) for metric name", PromQLWarning) + InvalidQuantileWarning = fmt.Errorf("%w: quantile value should be between 0 and 1", PromQLWarning) + BadBucketLabelWarning = fmt.Errorf("%w: bucket label %q is missing or has a malformed value", PromQLWarning, model.BucketLabel) + MixedFloatsHistogramsWarning = fmt.Errorf("%w: encountered a mix of histograms and floats for metric name", PromQLWarning) + MixedClassicNativeHistogramsWarning = fmt.Errorf("%w: vector contains a mix of classic and native histograms for metric name", PromQLWarning) - PossibleNonCounterInfo = fmt.Errorf("%w: metric might not be a counter, name does not end in _total/_sum/_count:", PromQLInfo) + PossibleNonCounterInfo = fmt.Errorf("%w: metric might not be a counter, name does not end in _total/_sum/_count:", PromQLInfo) + HistogramQuantileForcedMonotonicityInfo = fmt.Errorf("%w: input to histogram_quantile needed to be fixed for monotonicity (and may give inaccurate results) for metric name", PromQLInfo) ) type annoErr struct { @@ -156,15 +156,6 @@ func NewMixedClassicNativeHistogramsWarning(metricName string, pos posrange.Posi } } -// NewHistogramQuantileForcedMonotonicityWarning is used when the input (classic histograms) to -// histogram_quantile needs to be forced to be monotonic. -func NewHistogramQuantileForcedMonotonicityWarning(metricName string, pos posrange.PositionRange) annoErr { - return annoErr{ - PositionRange: pos, - Err: fmt.Errorf("%w %q", HistogramQuantileForcedMonotonicityWarning, metricName), - } -} - // NewPossibleNonCounterInfo is used when a counter metric does not have the suffixes // _total, _sum or _count. func NewPossibleNonCounterInfo(metricName string, pos posrange.PositionRange) annoErr { @@ -173,3 +164,12 @@ func NewPossibleNonCounterInfo(metricName string, pos posrange.PositionRange) an Err: fmt.Errorf("%w %q", PossibleNonCounterInfo, metricName), } } + +// NewHistogramQuantileForcedMonotonicityInfo is used when the input (classic histograms) to +// histogram_quantile needs to be forced to be monotonic. +func NewHistogramQuantileForcedMonotonicityInfo(metricName string, pos posrange.PositionRange) annoErr { + return annoErr{ + PositionRange: pos, + Err: fmt.Errorf("%w %q", HistogramQuantileForcedMonotonicityInfo, metricName), + } +} From a5a4eab679ccf2d432ab34b5143ef9e1c6482839 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 6 Oct 2023 12:28:07 +0100 Subject: [PATCH 44/55] Storage: reduce memory allocations when merging series sets (#12938) Instead of setting to nil and allocating a new slice every time the merge is advanced, re-use the previous slice. This is safe because the `currentSets` member is only used inside member functions, and explicitly copied in `At()`, the only place it leaves the struct. Signed-off-by: Bryan Boreham --- storage/merge.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/merge.go b/storage/merge.go index f7a88738c3..1e29374e53 100644 --- a/storage/merge.go +++ b/storage/merge.go @@ -347,7 +347,7 @@ func (c *genericMergeSeriesSet) Next() bool { } // Now, pop items of the heap that have equal label sets. - c.currentSets = nil + c.currentSets = c.currentSets[:0] c.currentLabels = c.heap[0].At().Labels() for len(c.heap) > 0 && labels.Equal(c.currentLabels, c.heap[0].At().Labels()) { set := heap.Pop(&c.heap).(genericSeriesSet) From d3554d84215e6279c4bf3d0bb2229206f012b689 Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Sun, 8 Oct 2023 13:51:24 +0100 Subject: [PATCH 45/55] Show group interval in Rules display (#12943) * Show group interval in Rules display Signed-off-by: Danny Kopping * Humanise interval Signed-off-by: Danny Kopping --------- Signed-off-by: Danny Kopping --- web/ui/react-app/src/pages/rules/RulesContent.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/ui/react-app/src/pages/rules/RulesContent.tsx b/web/ui/react-app/src/pages/rules/RulesContent.tsx index ef4a7ad8f8..9bb866d47b 100644 --- a/web/ui/react-app/src/pages/rules/RulesContent.tsx +++ b/web/ui/react-app/src/pages/rules/RulesContent.tsx @@ -13,6 +13,7 @@ interface RulesContentProps { interface RuleGroup { name: string; file: string; + interval: string; rules: Rule[]; evaluationTime: string; lastEvaluation: string; @@ -58,13 +59,16 @@ export const RulesContent: FC = ({ response }) => { - + From a7737ab3acd4c1c298176fd4d8e99b7359d4e223 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Mon, 9 Oct 2023 10:02:30 +0200 Subject: [PATCH 46/55] Fix PostingsCloner tests Signed-off-by: Arve Knudsen --- tsdb/index/postings_test.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tsdb/index/postings_test.go b/tsdb/index/postings_test.go index 4cc2bd9a24..7a5677c0dd 100644 --- a/tsdb/index/postings_test.go +++ b/tsdb/index/postings_test.go @@ -990,11 +990,9 @@ func TestPostingsCloner(t *testing.T) { check: func(t testing.TB, pc *PostingsCloner) { p1 := pc.Clone() require.False(t, p1.Seek(9)) - require.Equal(t, storage.SeriesRef(0), p1.At()) p2 := pc.Clone() require.False(t, p2.Seek(10)) - require.Equal(t, storage.SeriesRef(0), p2.At()) }, }, { @@ -1002,7 +1000,6 @@ func TestPostingsCloner(t *testing.T) { check: func(t testing.TB, pc *PostingsCloner) { p1 := pc.Clone() require.False(t, p1.Seek(9)) - require.Equal(t, storage.SeriesRef(0), p1.At()) p2 := pc.Clone() require.True(t, p2.Seek(2)) @@ -1070,21 +1067,12 @@ func TestPostingsCloner(t *testing.T) { require.Equal(t, storage.SeriesRef(4), p2.At()) }, }, - { - name: "at before call of next shouldn't panic", - check: func(t testing.TB, pc *PostingsCloner) { - p := pc.Clone() - require.Equal(t, storage.SeriesRef(0), p.At()) - }, - }, { name: "ensure a failed seek doesn't allow more next calls", check: func(t testing.TB, pc *PostingsCloner) { p := pc.Clone() require.False(t, p.Seek(9)) - require.Equal(t, storage.SeriesRef(0), p.At()) require.False(t, p.Next()) - require.Equal(t, storage.SeriesRef(0), p.At()) }, }, } { From 27d0e12f326dc50442fa8c95e3148cb9c2cd94a3 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Mon, 9 Oct 2023 11:43:46 +0200 Subject: [PATCH 47/55] Update tsdb/compact.go Co-authored-by: George Krajcsovits --- tsdb/compact.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tsdb/compact.go b/tsdb/compact.go index 4c264603ec..6f6f8a7a0c 100644 --- a/tsdb/compact.go +++ b/tsdb/compact.go @@ -233,7 +233,14 @@ func (c *LeveledCompactor) Plan(dir string) ([]string, error) { func (c *LeveledCompactor) plan(dms []dirMeta) ([]string, error) { slices.SortFunc(dms, func(a, b dirMeta) int { - return int(a.meta.MinTime - b.meta.MinTime) + switch { + case a.meta.MinTime < b.meta.MinTime: + return -1 + case a.meta.MinTime > b.meta.MinTime: + return 1 + default: + return 0 + } }) res := c.selectOverlappingDirs(dms) From 5bd8c8c561ecc8bf3dd37b80eb111eba64baa659 Mon Sep 17 00:00:00 2001 From: Oleg Zaytsev Date: Mon, 9 Oct 2023 16:15:06 +0200 Subject: [PATCH 48/55] Clarify Postings.At() contract (#12921) It's implicit, but should be explicit. It is invalid to call At() after a failed call to Next() or Seek(). Following up on https://github.com/prometheus/prometheus/pull/12906 Signed-off-by: Oleg Zaytsev --- tsdb/index/postings.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tsdb/index/postings.go b/tsdb/index/postings.go index 5f24dbfe1a..2132014ec8 100644 --- a/tsdb/index/postings.go +++ b/tsdb/index/postings.go @@ -413,6 +413,7 @@ type Postings interface { Seek(v storage.SeriesRef) bool // At returns the value at the current iterator position. + // At should only be called after a successful call to Next or Seek. At() storage.SeriesRef // Err returns the last error of the iterator. From fe90dcccffec8596ff3901b943aef5e1982172d6 Mon Sep 17 00:00:00 2001 From: Oleg Zaytsev Date: Mon, 9 Oct 2023 17:25:18 +0200 Subject: [PATCH 49/55] Revert ListPostings change (#12955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts change from https://github.com/prometheus/prometheus/pull/12906 The benchmarks show that it's slower when intersecting, which is a common usage for ListPostings (when intersecting matchers from Head) (old is before #12906, new is #12906): │ old │ new │ │ sec/op │ sec/op vs base │ Intersect/LongPostings1-16 20.54µ ± 1% 21.11µ ± 1% +2.76% (p=0.000 n=20) Intersect/LongPostings2-16 51.03m ± 1% 52.40m ± 2% +2.69% (p=0.000 n=20) Intersect/ManyPostings-16 194.2m ± 3% 332.1m ± 1% +71.00% (p=0.000 n=20) geomean 5.882m 7.161m +21.74% Signed-off-by: Oleg Zaytsev --- tsdb/index/postings.go | 35 ++++++++++++++++++++--------------- tsdb/index/postings_test.go | 2 ++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/tsdb/index/postings.go b/tsdb/index/postings.go index 2132014ec8..f79a8d4cfc 100644 --- a/tsdb/index/postings.go +++ b/tsdb/index/postings.go @@ -748,7 +748,7 @@ func (rp *removedPostings) Err() error { // ListPostings implements the Postings interface over a plain list. type ListPostings struct { list []storage.SeriesRef - pos int + cur storage.SeriesRef } func NewListPostings(list []storage.SeriesRef) Postings { @@ -760,34 +760,39 @@ func newListPostings(list ...storage.SeriesRef) *ListPostings { } func (it *ListPostings) At() storage.SeriesRef { - return it.list[it.pos-1] + return it.cur } func (it *ListPostings) Next() bool { - if it.pos < len(it.list) { - it.pos++ + if len(it.list) > 0 { + it.cur = it.list[0] + it.list = it.list[1:] return true } + it.cur = 0 return false } func (it *ListPostings) Seek(x storage.SeriesRef) bool { - if it.pos == 0 { - it.pos++ - } - if it.pos > len(it.list) { - return false - } // If the current value satisfies, then return. - if it.list[it.pos-1] >= x { + if it.cur >= x { return true } + if len(it.list) == 0 { + return false + } // Do binary search between current position and end. - it.pos = sort.Search(len(it.list[it.pos-1:]), func(i int) bool { - return it.list[i+it.pos-1] >= x - }) + it.pos - return it.pos-1 < len(it.list) + i := sort.Search(len(it.list), func(i int) bool { + return it.list[i] >= x + }) + if i < len(it.list) { + it.cur = it.list[i] + it.list = it.list[i+1:] + return true + } + it.list = nil + return false } func (it *ListPostings) Err() error { diff --git a/tsdb/index/postings_test.go b/tsdb/index/postings_test.go index f0f3bb75a8..783b5f84fc 100644 --- a/tsdb/index/postings_test.go +++ b/tsdb/index/postings_test.go @@ -1242,6 +1242,8 @@ func TestListPostings(t *testing.T) { }) } +// BenchmarkListPostings benchmarks ListPostings by iterating Next/At sequentially. +// See also BenchmarkIntersect as it performs more `At` calls than `Next` calls when intersecting. func BenchmarkListPostings(b *testing.B) { const maxCount = 1e6 input := make([]storage.SeriesRef, maxCount) From e7a1d3bfafb405d0f9fa83503619344665da8d8a Mon Sep 17 00:00:00 2001 From: Levi Harrison Date: Mon, 9 Oct 2023 12:21:57 -0400 Subject: [PATCH 50/55] Volunteer Levi Harrison for release shepherd Signed-off-by: Levi Harrison --- RELEASE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index 2ae07281b0..c39cc824ba 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -52,7 +52,8 @@ Release cadence of first pre-releases being cut is 6 weeks. | v2.45 LTS | 2023-05-31 | Jesus Vazquez (Github: @jesusvazquez) | | v2.46 | 2023-07-12 | Julien Pivotto (GitHub: @roidelapluie) | | v2.47 | 2023-08-23 | Bryan Boreham (GitHub: @bboreham) | -| v2.48 | 2023-10-04 | **searching for volunteer** | +| v2.48 | 2023-10-04 | Levi Harrison (GitHub: @LeviHarrison) | +| v2.49 | 2023-11-15 | **searching for volunteer** | If you are interested in volunteering please create a pull request against the [prometheus/prometheus](https://github.com/prometheus/prometheus) repository and propose yourself for the release series of your choice. From f6d9c84fde6b0fc89019590d4081876c7d93d609 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 9 Oct 2023 17:23:53 +0100 Subject: [PATCH 51/55] scraping: delay creating buffer, to save memory (#12953) We don't need the buffer to read the response until the scrape http call returns; creating it earlier makes the buffer pool larger. I split `scrape()` into `scrape()` which returns with the http response, and `readResponse()` which decompresses and copies the data into the supplied buffer. This design was chosen to minimize impact on the logic. Signed-off-by: Bryan Boreham --- scrape/scrape.go | 41 ++++++++++++++++++++++++----------------- scrape/scrape_test.go | 32 ++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/scrape/scrape.go b/scrape/scrape.go index e40ae81d28..299ffdc98b 100644 --- a/scrape/scrape.go +++ b/scrape/scrape.go @@ -785,7 +785,8 @@ func appender(app storage.Appender, sampleLimit, bucketLimit int) storage.Append // A scraper retrieves samples and accepts a status report at the end. type scraper interface { - scrape(ctx context.Context, w io.Writer) (string, error) + scrape(ctx context.Context) (*http.Response, error) + readResponse(ctx context.Context, resp *http.Response, w io.Writer) (string, error) Report(start time.Time, dur time.Duration, err error) offset(interval time.Duration, offsetSeed uint64) time.Duration } @@ -814,11 +815,11 @@ const ( var UserAgent = fmt.Sprintf("Prometheus/%s", version.Version) -func (s *targetScraper) scrape(ctx context.Context, w io.Writer) (string, error) { +func (s *targetScraper) scrape(ctx context.Context) (*http.Response, error) { if s.req == nil { req, err := http.NewRequest("GET", s.URL().String(), nil) if err != nil { - return "", err + return nil, err } req.Header.Add("Accept", s.acceptHeader) req.Header.Add("Accept-Encoding", "gzip") @@ -828,10 +829,10 @@ func (s *targetScraper) scrape(ctx context.Context, w io.Writer) (string, error) s.req = req } - resp, err := s.client.Do(s.req.WithContext(ctx)) - if err != nil { - return "", err - } + return s.client.Do(s.req.WithContext(ctx)) +} + +func (s *targetScraper) readResponse(ctx context.Context, resp *http.Response, w io.Writer) (string, error) { defer func() { io.Copy(io.Discard, resp.Body) resp.Body.Close() @@ -858,13 +859,14 @@ func (s *targetScraper) scrape(ctx context.Context, w io.Writer) (string, error) if s.gzipr == nil { s.buf = bufio.NewReader(resp.Body) + var err error s.gzipr, err = gzip.NewReader(s.buf) if err != nil { return "", err } } else { s.buf.Reset(resp.Body) - if err = s.gzipr.Reset(s.buf); err != nil { + if err := s.gzipr.Reset(s.buf); err != nil { return "", err } } @@ -1326,11 +1328,7 @@ func (sl *scrapeLoop) scrapeAndReport(last, appendTime time.Time, errc chan<- er ) } - b := sl.buffers.Get(sl.lastScrapeSize).([]byte) - defer sl.buffers.Put(b) - buf := bytes.NewBuffer(b) - - var total, added, seriesAdded, bytes int + var total, added, seriesAdded, bytesRead int var err, appErr, scrapeErr error app := sl.appender(sl.appenderCtx) @@ -1346,7 +1344,7 @@ func (sl *scrapeLoop) scrapeAndReport(last, appendTime time.Time, errc chan<- er }() defer func() { - if err = sl.report(app, appendTime, time.Since(start), total, added, seriesAdded, bytes, scrapeErr); err != nil { + if err = sl.report(app, appendTime, time.Since(start), total, added, seriesAdded, bytesRead, scrapeErr); err != nil { level.Warn(sl.l).Log("msg", "Appending scrape report failed", "err", err) } }() @@ -1367,8 +1365,17 @@ func (sl *scrapeLoop) scrapeAndReport(last, appendTime time.Time, errc chan<- er } var contentType string + var resp *http.Response + var b []byte + var buf *bytes.Buffer scrapeCtx, cancel := context.WithTimeout(sl.parentCtx, sl.timeout) - contentType, scrapeErr = sl.scraper.scrape(scrapeCtx, buf) + resp, scrapeErr = sl.scraper.scrape(scrapeCtx) + if scrapeErr == nil { + b = sl.buffers.Get(sl.lastScrapeSize).([]byte) + defer sl.buffers.Put(b) + buf = bytes.NewBuffer(b) + contentType, scrapeErr = sl.scraper.readResponse(scrapeCtx, resp, buf) + } cancel() if scrapeErr == nil { @@ -1379,14 +1386,14 @@ func (sl *scrapeLoop) scrapeAndReport(last, appendTime time.Time, errc chan<- er if len(b) > 0 { sl.lastScrapeSize = len(b) } - bytes = len(b) + bytesRead = len(b) } else { level.Debug(sl.l).Log("msg", "Scrape failed", "err", scrapeErr) if errc != nil { errc <- scrapeErr } if errors.Is(scrapeErr, errBodySizeLimit) { - bytes = -1 + bytesRead = -1 } } diff --git a/scrape/scrape_test.go b/scrape/scrape_test.go index 3b7d6a7abb..6c09b95e5a 100644 --- a/scrape/scrape_test.go +++ b/scrape/scrape_test.go @@ -2619,7 +2619,9 @@ func TestTargetScraperScrapeOK(t *testing.T) { } var buf bytes.Buffer - contentType, err := ts.scrape(context.Background(), &buf) + resp, err := ts.scrape(context.Background()) + require.NoError(t, err) + contentType, err := ts.readResponse(context.Background(), resp, &buf) require.NoError(t, err) require.Equal(t, "text/plain; version=0.0.4", contentType) require.Equal(t, "metric_a 1\nmetric_b 2\n", buf.String()) @@ -2665,7 +2667,7 @@ func TestTargetScrapeScrapeCancel(t *testing.T) { }() go func() { - _, err := ts.scrape(ctx, io.Discard) + _, err := ts.scrape(ctx) switch { case err == nil: errc <- errors.New("Expected error but got nil") @@ -2711,7 +2713,9 @@ func TestTargetScrapeScrapeNotFound(t *testing.T) { acceptHeader: scrapeAcceptHeader, } - _, err = ts.scrape(context.Background(), io.Discard) + resp, err := ts.scrape(context.Background()) + require.NoError(t, err) + _, err = ts.readResponse(context.Background(), resp, io.Discard) require.Contains(t, err.Error(), "404", "Expected \"404 NotFound\" error but got: %s", err) } @@ -2755,26 +2759,34 @@ func TestTargetScraperBodySizeLimit(t *testing.T) { var buf bytes.Buffer // Target response uncompressed body, scrape with body size limit. - _, err = ts.scrape(context.Background(), &buf) + resp, err := ts.scrape(context.Background()) + require.NoError(t, err) + _, err = ts.readResponse(context.Background(), resp, &buf) require.ErrorIs(t, err, errBodySizeLimit) require.Equal(t, bodySizeLimit, buf.Len()) // Target response gzip compressed body, scrape with body size limit. gzipResponse = true buf.Reset() - _, err = ts.scrape(context.Background(), &buf) + resp, err = ts.scrape(context.Background()) + require.NoError(t, err) + _, err = ts.readResponse(context.Background(), resp, &buf) require.ErrorIs(t, err, errBodySizeLimit) require.Equal(t, bodySizeLimit, buf.Len()) // Target response uncompressed body, scrape without body size limit. gzipResponse = false buf.Reset() ts.bodySizeLimit = 0 - _, err = ts.scrape(context.Background(), &buf) + resp, err = ts.scrape(context.Background()) + require.NoError(t, err) + _, err = ts.readResponse(context.Background(), resp, &buf) require.NoError(t, err) require.Equal(t, len(responseBody), buf.Len()) // Target response gzip compressed body, scrape without body size limit. gzipResponse = true buf.Reset() - _, err = ts.scrape(context.Background(), &buf) + resp, err = ts.scrape(context.Background()) + require.NoError(t, err) + _, err = ts.readResponse(context.Background(), resp, &buf) require.NoError(t, err) require.Equal(t, len(responseBody), buf.Len()) } @@ -2802,7 +2814,11 @@ func (ts *testScraper) Report(start time.Time, duration time.Duration, err error ts.lastError = err } -func (ts *testScraper) scrape(ctx context.Context, w io.Writer) (string, error) { +func (ts *testScraper) scrape(ctx context.Context) (*http.Response, error) { + return nil, ts.scrapeErr +} + +func (ts *testScraper) readResponse(ctx context.Context, resp *http.Response, w io.Writer) (string, error) { if ts.scrapeFunc != nil { return "", ts.scrapeFunc(ctx, w) } From 26d07ee8d334ec1cc9ec5979cad8c47eca327254 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Tue, 10 Oct 2023 09:49:10 +0200 Subject: [PATCH 52/55] tsdb: Avoid potential overflow in SortFunc Signed-off-by: Arve Knudsen --- tsdb/db.go | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/tsdb/db.go b/tsdb/db.go index 524fba7276..d8e40594ba 100644 --- a/tsdb/db.go +++ b/tsdb/db.go @@ -631,7 +631,14 @@ func (db *DBReadOnly) Blocks() ([]BlockReader, error) { } slices.SortFunc(loadable, func(a, b *Block) int { - return int(a.Meta().MinTime - b.Meta().MinTime) + switch { + case a.Meta().MinTime < b.Meta().MinTime: + return -1 + case a.Meta().MinTime > b.Meta().MinTime: + return 1 + default: + return 0 + } }) blockMetas := make([]BlockMeta, 0, len(loadable)) @@ -1507,7 +1514,14 @@ func (db *DB) reloadBlocks() (err error) { db.metrics.blocksBytes.Set(float64(blocksSize)) slices.SortFunc(toLoad, func(a, b *Block) int { - return int(a.Meta().MinTime - b.Meta().MinTime) + switch { + case a.Meta().MinTime < b.Meta().MinTime: + return -1 + case a.Meta().MinTime > b.Meta().MinTime: + return 1 + default: + return 0 + } }) // Swap new blocks first for subsequently created readers to be seen. @@ -1582,7 +1596,14 @@ func deletableBlocks(db *DB, blocks []*Block) map[ulid.ULID]struct{} { // Sort the blocks by time - newest to oldest (largest to smallest timestamp). // This ensures that the retentions will remove the oldest blocks. slices.SortFunc(blocks, func(a, b *Block) int { - return int(b.Meta().MaxTime - a.Meta().MaxTime) + switch { + case b.Meta().MaxTime < a.Meta().MaxTime: + return -1 + case b.Meta().MaxTime > a.Meta().MaxTime: + return 1 + default: + return 0 + } }) for _, block := range blocks { From 4b9c19fe55108e39838472f2b08bc07fb96741a2 Mon Sep 17 00:00:00 2001 From: Arthur Silva Sens Date: Tue, 10 Oct 2023 04:54:49 -0300 Subject: [PATCH 53/55] Add created timestamps to prompb (#12936) Signed-off-by: Arthur Silva Sens --- prompb/io/prometheus/client/metrics.pb.go | 381 ++++++++++++++++------ prompb/io/prometheus/client/metrics.proto | 8 +- 2 files changed, 289 insertions(+), 100 deletions(-) diff --git a/prompb/io/prometheus/client/metrics.pb.go b/prompb/io/prometheus/client/metrics.pb.go index 83a7da7799..05d25747b4 100644 --- a/prompb/io/prometheus/client/metrics.pb.go +++ b/prompb/io/prometheus/client/metrics.pb.go @@ -172,11 +172,12 @@ func (m *Gauge) GetValue() float64 { } type Counter struct { - Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` - Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar,proto3" json:"exemplar,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` + Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar,proto3" json:"exemplar,omitempty"` + CreatedTimestamp *types.Timestamp `protobuf:"bytes,3,opt,name=created_timestamp,json=createdTimestamp,proto3" json:"created_timestamp,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Counter) Reset() { *m = Counter{} } @@ -226,6 +227,13 @@ func (m *Counter) GetExemplar() *Exemplar { return nil } +func (m *Counter) GetCreatedTimestamp() *types.Timestamp { + if m != nil { + return m.CreatedTimestamp + } + return nil +} + type Quantile struct { Quantile float64 `protobuf:"fixed64,1,opt,name=quantile,proto3" json:"quantile,omitempty"` Value float64 `protobuf:"fixed64,2,opt,name=value,proto3" json:"value,omitempty"` @@ -282,12 +290,13 @@ func (m *Quantile) GetValue() float64 { } type Summary struct { - SampleCount uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount,proto3" json:"sample_count,omitempty"` - SampleSum float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum,proto3" json:"sample_sum,omitempty"` - Quantile []Quantile `protobuf:"bytes,3,rep,name=quantile,proto3" json:"quantile"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + SampleCount uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount,proto3" json:"sample_count,omitempty"` + SampleSum float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum,proto3" json:"sample_sum,omitempty"` + Quantile []Quantile `protobuf:"bytes,3,rep,name=quantile,proto3" json:"quantile"` + CreatedTimestamp *types.Timestamp `protobuf:"bytes,4,opt,name=created_timestamp,json=createdTimestamp,proto3" json:"created_timestamp,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Summary) Reset() { *m = Summary{} } @@ -344,6 +353,13 @@ func (m *Summary) GetQuantile() []Quantile { return nil } +func (m *Summary) GetCreatedTimestamp() *types.Timestamp { + if m != nil { + return m.CreatedTimestamp + } + return nil +} + type Untyped struct { Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -396,7 +412,8 @@ type Histogram struct { SampleCountFloat float64 `protobuf:"fixed64,4,opt,name=sample_count_float,json=sampleCountFloat,proto3" json:"sample_count_float,omitempty"` SampleSum float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum,proto3" json:"sample_sum,omitempty"` // Buckets for the conventional histogram. - Bucket []Bucket `protobuf:"bytes,3,rep,name=bucket,proto3" json:"bucket"` + Bucket []Bucket `protobuf:"bytes,3,rep,name=bucket,proto3" json:"bucket"` + CreatedTimestamp *types.Timestamp `protobuf:"bytes,15,opt,name=created_timestamp,json=createdTimestamp,proto3" json:"created_timestamp,omitempty"` // schema defines the bucket schema. Currently, valid numbers are -4 <= n <= 8. // They are all for base-2 bucket schemas, where 1 is a bucket boundary in each case, and // then each power of two is divided into 2^n logarithmic buckets. @@ -489,6 +506,13 @@ func (m *Histogram) GetBucket() []Bucket { return nil } +func (m *Histogram) GetCreatedTimestamp() *types.Timestamp { + if m != nil { + return m.CreatedTimestamp + } + return nil +} + func (m *Histogram) GetSchema() int32 { if m != nil { return m.Schema @@ -941,65 +965,68 @@ func init() { } var fileDescriptor_d1e5ddb18987a258 = []byte{ - // 923 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x8e, 0xdb, 0x44, - 0x18, 0xad, 0x1b, 0xe7, 0xc7, 0x5f, 0x36, 0xdb, 0x74, 0x88, 0x2a, 0x6b, 0x61, 0x37, 0xc1, 0x12, - 0xd2, 0x82, 0x50, 0x22, 0xa0, 0x08, 0x54, 0x40, 0x62, 0xb7, 0xdd, 0x6e, 0x51, 0x49, 0x5b, 0x26, - 0xc9, 0x45, 0xe1, 0xc2, 0x9a, 0x64, 0x67, 0x1d, 0x0b, 0xdb, 0x63, 0xec, 0x71, 0xc5, 0x72, 0xcf, - 0x25, 0xd7, 0xbc, 0x02, 0x4f, 0x82, 0x7a, 0xc9, 0x13, 0x20, 0xb4, 0xef, 0xc0, 0x3d, 0x9a, 0x3f, - 0x3b, 0x5b, 0x39, 0x85, 0x15, 0x77, 0x33, 0xc7, 0xe7, 0xfb, 0xe6, 0x9c, 0x99, 0xc9, 0x99, 0x80, - 0x17, 0xb2, 0x49, 0x9a, 0xb1, 0x98, 0xf2, 0x35, 0x2d, 0xf2, 0xc9, 0x2a, 0x0a, 0x69, 0xc2, 0x27, - 0x31, 0xe5, 0x59, 0xb8, 0xca, 0xc7, 0x69, 0xc6, 0x38, 0x43, 0x83, 0x90, 0x8d, 0x2b, 0xce, 0x58, - 0x71, 0xf6, 0x06, 0x01, 0x0b, 0x98, 0x24, 0x4c, 0xc4, 0x48, 0x71, 0xf7, 0x86, 0x01, 0x63, 0x41, - 0x44, 0x27, 0x72, 0xb6, 0x2c, 0xce, 0x27, 0x3c, 0x8c, 0x69, 0xce, 0x49, 0x9c, 0x2a, 0x82, 0xf7, - 0x31, 0x38, 0x5f, 0x93, 0x25, 0x8d, 0x9e, 0x91, 0x30, 0x43, 0x08, 0xec, 0x84, 0xc4, 0xd4, 0xb5, - 0x46, 0xd6, 0xa1, 0x83, 0xe5, 0x18, 0x0d, 0xa0, 0xf9, 0x82, 0x44, 0x05, 0x75, 0x6f, 0x4a, 0x50, - 0x4d, 0xbc, 0x7d, 0x68, 0x9e, 0x92, 0x22, 0xd8, 0xf8, 0x2c, 0x6a, 0x2c, 0xf3, 0xf9, 0x3b, 0x68, - 0xdf, 0x67, 0x45, 0xc2, 0x69, 0x56, 0x4f, 0x40, 0xf7, 0xa0, 0x43, 0x7f, 0xa4, 0x71, 0x1a, 0x91, - 0x4c, 0x36, 0xee, 0x7e, 0x78, 0x30, 0xae, 0xb3, 0x35, 0x3e, 0xd1, 0x2c, 0x5c, 0xf2, 0xbd, 0xcf, - 0xa1, 0xf3, 0x4d, 0x41, 0x12, 0x1e, 0x46, 0x14, 0xed, 0x41, 0xe7, 0x07, 0x3d, 0xd6, 0x0b, 0x94, - 0xf3, 0xab, 0xca, 0x4b, 0x69, 0xbf, 0x58, 0xd0, 0x9e, 0x15, 0x71, 0x4c, 0xb2, 0x0b, 0xf4, 0x36, - 0xec, 0xe4, 0x24, 0x4e, 0x23, 0xea, 0xaf, 0x84, 0x5a, 0xd9, 0xc1, 0xc6, 0x5d, 0x85, 0x49, 0x03, - 0x68, 0x1f, 0x40, 0x53, 0xf2, 0x22, 0xd6, 0x9d, 0x1c, 0x85, 0xcc, 0x8a, 0x18, 0x7d, 0xb9, 0xb1, - 0x7e, 0x63, 0xd4, 0xd8, 0xee, 0xc3, 0x28, 0x3e, 0xb6, 0x5f, 0xfe, 0x39, 0xbc, 0x51, 0xa9, 0xf4, - 0x86, 0xd0, 0x5e, 0x24, 0xfc, 0x22, 0xa5, 0x67, 0x5b, 0xf6, 0xf2, 0x6f, 0x1b, 0x9c, 0x47, 0x61, - 0xce, 0x59, 0x90, 0x91, 0xf8, 0xbf, 0x48, 0x7e, 0x1f, 0xd0, 0x26, 0xc5, 0x3f, 0x8f, 0x18, 0xe1, - 0xae, 0x2d, 0x7b, 0xf6, 0x37, 0x88, 0x0f, 0x05, 0xfe, 0x6f, 0x06, 0xef, 0x41, 0x6b, 0x59, 0xac, - 0xbe, 0xa7, 0x5c, 0xdb, 0x7b, 0xab, 0xde, 0xde, 0xb1, 0xe4, 0x68, 0x73, 0xba, 0x02, 0xdd, 0x81, - 0x56, 0xbe, 0x5a, 0xd3, 0x98, 0xb8, 0xcd, 0x91, 0x75, 0x78, 0x1b, 0xeb, 0x19, 0x7a, 0x07, 0x76, - 0x7f, 0xa2, 0x19, 0xf3, 0xf9, 0x3a, 0xa3, 0xf9, 0x9a, 0x45, 0x67, 0x6e, 0x4b, 0x2e, 0xdb, 0x13, - 0xe8, 0xdc, 0x80, 0x42, 0x99, 0xa4, 0x29, 0xa3, 0x6d, 0x69, 0xd4, 0x11, 0x88, 0xb2, 0x79, 0x08, - 0xfd, 0xea, 0xb3, 0x36, 0xd9, 0x91, 0x7d, 0x76, 0x4b, 0x92, 0xb2, 0xf8, 0x18, 0x7a, 0x09, 0x0d, - 0x08, 0x0f, 0x5f, 0x50, 0x3f, 0x4f, 0x49, 0xe2, 0x3a, 0xd2, 0xca, 0xe8, 0x75, 0x56, 0x66, 0x29, - 0x49, 0xb4, 0x9d, 0x1d, 0x53, 0x2c, 0x30, 0x21, 0xbe, 0x6c, 0x76, 0x46, 0x23, 0x4e, 0x5c, 0x18, - 0x35, 0x0e, 0x11, 0x2e, 0x97, 0x78, 0x20, 0xc0, 0x2b, 0x34, 0x65, 0xa0, 0x3b, 0x6a, 0x08, 0x8f, - 0x06, 0x55, 0x26, 0x1e, 0x43, 0x2f, 0x65, 0x79, 0x58, 0x49, 0xdb, 0xb9, 0x9e, 0x34, 0x53, 0x6c, - 0xa4, 0x95, 0xcd, 0x94, 0xb4, 0x9e, 0x92, 0x66, 0xd0, 0x52, 0x5a, 0x49, 0x53, 0xd2, 0x76, 0x95, - 0x34, 0x83, 0x4a, 0x69, 0xde, 0xef, 0x16, 0xb4, 0xd4, 0x82, 0xe8, 0x5d, 0xe8, 0xaf, 0x8a, 0xb8, - 0x88, 0x36, 0xed, 0xa8, 0x8b, 0x77, 0xab, 0xc2, 0x95, 0xa1, 0xbb, 0x70, 0xe7, 0x55, 0xea, 0x95, - 0x0b, 0x38, 0x78, 0xa5, 0x40, 0x9d, 0xd0, 0x10, 0xba, 0x45, 0x9a, 0xd2, 0xcc, 0x5f, 0xb2, 0x22, - 0x39, 0xd3, 0xb7, 0x10, 0x24, 0x74, 0x2c, 0x90, 0x2b, 0x79, 0xd1, 0xb8, 0x76, 0x5e, 0x40, 0xb5, - 0x71, 0xe2, 0x52, 0xb2, 0xf3, 0xf3, 0x9c, 0x2a, 0x07, 0xb7, 0xb1, 0x9e, 0x09, 0x3c, 0xa2, 0x49, - 0xc0, 0xd7, 0x72, 0xf5, 0x1e, 0xd6, 0x33, 0xef, 0x57, 0x0b, 0x3a, 0xa6, 0x29, 0xfa, 0x0c, 0x9a, - 0x91, 0x48, 0x4b, 0xd7, 0x92, 0xc7, 0x34, 0xac, 0xd7, 0x50, 0x06, 0xaa, 0x3e, 0x25, 0x55, 0x53, - 0x9f, 0x47, 0xe8, 0x53, 0x70, 0xca, 0x4c, 0xd6, 0xd6, 0xf6, 0xc6, 0x2a, 0xb5, 0xc7, 0x26, 0xb5, - 0xc7, 0x73, 0xc3, 0xc0, 0x15, 0xd9, 0xfb, 0xb9, 0x01, 0xad, 0xa9, 0x7c, 0x19, 0xfe, 0x9f, 0xae, - 0x0f, 0xa0, 0x19, 0x88, 0x2c, 0xd7, 0x41, 0xfc, 0x66, 0x7d, 0xb1, 0x8c, 0x7b, 0xac, 0x98, 0xe8, - 0x13, 0x68, 0xaf, 0x54, 0xbe, 0x6b, 0xc9, 0xfb, 0xf5, 0x45, 0xfa, 0x11, 0xc0, 0x86, 0x2d, 0x0a, - 0x73, 0x15, 0xbe, 0xf2, 0x3e, 0x6c, 0x2d, 0xd4, 0x09, 0x8d, 0x0d, 0x5b, 0x14, 0x16, 0x2a, 0x26, - 0x65, 0x98, 0x6c, 0x2d, 0xd4, 0x59, 0x8a, 0x0d, 0x1b, 0x7d, 0x01, 0xce, 0xda, 0xa4, 0xa7, 0x0c, - 0x91, 0xad, 0xdb, 0x53, 0x86, 0x2c, 0xae, 0x2a, 0x44, 0xde, 0x96, 0x3b, 0xee, 0xc7, 0xb9, 0x4c, - 0xaa, 0x06, 0xee, 0x96, 0xd8, 0x34, 0xf7, 0x7e, 0xb3, 0x60, 0x47, 0x9d, 0xc3, 0x43, 0x12, 0x87, - 0xd1, 0x45, 0xed, 0x33, 0x8a, 0xc0, 0x5e, 0xd3, 0x28, 0xd5, 0xaf, 0xa8, 0x1c, 0xa3, 0xbb, 0x60, - 0x0b, 0x8d, 0x72, 0x0b, 0x77, 0xb7, 0xfd, 0xe6, 0x55, 0xe7, 0xf9, 0x45, 0x4a, 0xb1, 0x64, 0x8b, - 0x44, 0x56, 0xff, 0x07, 0x5c, 0xfb, 0x75, 0x89, 0xac, 0xea, 0x4c, 0x22, 0xab, 0x8a, 0xf7, 0x96, - 0x00, 0x55, 0x3f, 0xd4, 0x85, 0xf6, 0xfd, 0xa7, 0x8b, 0x27, 0xf3, 0x13, 0xdc, 0xbf, 0x81, 0x1c, - 0x68, 0x9e, 0x1e, 0x2d, 0x4e, 0x4f, 0xfa, 0x96, 0xc0, 0x67, 0x8b, 0xe9, 0xf4, 0x08, 0x3f, 0xef, - 0xdf, 0x14, 0x93, 0xc5, 0x93, 0xf9, 0xf3, 0x67, 0x27, 0x0f, 0xfa, 0x0d, 0xd4, 0x03, 0xe7, 0xd1, - 0x57, 0xb3, 0xf9, 0xd3, 0x53, 0x7c, 0x34, 0xed, 0xdb, 0xe8, 0x0d, 0xb8, 0x25, 0x6b, 0xfc, 0x0a, - 0x6c, 0x1e, 0x7b, 0x2f, 0x2f, 0x0f, 0xac, 0x3f, 0x2e, 0x0f, 0xac, 0xbf, 0x2e, 0x0f, 0xac, 0x6f, - 0x07, 0x21, 0xf3, 0x2b, 0x71, 0xbe, 0x12, 0xb7, 0x6c, 0xc9, 0x9b, 0xfd, 0xd1, 0x3f, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x52, 0x2d, 0xb5, 0x31, 0xef, 0x08, 0x00, 0x00, + // 963 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x6e, 0x1b, 0x45, + 0x14, 0xee, 0x76, 0xfd, 0x93, 0x3d, 0x8e, 0x93, 0xcd, 0x60, 0x55, 0xab, 0x40, 0x62, 0xb3, 0x12, + 0x52, 0x40, 0xc8, 0x16, 0x50, 0x04, 0x2a, 0x45, 0x22, 0x69, 0xd3, 0x14, 0x15, 0xb7, 0x65, 0x6c, + 0x5f, 0x94, 0x9b, 0xd5, 0xd8, 0x9e, 0xac, 0x57, 0xec, 0xee, 0x2c, 0xfb, 0x53, 0x11, 0xee, 0x79, + 0x06, 0x5e, 0x01, 0xf1, 0x1c, 0x08, 0xf5, 0x92, 0x07, 0x40, 0x08, 0xe5, 0x49, 0xd0, 0xfc, 0xed, + 0x3a, 0xd5, 0xba, 0x90, 0xf6, 0x6e, 0xe6, 0xf3, 0x77, 0xce, 0x7c, 0xe7, 0x9b, 0xf1, 0x39, 0x0b, + 0x6e, 0xc0, 0x46, 0x49, 0xca, 0x22, 0x9a, 0xaf, 0x68, 0x91, 0x8d, 0x16, 0x61, 0x40, 0xe3, 0x7c, + 0x14, 0xd1, 0x3c, 0x0d, 0x16, 0xd9, 0x30, 0x49, 0x59, 0xce, 0x50, 0x2f, 0x60, 0xc3, 0x8a, 0x33, + 0x94, 0x9c, 0xfd, 0x9e, 0xcf, 0x7c, 0x26, 0x08, 0x23, 0xbe, 0x92, 0xdc, 0xfd, 0xbe, 0xcf, 0x98, + 0x1f, 0xd2, 0x91, 0xd8, 0xcd, 0x8b, 0xf3, 0x51, 0x1e, 0x44, 0x34, 0xcb, 0x49, 0x94, 0x48, 0x82, + 0xfb, 0x29, 0x58, 0xdf, 0x90, 0x39, 0x0d, 0x9f, 0x92, 0x20, 0x45, 0x08, 0x1a, 0x31, 0x89, 0xa8, + 0x63, 0x0c, 0x8c, 0x23, 0x0b, 0x8b, 0x35, 0xea, 0x41, 0xf3, 0x39, 0x09, 0x0b, 0xea, 0xdc, 0x14, + 0xa0, 0xdc, 0xb8, 0x07, 0xd0, 0x3c, 0x23, 0x85, 0xbf, 0xf6, 0x33, 0x8f, 0x31, 0xf4, 0xcf, 0xbf, + 0x19, 0xd0, 0xbe, 0xc7, 0x8a, 0x38, 0xa7, 0x69, 0x3d, 0x03, 0xdd, 0x81, 0x2d, 0xfa, 0x23, 0x8d, + 0x92, 0x90, 0xa4, 0x22, 0x73, 0xe7, 0xe3, 0xc3, 0x61, 0x5d, 0x5d, 0xc3, 0x53, 0xc5, 0xc2, 0x25, + 0x1f, 0x8d, 0x61, 0x6f, 0x91, 0x52, 0x92, 0xd3, 0xa5, 0x57, 0x96, 0xe3, 0x98, 0x22, 0xc9, 0xfe, + 0x50, 0x16, 0x3c, 0xd4, 0x05, 0x0f, 0xa7, 0x9a, 0x71, 0xd2, 0x78, 0xf1, 0x77, 0xdf, 0xc0, 0xb6, + 0x0a, 0x2d, 0x71, 0xf7, 0x2e, 0x6c, 0x7d, 0x5b, 0x90, 0x38, 0x0f, 0x42, 0x8a, 0xf6, 0x61, 0xeb, + 0x07, 0xb5, 0x56, 0x7a, 0xcb, 0xfd, 0x55, 0x27, 0xca, 0x52, 0xff, 0x32, 0xa0, 0x3d, 0x29, 0xa2, + 0x88, 0xa4, 0x17, 0xe8, 0x5d, 0xd8, 0xce, 0x48, 0x94, 0x84, 0xd4, 0x5b, 0xf0, 0xe2, 0x45, 0x86, + 0x06, 0xee, 0x48, 0x4c, 0xf8, 0x81, 0x0e, 0x00, 0x14, 0x25, 0x2b, 0x22, 0x95, 0xc9, 0x92, 0xc8, + 0xa4, 0x88, 0xd0, 0x57, 0x6b, 0xe7, 0x9b, 0x03, 0x73, 0xb3, 0x2d, 0x5a, 0xb1, 0xa8, 0xea, 0xc6, + 0x9a, 0xca, 0x5a, 0x73, 0x1a, 0xaf, 0x6d, 0x4e, 0x1f, 0xda, 0xb3, 0x38, 0xbf, 0x48, 0xe8, 0x72, + 0xc3, 0x55, 0xff, 0xde, 0x04, 0xeb, 0x61, 0x90, 0xe5, 0xcc, 0x4f, 0x49, 0xf4, 0x7f, 0x1c, 0xf8, + 0x10, 0xd0, 0x3a, 0xc5, 0x3b, 0x0f, 0x19, 0xc9, 0x85, 0x42, 0x03, 0xdb, 0x6b, 0xc4, 0x07, 0x1c, + 0xff, 0x2f, 0xbf, 0xee, 0x40, 0x6b, 0x5e, 0x2c, 0xbe, 0xa7, 0xb9, 0x72, 0xeb, 0x9d, 0x7a, 0xb7, + 0x4e, 0x04, 0x47, 0x79, 0xa5, 0x22, 0xea, 0x9d, 0xda, 0x7d, 0x5d, 0xa7, 0xd0, 0x2d, 0x68, 0x65, + 0x8b, 0x15, 0x8d, 0x88, 0xd3, 0x1c, 0x18, 0x47, 0x7b, 0x58, 0xed, 0xd0, 0x7b, 0xb0, 0xf3, 0x13, + 0x4d, 0x99, 0x97, 0xaf, 0x52, 0x9a, 0xad, 0x58, 0xb8, 0x74, 0x5a, 0xa2, 0x8a, 0x2e, 0x47, 0xa7, + 0x1a, 0xe4, 0x85, 0x0a, 0x9a, 0xf4, 0xad, 0x2d, 0x7c, 0xb3, 0x38, 0x22, 0x5d, 0x3b, 0x02, 0xbb, + 0xfa, 0x59, 0x79, 0xb6, 0x25, 0xf2, 0xec, 0x94, 0x24, 0xe9, 0xd8, 0x23, 0xe8, 0xc6, 0xd4, 0x27, + 0x79, 0xf0, 0x9c, 0x7a, 0x59, 0x42, 0x62, 0xc7, 0x12, 0xce, 0x0c, 0x5e, 0xe5, 0xcc, 0x24, 0x21, + 0xb1, 0x72, 0x67, 0x5b, 0x07, 0x73, 0x8c, 0x8b, 0x2f, 0x93, 0x2d, 0x69, 0x98, 0x13, 0x07, 0x06, + 0xe6, 0x11, 0xc2, 0xe5, 0x11, 0xf7, 0x39, 0x78, 0x85, 0x26, 0x0b, 0xe8, 0x0c, 0x4c, 0x5e, 0xa3, + 0x46, 0x65, 0x11, 0x8f, 0xa0, 0x9b, 0xb0, 0x2c, 0xa8, 0xa4, 0x6d, 0x5f, 0x4f, 0x9a, 0x0e, 0xd6, + 0xd2, 0xca, 0x64, 0x52, 0x5a, 0x57, 0x4a, 0xd3, 0x68, 0x29, 0xad, 0xa4, 0x49, 0x69, 0x3b, 0x52, + 0x9a, 0x46, 0x85, 0x34, 0xf7, 0x0f, 0x03, 0x5a, 0xf2, 0x40, 0xf4, 0x3e, 0xd8, 0x8b, 0x22, 0x2a, + 0xc2, 0xf5, 0x72, 0xe4, 0x3b, 0xde, 0xad, 0x70, 0x59, 0xd0, 0x6d, 0xb8, 0xf5, 0x32, 0xf5, 0xca, + 0x7b, 0xee, 0xbd, 0x14, 0x20, 0x6f, 0xa8, 0x0f, 0x9d, 0x22, 0x49, 0x68, 0xea, 0xcd, 0x59, 0x11, + 0x2f, 0xd5, 0xa3, 0x06, 0x01, 0x9d, 0x70, 0xe4, 0x4a, 0x73, 0x34, 0xaf, 0xd7, 0x1c, 0xdd, 0xbb, + 0x00, 0x95, 0x71, 0xfc, 0x51, 0xb2, 0xf3, 0xf3, 0x8c, 0xca, 0x0a, 0xf6, 0xb0, 0xda, 0x71, 0x3c, + 0xa4, 0xb1, 0x9f, 0xaf, 0xc4, 0xe9, 0x5d, 0xac, 0x76, 0xee, 0x2f, 0x06, 0x6c, 0xe9, 0xa4, 0xe8, + 0x0b, 0x68, 0x86, 0x7c, 0x36, 0x38, 0x86, 0xb8, 0xa6, 0x7e, 0xbd, 0x86, 0x72, 0x7c, 0xa8, 0x5b, + 0x92, 0x31, 0xf5, 0xdd, 0x12, 0x7d, 0x0e, 0xd6, 0x35, 0x5a, 0x36, 0xae, 0xc8, 0xee, 0xcf, 0x26, + 0xb4, 0xc6, 0x62, 0x0e, 0xbe, 0x99, 0xae, 0x8f, 0xa0, 0xe9, 0xf3, 0xc9, 0xa5, 0xa6, 0xce, 0xdb, + 0xf5, 0xc1, 0x62, 0xb8, 0x61, 0xc9, 0x44, 0x9f, 0x41, 0x7b, 0x21, 0x87, 0x99, 0x92, 0x7c, 0x50, + 0x1f, 0xa4, 0x26, 0x1e, 0xd6, 0x6c, 0x1e, 0x98, 0xc9, 0xd1, 0xa0, 0x3a, 0xf0, 0x86, 0x40, 0x35, + 0x3f, 0xb0, 0x66, 0xf3, 0xc0, 0x42, 0x76, 0x5d, 0xd1, 0x4c, 0x36, 0x06, 0xaa, 0xd6, 0x8c, 0x35, + 0x1b, 0x7d, 0x09, 0xd6, 0x4a, 0x37, 0x63, 0xd1, 0x44, 0x36, 0xda, 0x53, 0xf6, 0x6c, 0x5c, 0x45, + 0xf0, 0xf6, 0x5d, 0x3a, 0xee, 0x45, 0x99, 0xe8, 0x54, 0x26, 0xee, 0x94, 0xd8, 0x38, 0x73, 0x7f, + 0x35, 0x60, 0x5b, 0xde, 0xc3, 0x03, 0x12, 0x05, 0xe1, 0x45, 0xed, 0x47, 0x03, 0x82, 0xc6, 0x8a, + 0x86, 0x89, 0xfa, 0x66, 0x10, 0x6b, 0x74, 0x1b, 0x1a, 0x5c, 0xa3, 0xb0, 0x70, 0x67, 0xd3, 0x7f, + 0x5e, 0x66, 0x9e, 0x5e, 0x24, 0x14, 0x0b, 0x36, 0x6f, 0xf0, 0xf2, 0xeb, 0xc7, 0x69, 0xbc, 0xaa, + 0xc1, 0xcb, 0x38, 0xdd, 0xe0, 0x65, 0xc4, 0x07, 0x73, 0x80, 0x2a, 0x1f, 0xea, 0x40, 0xfb, 0xde, + 0x93, 0xd9, 0xe3, 0xe9, 0x29, 0xb6, 0x6f, 0x20, 0x0b, 0x9a, 0x67, 0xc7, 0xb3, 0xb3, 0x53, 0xdb, + 0xe0, 0xf8, 0x64, 0x36, 0x1e, 0x1f, 0xe3, 0x67, 0xf6, 0x4d, 0xbe, 0x99, 0x3d, 0x9e, 0x3e, 0x7b, + 0x7a, 0x7a, 0xdf, 0x36, 0x51, 0x17, 0xac, 0x87, 0x5f, 0x4f, 0xa6, 0x4f, 0xce, 0xf0, 0xf1, 0xd8, + 0x6e, 0xa0, 0xb7, 0x60, 0x57, 0xc4, 0x78, 0x15, 0xd8, 0x3c, 0x71, 0x5f, 0x5c, 0x1e, 0x1a, 0x7f, + 0x5e, 0x1e, 0x1a, 0xff, 0x5c, 0x1e, 0x1a, 0xdf, 0xf5, 0x02, 0xe6, 0x55, 0xe2, 0x3c, 0x29, 0x6e, + 0xde, 0x12, 0x2f, 0xfb, 0x93, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x68, 0x3f, 0xd9, 0x07, 0xdd, + 0x09, 0x00, 0x00, } func (m *LabelPair) Marshal() (dAtA []byte, err error) { @@ -1100,6 +1127,18 @@ func (m *Counter) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.CreatedTimestamp != nil { + { + size, err := m.CreatedTimestamp.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMetrics(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } if m.Exemplar != nil { { size, err := m.Exemplar.MarshalToSizedBuffer(dAtA[:i]) @@ -1184,6 +1223,18 @@ func (m *Summary) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.CreatedTimestamp != nil { + { + size, err := m.CreatedTimestamp.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMetrics(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } if len(m.Quantile) > 0 { for iNdEx := len(m.Quantile) - 1; iNdEx >= 0; iNdEx-- { { @@ -1269,32 +1320,44 @@ func (m *Histogram) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.CreatedTimestamp != nil { + { + size, err := m.CreatedTimestamp.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintMetrics(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } if len(m.PositiveCount) > 0 { for iNdEx := len(m.PositiveCount) - 1; iNdEx >= 0; iNdEx-- { - f2 := math.Float64bits(float64(m.PositiveCount[iNdEx])) + f5 := math.Float64bits(float64(m.PositiveCount[iNdEx])) i -= 8 - encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(f2)) + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(f5)) } i = encodeVarintMetrics(dAtA, i, uint64(len(m.PositiveCount)*8)) i-- dAtA[i] = 0x72 } if len(m.PositiveDelta) > 0 { - var j3 int - dAtA5 := make([]byte, len(m.PositiveDelta)*10) + var j6 int + dAtA8 := make([]byte, len(m.PositiveDelta)*10) for _, num := range m.PositiveDelta { - x4 := (uint64(num) << 1) ^ uint64((num >> 63)) - for x4 >= 1<<7 { - dAtA5[j3] = uint8(uint64(x4)&0x7f | 0x80) - j3++ - x4 >>= 7 + x7 := (uint64(num) << 1) ^ uint64((num >> 63)) + for x7 >= 1<<7 { + dAtA8[j6] = uint8(uint64(x7)&0x7f | 0x80) + j6++ + x7 >>= 7 } - dAtA5[j3] = uint8(x4) - j3++ + dAtA8[j6] = uint8(x7) + j6++ } - i -= j3 - copy(dAtA[i:], dAtA5[:j3]) - i = encodeVarintMetrics(dAtA, i, uint64(j3)) + i -= j6 + copy(dAtA[i:], dAtA8[:j6]) + i = encodeVarintMetrics(dAtA, i, uint64(j6)) i-- dAtA[i] = 0x6a } @@ -1314,30 +1377,30 @@ func (m *Histogram) MarshalToSizedBuffer(dAtA []byte) (int, error) { } if len(m.NegativeCount) > 0 { for iNdEx := len(m.NegativeCount) - 1; iNdEx >= 0; iNdEx-- { - f6 := math.Float64bits(float64(m.NegativeCount[iNdEx])) + f9 := math.Float64bits(float64(m.NegativeCount[iNdEx])) i -= 8 - encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(f6)) + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(f9)) } i = encodeVarintMetrics(dAtA, i, uint64(len(m.NegativeCount)*8)) i-- dAtA[i] = 0x5a } if len(m.NegativeDelta) > 0 { - var j7 int - dAtA9 := make([]byte, len(m.NegativeDelta)*10) + var j10 int + dAtA12 := make([]byte, len(m.NegativeDelta)*10) for _, num := range m.NegativeDelta { - x8 := (uint64(num) << 1) ^ uint64((num >> 63)) - for x8 >= 1<<7 { - dAtA9[j7] = uint8(uint64(x8)&0x7f | 0x80) - j7++ - x8 >>= 7 + x11 := (uint64(num) << 1) ^ uint64((num >> 63)) + for x11 >= 1<<7 { + dAtA12[j10] = uint8(uint64(x11)&0x7f | 0x80) + j10++ + x11 >>= 7 } - dAtA9[j7] = uint8(x8) - j7++ + dAtA12[j10] = uint8(x11) + j10++ } - i -= j7 - copy(dAtA[i:], dAtA9[:j7]) - i = encodeVarintMetrics(dAtA, i, uint64(j7)) + i -= j10 + copy(dAtA[i:], dAtA12[:j10]) + i = encodeVarintMetrics(dAtA, i, uint64(j10)) i-- dAtA[i] = 0x52 } @@ -1788,6 +1851,10 @@ func (m *Counter) Size() (n int) { l = m.Exemplar.Size() n += 1 + l + sovMetrics(uint64(l)) } + if m.CreatedTimestamp != nil { + l = m.CreatedTimestamp.Size() + n += 1 + l + sovMetrics(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -1830,6 +1897,10 @@ func (m *Summary) Size() (n int) { n += 1 + l + sovMetrics(uint64(l)) } } + if m.CreatedTimestamp != nil { + l = m.CreatedTimestamp.Size() + n += 1 + l + sovMetrics(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -1916,6 +1987,10 @@ func (m *Histogram) Size() (n int) { if len(m.PositiveCount) > 0 { n += 1 + sovMetrics(uint64(len(m.PositiveCount)*8)) + len(m.PositiveCount)*8 } + if m.CreatedTimestamp != nil { + l = m.CreatedTimestamp.Size() + n += 1 + l + sovMetrics(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -2319,6 +2394,42 @@ func (m *Counter) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CreatedTimestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMetrics + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CreatedTimestamp == nil { + m.CreatedTimestamp = &types.Timestamp{} + } + if err := m.CreatedTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMetrics(dAtA[iNdEx:]) @@ -2507,6 +2618,42 @@ func (m *Summary) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CreatedTimestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMetrics + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CreatedTimestamp == nil { + m.CreatedTimestamp = &types.Timestamp{} + } + if err := m.CreatedTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMetrics(dAtA[iNdEx:]) @@ -3089,6 +3236,42 @@ func (m *Histogram) Unmarshal(dAtA []byte) error { } else { return fmt.Errorf("proto: wrong wireType = %d for field PositiveCount", wireType) } + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CreatedTimestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthMetrics + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CreatedTimestamp == nil { + m.CreatedTimestamp = &types.Timestamp{} + } + if err := m.CreatedTimestamp.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMetrics(dAtA[iNdEx:]) diff --git a/prompb/io/prometheus/client/metrics.proto b/prompb/io/prometheus/client/metrics.proto index 3fef2b6d00..8e225bb3b9 100644 --- a/prompb/io/prometheus/client/metrics.proto +++ b/prompb/io/prometheus/client/metrics.proto @@ -51,6 +51,8 @@ message Gauge { message Counter { double value = 1; Exemplar exemplar = 2; + + google.protobuf.Timestamp created_timestamp = 3 [(gogoproto.nullable) = true]; } message Quantile { @@ -62,6 +64,8 @@ message Summary { uint64 sample_count = 1; double sample_sum = 2; repeated Quantile quantile = 3 [(gogoproto.nullable) = false]; + + google.protobuf.Timestamp created_timestamp = 4 [(gogoproto.nullable) = true]; } message Untyped { @@ -75,6 +79,8 @@ message Histogram { // Buckets for the conventional histogram. repeated Bucket bucket = 3 [(gogoproto.nullable) = false]; // Ordered in increasing order of upper_bound, +Inf bucket is optional. + google.protobuf.Timestamp created_timestamp = 15 [(gogoproto.nullable) = true]; + // Everything below here is for native histograms (also known as sparse histograms). // Native histograms are an experimental feature without stability guarantees. @@ -147,4 +153,4 @@ message MetricFamily { string help = 2; MetricType type = 3; repeated Metric metric = 4 [(gogoproto.nullable) = false]; -} +} \ No newline at end of file From 02680b42f660b8a1cd219e8194045340e3e5996f Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Tue, 10 Oct 2023 10:05:21 +0200 Subject: [PATCH 54/55] tsdb: Avoid potential overflow in comparisons Signed-off-by: Arve Knudsen --- tsdb/index/postingsstats.go | 11 ++++++++++- tsdb/ooo_head_read.go | 34 ++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/tsdb/index/postingsstats.go b/tsdb/index/postingsstats.go index 70622b3d27..0ad4e08575 100644 --- a/tsdb/index/postingsstats.go +++ b/tsdb/index/postingsstats.go @@ -63,6 +63,15 @@ func (m *maxHeap) push(item Stat) { } func (m *maxHeap) get() []Stat { - slices.SortFunc(m.Items, func(a, b Stat) int { return int(b.Count - a.Count) }) + slices.SortFunc(m.Items, func(a, b Stat) int { + switch { + case b.Count < a.Count: + return -1 + case b.Count > a.Count: + return 1 + default: + return 0 + } + }) return m.Items } diff --git a/tsdb/ooo_head_read.go b/tsdb/ooo_head_read.go index 186f466331..7b24d8c20a 100644 --- a/tsdb/ooo_head_read.go +++ b/tsdb/ooo_head_read.go @@ -184,17 +184,39 @@ type chunkMetaAndChunkDiskMapperRef struct { } func refLessByMinTimeAndMinRef(a, b chunkMetaAndChunkDiskMapperRef) int { - if a.meta.MinTime == b.meta.MinTime { - return int(a.meta.Ref - b.meta.Ref) + switch { + case a.meta.MinTime < b.meta.MinTime: + return -1 + case a.meta.MinTime > b.meta.MinTime: + return 1 + } + + switch { + case a.meta.Ref < b.meta.Ref: + return -1 + case a.meta.Ref > b.meta.Ref: + return 1 + default: + return 0 } - return int(a.meta.MinTime - b.meta.MinTime) } func lessByMinTimeAndMinRef(a, b chunks.Meta) int { - if a.MinTime == b.MinTime { - return int(a.Ref - b.Ref) + switch { + case a.MinTime < b.MinTime: + return -1 + case a.MinTime > b.MinTime: + return 1 + } + + switch { + case a.Ref < b.Ref: + return -1 + case a.Ref > b.Ref: + return 1 + default: + return 0 } - return int(a.MinTime - b.MinTime) } func (oh *OOOHeadIndexReader) Postings(ctx context.Context, name string, values ...string) (index.Postings, error) { From 4e5bb43fed7d4c3d9e918fac70e16fbb7796bfd8 Mon Sep 17 00:00:00 2001 From: Arve Knudsen Date: Tue, 10 Oct 2023 10:26:03 +0200 Subject: [PATCH 55/55] tsdb: Avoid potential overflow in comparisons Signed-off-by: Arve Knudsen --- cmd/promtool/tsdb.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd/promtool/tsdb.go b/cmd/promtool/tsdb.go index 85aeacc11e..60dd3e3bdb 100644 --- a/cmd/promtool/tsdb.go +++ b/cmd/promtool/tsdb.go @@ -459,7 +459,16 @@ func analyzeBlock(ctx context.Context, path, blockID string, limit int, runExten postingInfos := []postingInfo{} printInfo := func(postingInfos []postingInfo) { - slices.SortFunc(postingInfos, func(a, b postingInfo) int { return int(b.metric) - int(a.metric) }) + slices.SortFunc(postingInfos, func(a, b postingInfo) int { + switch { + case b.metric < a.metric: + return -1 + case b.metric > a.metric: + return 1 + default: + return 0 + } + }) for i, pc := range postingInfos { if i >= limit {
+

{g.name}

+

Interval: {humanizeDuration(parseFloat(g.interval) * 1000)}

+

{formatRelative(g.lastEvaluation, now())}