diff --git a/.golangci.yml b/.golangci.yml index 2b7f7b0004..5d15bc33a3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,7 +17,8 @@ linters: - loggercheck - misspell - nilnesserr - - nolintlint + # TODO(bwplotka): Enable once https://github.com/golangci/golangci-lint/issues/3228 is fixed. + # - nolintlint - perfsprint - predeclared - revive @@ -157,7 +158,6 @@ linters-settings: - name: unexported-return - name: unreachable-code - name: unused-parameter - disabled: true - name: var-declaration - name: var-naming testifylint: diff --git a/.promu.yml b/.promu.yml index 6feaa6ef64..23379cc1ef 100644 --- a/.promu.yml +++ b/.promu.yml @@ -1,7 +1,7 @@ go: # Whenever the Go version is updated here, # .github/workflows should also be updated. - version: 1.23 + version: 1.24 repository: path: github.com/prometheus/prometheus build: diff --git a/CHANGELOG.md b/CHANGELOG.md index 2adad6059c..f1e7483860 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,32 @@ ## unreleased +* [CHANGE] Make setting out-of-order native histograms feature (`--enable-feature=ooo-native-histograms`) a no-op. Out-of-order native histograms are now always enabled when `out_of_order_time_window` is greater than zero and `--enable-feature=native-histograms` is set. #16207 * [ENHANCEMENT] TSDB: add `prometheus_tsdb_wal_replay_unknown_refs_total` and `prometheus_tsdb_wbl_replay_unknown_refs_total` metrics to track unknown series references during WAL/WBL replay. #16166 * [BUGFIX] TSDB: fix unknown series errors and possible lost data during WAL replay when series are removed from the head due to inactivity and reappear before the next WAL checkpoint. #16060 + +## 3.2.1 / 2025-02-25 + +* [BUGFIX] Don't send Accept` header `escape=allow-utf-8` when `metric_name_validation_scheme: legacy` is configured. #16061 + +## 3.2.0 / 2025-02-17 + +* [CHANGE] relabel: Replace actions can now use UTF-8 characters in `targetLabel` field. Note that `$` or `${}` will be expanded. This also apply to `replacement` field for `LabelMap` action. #15851 +* [CHANGE] rulefmt: Rule names can use UTF-8 characters, except `{` and `}` characters (due to common mistake checks). #15851 +* [FEATURE] remote/otlp: Add feature flag `otlp-deltatocumulative` to support conversion from delta to cumulative. #15165 +* [ENHANCEMENT] openstack SD: Discover Octavia loadbalancers. #15539 +* [ENHANCEMENT] scrape: Add metadata for automatic metrics to WAL for `metadata-wal-records` feature. #15837 * [ENHANCEMENT] promtool: Support linting of scrape interval, through lint option `too-long-scrape-interval`. #15719 +* [ENHANCEMENT] promtool: Add --ignore-unknown-fields option. #15706 +* [ENHANCEMENT] ui: Make "hide empty rules" and hide empty rules" persistent #15807 +* [ENHANCEMENT] web/api: Add a limit parameter to `/query` and `/query_range`. #15552 +* [ENHANCEMENT] api: Add fields Node and ServerTime to `/status`. #15784 +* [PERF] Scraping: defer computing labels for dropped targets until they are needed by the UI. #15261 +* [BUGFIX] remotewrite2: Fix invalid metadata bug for metrics without metadata. #15829 +* [BUGFIX] remotewrite2: Fix the unit field propagation. #15825 +* [BUGFIX] scrape: Fix WAL metadata for histograms and summaries. #15832 +* [BUGFIX] ui: Merge duplicate "Alerts page settings" sections. #15810 +* [BUGFIX] PromQL: Fix `` functions with histograms. #15711 ## 3.1.0 / 2025-01-02 diff --git a/Dockerfile b/Dockerfile index 1e46a62f95..31e863d8a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ COPY NOTICE /NOTICE COPY npm_licenses.tar.bz2 /npm_licenses.tar.bz2 WORKDIR /prometheus -RUN chown -R nobody:nobody /etc/prometheus /prometheus +RUN chown -R nobody:nobody /etc/prometheus /prometheus && chmod g+w /prometheus USER nobody EXPOSE 9090 diff --git a/Makefile.common b/Makefile.common index e8832656ab..668b778d78 100644 --- a/Makefile.common +++ b/Makefile.common @@ -61,7 +61,7 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_ SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.63.4 +GOLANGCI_LINT_VERSION ?= v1.64.6 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) diff --git a/README.md b/README.md index 658cee4640..a027328e20 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,8 @@ Prometheus will now be reachable at . To build Prometheus from source code, You need: * Go [version 1.22 or greater](https://golang.org/doc/install). -* NodeJS [version 16 or greater](https://nodejs.org/). -* npm [version 7 or greater](https://www.npmjs.com/). +* NodeJS [version 22 or greater](https://nodejs.org/). +* npm [version 8 or greater](https://www.npmjs.com/). Start by cloning the repository: diff --git a/VERSION b/VERSION index fd2a01863f..e4604e3afd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.0 +3.2.1 diff --git a/cmd/prometheus/main.go b/cmd/prometheus/main.go index d69648d88b..0e9d7c1d78 100644 --- a/cmd/prometheus/main.go +++ b/cmd/prometheus/main.go @@ -73,7 +73,7 @@ import ( "github.com/prometheus/prometheus/tracing" "github.com/prometheus/prometheus/tsdb" "github.com/prometheus/prometheus/tsdb/agent" - "github.com/prometheus/prometheus/tsdb/wlog" + "github.com/prometheus/prometheus/util/compression" "github.com/prometheus/prometheus/util/documentcli" "github.com/prometheus/prometheus/util/logging" "github.com/prometheus/prometheus/util/notifications" @@ -140,8 +140,10 @@ var ( ) func init() { - // This can be removed when the default validation scheme in common is updated. + // This can be removed when the legacy global mode is fully deprecated. + //nolint:staticcheck model.NameValidationScheme = model.UTF8Validation + prometheus.MustRegister(versioncollector.NewCollector(strings.ReplaceAll(appName, "-", "_"))) var err error @@ -154,7 +156,7 @@ func init() { // serverOnlyFlag creates server-only kingpin flag. func serverOnlyFlag(app *kingpin.Application, name, help string) *kingpin.FlagClause { return app.Flag(name, fmt.Sprintf("%s Use with server mode only.", help)). - PreAction(func(parseContext *kingpin.ParseContext) error { + PreAction(func(_ *kingpin.ParseContext) error { // This will be invoked only if flag is actually provided by user. serverOnlyFlags = append(serverOnlyFlags, "--"+name) return nil @@ -164,7 +166,7 @@ func serverOnlyFlag(app *kingpin.Application, name, help string) *kingpin.FlagCl // agentOnlyFlag creates agent-only kingpin flag. func agentOnlyFlag(app *kingpin.Application, name, help string) *kingpin.FlagClause { return app.Flag(name, fmt.Sprintf("%s Use with agent mode only.", help)). - PreAction(func(parseContext *kingpin.ParseContext) error { + PreAction(func(_ *kingpin.ParseContext) error { // This will be invoked only if flag is actually provided by user. agentOnlyFlags = append(agentOnlyFlags, "--"+name) return nil @@ -255,8 +257,7 @@ func (c *flagConfig) setFeatureListOptions(logger *slog.Logger) error { config.DefaultGlobalConfig.ScrapeProtocols = config.DefaultProtoFirstScrapeProtocols logger.Info("Experimental native histogram support enabled. Changed default scrape_protocols to prefer PrometheusProto format.", "global.scrape_protocols", fmt.Sprintf("%v", config.DefaultGlobalConfig.ScrapeProtocols)) case "ooo-native-histograms": - c.tsdb.EnableOOONativeHistograms = true - logger.Info("Experimental out-of-order native histogram ingestion enabled. This will only take effect if OutOfOrderTimeWindow is > 0 and if EnableNativeHistograms = true") + logger.Warn("This option for --enable-feature is now permanently enabled and therefore a no-op.", "option", o) case "created-timestamp-zero-ingestion": c.scrape.EnableCreatedTimestampZeroIngestion = true c.web.CTZeroIngestionEnabled = true @@ -287,6 +288,14 @@ func (c *flagConfig) setFeatureListOptions(logger *slog.Logger) error { return nil } +// parseCompressionType parses the two compression-related configuration values and returns the CompressionType. +func parseCompressionType(compress bool, compressType compression.Type) compression.Type { + if compress { + return compressType + } + return compression.None +} + func main() { if os.Getenv("DEBUG") != "" { runtime.SetBlockProfileRate(20) @@ -425,11 +434,15 @@ func main() { serverOnlyFlag(a, "storage.tsdb.allow-overlapping-compaction", "Allow compaction of overlapping blocks. If set to false, TSDB stops vertical compaction and leaves overlapping blocks there. The use case is to let another component handle the compaction of overlapping blocks."). Default("true").Hidden().BoolVar(&cfg.tsdb.EnableOverlappingCompaction) - serverOnlyFlag(a, "storage.tsdb.wal-compression", "Compress the tsdb WAL."). - Hidden().Default("true").BoolVar(&cfg.tsdb.WALCompression) + var ( + tsdbWALCompression bool + tsdbWALCompressionType string + ) + serverOnlyFlag(a, "storage.tsdb.wal-compression", "Compress the tsdb WAL. If false, the --storage.tsdb.wal-compression-type flag is ignored."). + Hidden().Default("true").BoolVar(&tsdbWALCompression) - serverOnlyFlag(a, "storage.tsdb.wal-compression-type", "Compression algorithm for the tsdb WAL."). - Hidden().Default(string(wlog.CompressionSnappy)).EnumVar(&cfg.tsdb.WALCompressionType, string(wlog.CompressionSnappy), string(wlog.CompressionZstd)) + serverOnlyFlag(a, "storage.tsdb.wal-compression-type", "Compression algorithm for the tsdb WAL, used when --storage.tsdb.wal-compression is true."). + Hidden().Default(compression.Snappy).EnumVar(&tsdbWALCompressionType, compression.Snappy, compression.Zstd) serverOnlyFlag(a, "storage.tsdb.head-chunks-write-queue-size", "Size of the queue through which head chunks are written to the disk to be m-mapped, 0 disables the queue completely. Experimental."). Default("0").IntVar(&cfg.tsdb.HeadChunksWriteQueueSize) @@ -447,11 +460,15 @@ func main() { "Size at which to split WAL segment files. Example: 100MB"). Hidden().PlaceHolder("").BytesVar(&cfg.agent.WALSegmentSize) - agentOnlyFlag(a, "storage.agent.wal-compression", "Compress the agent WAL."). - Default("true").BoolVar(&cfg.agent.WALCompression) + var ( + agentWALCompression bool + agentWALCompressionType string + ) + agentOnlyFlag(a, "storage.agent.wal-compression", "Compress the agent WAL. If false, the --storage.agent.wal-compression-type flag is ignored."). + Default("true").BoolVar(&agentWALCompression) - agentOnlyFlag(a, "storage.agent.wal-compression-type", "Compression algorithm for the agent WAL."). - Hidden().Default(string(wlog.CompressionSnappy)).EnumVar(&cfg.agent.WALCompressionType, string(wlog.CompressionSnappy), string(wlog.CompressionZstd)) + agentOnlyFlag(a, "storage.agent.wal-compression-type", "Compression algorithm for the agent WAL, used when --storage.agent.wal-compression is true."). + Hidden().Default(compression.Snappy).EnumVar(&agentWALCompressionType, compression.Snappy, compression.Zstd) agentOnlyFlag(a, "storage.agent.wal-truncate-frequency", "The frequency at which to truncate the WAL and remove old data."). @@ -526,7 +543,7 @@ func main() { promslogflag.AddFlags(a, &cfg.promslogConfig) - a.Flag("write-documentation", "Generate command line documentation. Internal use.").Hidden().Action(func(ctx *kingpin.ParseContext) error { + a.Flag("write-documentation", "Generate command line documentation. Internal use.").Hidden().Action(func(_ *kingpin.ParseContext) error { if err := documentcli.GenerateMarkdown(a.Model(), os.Stdout); err != nil { os.Exit(1) return err @@ -669,6 +686,10 @@ func main() { logger.Warn("The --storage.tsdb.delayed-compaction.max-percent should have a value between 1 and 100. Using default", "default", tsdb.DefaultCompactionDelayMaxPercent) cfg.tsdb.CompactionDelayMaxPercent = tsdb.DefaultCompactionDelayMaxPercent } + + cfg.tsdb.WALCompressionType = parseCompressionType(tsdbWALCompression, tsdbWALCompressionType) + } else { + cfg.agent.WALCompressionType = parseCompressionType(agentWALCompression, agentWALCompressionType) } noStepSubqueryInterval := &safePromQLNoStepSubqueryInterval{} @@ -1021,7 +1042,7 @@ func main() { } return nil }, - func(err error) { + func(_ error) { close(cancel) webHandler.SetReady(web.Stopping) notifs.AddNotification(notifications.ShuttingDown) @@ -1036,7 +1057,7 @@ func main() { logger.Info("Scrape discovery manager stopped") return err }, - func(err error) { + func(_ error) { logger.Info("Stopping scrape discovery manager...") cancelScrape() }, @@ -1050,7 +1071,7 @@ func main() { logger.Info("Notify discovery manager stopped") return err }, - func(err error) { + func(_ error) { logger.Info("Stopping notify discovery manager...") cancelNotify() }, @@ -1064,7 +1085,7 @@ func main() { ruleManager.Run() return nil }, - func(err error) { + func(_ error) { ruleManager.Stop() }, ) @@ -1083,7 +1104,7 @@ func main() { logger.Info("Scrape manager stopped") return err }, - func(err error) { + func(_ error) { // Scrape manager needs to be stopped before closing the local TSDB // so that it doesn't try to write samples to a closed storage. // We should also wait for rule manager to be fully stopped to ensure @@ -1101,7 +1122,7 @@ func main() { tracingManager.Run() return nil }, - func(err error) { + func(_ error) { tracingManager.Stop() }, ) @@ -1182,7 +1203,7 @@ func main() { } } }, - func(err error) { + func(_ error) { // Wait for any in-progress reloads to complete to avoid // reloading things after they have been shutdown. cancel <- struct{}{} @@ -1214,7 +1235,7 @@ func main() { <-cancel return nil }, - func(err error) { + func(_ error) { close(cancel) }, ) @@ -1257,7 +1278,7 @@ func main() { "NoLockfile", cfg.tsdb.NoLockfile, "RetentionDuration", cfg.tsdb.RetentionDuration, "WALSegmentSize", cfg.tsdb.WALSegmentSize, - "WALCompression", cfg.tsdb.WALCompression, + "WALCompressionType", cfg.tsdb.WALCompressionType, ) startTimeMargin := int64(2 * time.Duration(cfg.tsdb.MinBlockDuration).Seconds() * 1000) @@ -1267,7 +1288,7 @@ func main() { <-cancel return nil }, - func(err error) { + func(_ error) { if err := fanoutStorage.Close(); err != nil { logger.Error("Error stopping storage", "err", err) } @@ -1308,7 +1329,7 @@ func main() { logger.Info("Agent WAL storage started") logger.Debug("Agent WAL storage options", "WALSegmentSize", cfg.agent.WALSegmentSize, - "WALCompression", cfg.agent.WALCompression, + "WALCompressionType", cfg.agent.WALCompressionType, "StripeSize", cfg.agent.StripeSize, "TruncateFrequency", cfg.agent.TruncateFrequency, "MinWALTime", cfg.agent.MinWALTime, @@ -1322,7 +1343,7 @@ func main() { <-cancel return nil }, - func(e error) { + func(_ error) { if err := fanoutStorage.Close(); err != nil { logger.Error("Error stopping storage", "err", err) } @@ -1339,7 +1360,7 @@ func main() { } return nil }, - func(err error) { + func(_ error) { cancelWeb() }, ) @@ -1361,7 +1382,7 @@ func main() { logger.Info("Notifier manager stopped") return nil }, - func(err error) { + func(_ error) { notifierManager.Stop() }, ) @@ -1638,29 +1659,29 @@ func (s *readyStorage) Appender(ctx context.Context) storage.Appender { type notReadyAppender struct{} // SetOptions does nothing in this appender implementation. -func (n notReadyAppender) SetOptions(opts *storage.AppendOptions) {} +func (n notReadyAppender) SetOptions(_ *storage.AppendOptions) {} -func (n notReadyAppender) Append(ref storage.SeriesRef, l labels.Labels, t int64, v float64) (storage.SeriesRef, error) { +func (n notReadyAppender) Append(_ storage.SeriesRef, _ labels.Labels, _ int64, _ float64) (storage.SeriesRef, error) { return 0, tsdb.ErrNotReady } -func (n notReadyAppender) AppendExemplar(ref storage.SeriesRef, l labels.Labels, e exemplar.Exemplar) (storage.SeriesRef, error) { +func (n notReadyAppender) AppendExemplar(_ storage.SeriesRef, _ labels.Labels, _ exemplar.Exemplar) (storage.SeriesRef, error) { return 0, tsdb.ErrNotReady } -func (n notReadyAppender) AppendHistogram(ref storage.SeriesRef, l labels.Labels, t int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { +func (n notReadyAppender) AppendHistogram(_ storage.SeriesRef, _ labels.Labels, _ int64, _ *histogram.Histogram, _ *histogram.FloatHistogram) (storage.SeriesRef, error) { return 0, tsdb.ErrNotReady } -func (n notReadyAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, l labels.Labels, t, ct int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { +func (n notReadyAppender) AppendHistogramCTZeroSample(_ storage.SeriesRef, _ labels.Labels, _, _ int64, _ *histogram.Histogram, _ *histogram.FloatHistogram) (storage.SeriesRef, error) { return 0, tsdb.ErrNotReady } -func (n notReadyAppender) UpdateMetadata(ref storage.SeriesRef, l labels.Labels, m metadata.Metadata) (storage.SeriesRef, error) { +func (n notReadyAppender) UpdateMetadata(_ storage.SeriesRef, _ labels.Labels, _ metadata.Metadata) (storage.SeriesRef, error) { return 0, tsdb.ErrNotReady } -func (n notReadyAppender) AppendCTZeroSample(ref storage.SeriesRef, l labels.Labels, t, ct int64) (storage.SeriesRef, error) { +func (n notReadyAppender) AppendCTZeroSample(_ storage.SeriesRef, _ labels.Labels, _, _ int64) (storage.SeriesRef, error) { return 0, tsdb.ErrNotReady } @@ -1781,8 +1802,7 @@ type tsdbOptions struct { RetentionDuration model.Duration MaxBytes units.Base2Bytes NoLockfile bool - WALCompression bool - WALCompressionType string + WALCompressionType compression.Type HeadChunksWriteQueueSize int SamplesPerChunk int StripeSize int @@ -1796,7 +1816,6 @@ type tsdbOptions struct { EnableDelayedCompaction bool CompactionDelayMaxPercent int EnableOverlappingCompaction bool - EnableOOONativeHistograms bool } func (opts tsdbOptions) ToTSDBOptions() tsdb.Options { @@ -1806,7 +1825,7 @@ func (opts tsdbOptions) ToTSDBOptions() tsdb.Options { RetentionDuration: int64(time.Duration(opts.RetentionDuration) / time.Millisecond), MaxBytes: int64(opts.MaxBytes), NoLockfile: opts.NoLockfile, - WALCompression: wlog.ParseCompressionType(opts.WALCompression, opts.WALCompressionType), + WALCompression: opts.WALCompressionType, HeadChunksWriteQueueSize: opts.HeadChunksWriteQueueSize, SamplesPerChunk: opts.SamplesPerChunk, StripeSize: opts.StripeSize, @@ -1816,7 +1835,6 @@ func (opts tsdbOptions) ToTSDBOptions() tsdb.Options { MaxExemplars: opts.MaxExemplars, EnableMemorySnapshotOnShutdown: opts.EnableMemorySnapshotOnShutdown, EnableNativeHistograms: opts.EnableNativeHistograms, - EnableOOONativeHistograms: opts.EnableOOONativeHistograms, OutOfOrderTimeWindow: opts.OutOfOrderTimeWindow, EnableDelayedCompaction: opts.EnableDelayedCompaction, CompactionDelayMaxPercent: opts.CompactionDelayMaxPercent, @@ -1828,8 +1846,7 @@ func (opts tsdbOptions) ToTSDBOptions() tsdb.Options { // as agent.Option fields are unit agnostic (time). type agentOptions struct { WALSegmentSize units.Base2Bytes - WALCompression bool - WALCompressionType string + WALCompressionType compression.Type StripeSize int TruncateFrequency model.Duration MinWALTime, MaxWALTime model.Duration @@ -1843,7 +1860,7 @@ func (opts agentOptions) ToAgentOptions(outOfOrderTimeWindow int64) agent.Option } return agent.Options{ WALSegmentSize: int(opts.WALSegmentSize), - WALCompression: wlog.ParseCompressionType(opts.WALCompression, opts.WALCompressionType), + WALCompression: opts.WALCompressionType, StripeSize: opts.StripeSize, TruncateFrequency: time.Duration(opts.TruncateFrequency), MinWALTime: durationToInt64Millis(time.Duration(opts.MinWALTime)), diff --git a/cmd/prometheus/main_test.go b/cmd/prometheus/main_test.go index 4bd1c71b2d..0d0ab56eb4 100644 --- a/cmd/prometheus/main_test.go +++ b/cmd/prometheus/main_test.go @@ -26,6 +26,7 @@ import ( "runtime" "strconv" "strings" + "sync" "syscall" "testing" "time" @@ -43,7 +44,8 @@ import ( ) func init() { - // This can be removed when the default validation scheme in common is updated. + // This can be removed when the legacy global mode is fully deprecated. + //nolint:staticcheck model.NameValidationScheme = model.UTF8Validation } @@ -246,7 +248,14 @@ func TestWALSegmentSizeBounds(t *testing.T) { // Log stderr in case of failure. stderr, err := prom.StderrPipe() require.NoError(t, err) + + // WaitGroup is used to ensure that we don't call t.Log() after the test has finished. + var wg sync.WaitGroup + wg.Add(1) + defer wg.Wait() + go func() { + defer wg.Done() slurp, _ := io.ReadAll(stderr) t.Log(string(slurp)) }() @@ -303,7 +312,14 @@ func TestMaxBlockChunkSegmentSizeBounds(t *testing.T) { // Log stderr in case of failure. stderr, err := prom.StderrPipe() require.NoError(t, err) + + // WaitGroup is used to ensure that we don't call t.Log() after the test has finished. + var wg sync.WaitGroup + wg.Add(1) + defer wg.Wait() + go func() { + defer wg.Done() slurp, _ := io.ReadAll(stderr) t.Log(string(slurp)) }() @@ -497,7 +513,14 @@ func TestModeSpecificFlags(t *testing.T) { // Log stderr in case of failure. stderr, err := prom.StderrPipe() require.NoError(t, err) + + // WaitGroup is used to ensure that we don't call t.Log() after the test has finished. + var wg sync.WaitGroup + wg.Add(1) + defer wg.Wait() + go func() { + defer wg.Done() slurp, _ := io.ReadAll(stderr) t.Log(string(slurp)) }() diff --git a/cmd/prometheus/scrape_failure_log_test.go b/cmd/prometheus/scrape_failure_log_test.go index 8d86d719f9..e04b1aaa2d 100644 --- a/cmd/prometheus/scrape_failure_log_test.go +++ b/cmd/prometheus/scrape_failure_log_test.go @@ -171,7 +171,7 @@ func reloadPrometheus(t *testing.T, port int) { // startGarbageServer sets up a mock server that returns a 500 Internal Server Error // for all requests. It also increments the request count each time it's hit. func startGarbageServer(t *testing.T, requestCount *atomic.Int32) string { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { requestCount.Inc() w.WriteHeader(http.StatusInternalServerError) })) diff --git a/cmd/promtool/backfill.go b/cmd/promtool/backfill.go index 473ea036ec..0964f0d546 100644 --- a/cmd/promtool/backfill.go +++ b/cmd/promtool/backfill.go @@ -21,7 +21,7 @@ import ( "math" "time" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/common/promslog" diff --git a/cmd/promtool/backfill_test.go b/cmd/promtool/backfill_test.go index da64b5dca1..8a599510a9 100644 --- a/cmd/promtool/backfill_test.go +++ b/cmd/promtool/backfill_test.go @@ -45,7 +45,7 @@ func sortSamples(samples []backfillSample) { }) } -func queryAllSeries(t testing.TB, q storage.Querier, expectedMinTime, expectedMaxTime int64) []backfillSample { +func queryAllSeries(t testing.TB, q storage.Querier, _, _ int64) []backfillSample { ss := q.Select(context.Background(), false, nil, labels.MustNewMatcher(labels.MatchRegexp, "", ".*")) samples := []backfillSample{} for ss.Next() { diff --git a/cmd/promtool/main.go b/cmd/promtool/main.go index 00280500ed..5955cc0655 100644 --- a/cmd/promtool/main.go +++ b/cmd/promtool/main.go @@ -63,7 +63,8 @@ import ( ) func init() { - // This can be removed when the default validation scheme in common is updated. + // This can be removed when the legacy global mode is fully deprecated. + //nolint:staticcheck model.NameValidationScheme = model.UTF8Validation } @@ -1324,7 +1325,7 @@ func labelsSetPromQL(query, labelMatchType, name, value string) error { return fmt.Errorf("invalid label match type: %s", labelMatchType) } - parser.Inspect(expr, func(node parser.Node, path []parser.Node) error { + parser.Inspect(expr, func(node parser.Node, _ []parser.Node) error { if n, ok := node.(*parser.VectorSelector); ok { var found bool for i, l := range n.LabelMatchers { @@ -1355,7 +1356,7 @@ func labelsDeletePromQL(query, name string) error { return err } - parser.Inspect(expr, func(node parser.Node, path []parser.Node) error { + parser.Inspect(expr, func(node parser.Node, _ []parser.Node) error { if n, ok := node.(*parser.VectorSelector); ok { for i, l := range n.LabelMatchers { if l.Name == name { diff --git a/cmd/promtool/main_test.go b/cmd/promtool/main_test.go index 48bed9a2df..d3804da5e2 100644 --- a/cmd/promtool/main_test.go +++ b/cmd/promtool/main_test.go @@ -40,7 +40,8 @@ import ( ) func init() { - // This can be removed when the default validation scheme in common is updated. + // This can be removed when the legacy global mode is fully deprecated. + //nolint:staticcheck model.NameValidationScheme = model.UTF8Validation } @@ -136,8 +137,8 @@ func TestCheckSDFile(t *testing.T) { }, { name: "bad file extension", - file: "./testdata/bad-sd-file-extension.nonexistant", - err: "invalid file extension: \".nonexistant\"", + file: "./testdata/bad-sd-file-extension.nonexistent", + err: "invalid file extension: \".nonexistent\"", }, { name: "bad format", diff --git a/cmd/promtool/metrics.go b/cmd/promtool/metrics.go index 4c91d1d6fe..56b5209541 100644 --- a/cmd/promtool/metrics.go +++ b/cmd/promtool/metrics.go @@ -23,11 +23,11 @@ import ( "os" "time" - "github.com/golang/snappy" config_util "github.com/prometheus/common/config" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/storage/remote" + "github.com/prometheus/prometheus/util/compression" "github.com/prometheus/prometheus/util/fmtutil" ) @@ -116,7 +116,12 @@ func parseAndPushMetrics(client *remote.Client, data []byte, labels map[string]s } // Encode the request body into snappy encoding. - compressed := snappy.Encode(nil, raw) + compressed, err := compression.Encode(compression.Snappy, raw, nil) + if err != nil { + fmt.Fprintln(os.Stderr, " FAILED:", err) + return false + } + _, err = client.Store(context.Background(), compressed, 0) if err != nil { fmt.Fprintln(os.Stderr, " FAILED:", err) diff --git a/cmd/promtool/rules_test.go b/cmd/promtool/rules_test.go index e22b8a556b..3cb47aa8af 100644 --- a/cmd/promtool/rules_test.go +++ b/cmd/promtool/rules_test.go @@ -35,7 +35,7 @@ type mockQueryRangeAPI struct { samples model.Matrix } -func (mockAPI mockQueryRangeAPI) QueryRange(_ context.Context, query string, r v1.Range, opts ...v1.Option) (model.Value, v1.Warnings, error) { +func (mockAPI mockQueryRangeAPI) QueryRange(_ context.Context, _ string, _ v1.Range, _ ...v1.Option) (model.Value, v1.Warnings, error) { return mockAPI.samples, v1.Warnings{}, nil } diff --git a/cmd/promtool/sd.go b/cmd/promtool/sd.go index 8863fbeac0..884864205c 100644 --- a/cmd/promtool/sd.go +++ b/cmd/promtool/sd.go @@ -38,7 +38,7 @@ type sdCheckResult struct { } // CheckSD performs service discovery for the given job name and reports the results. -func CheckSD(sdConfigFiles, sdJobName string, sdTimeout time.Duration, registerer prometheus.Registerer) int { +func CheckSD(sdConfigFiles, sdJobName string, sdTimeout time.Duration, _ prometheus.Registerer) int { logger := promslog.New(&promslog.Config{}) cfg, err := config.LoadFile(sdConfigFiles, false, logger) diff --git a/cmd/promtool/testdata/bad-sd-file-extension.nonexistant b/cmd/promtool/testdata/bad-sd-file-extension.nonexistent similarity index 100% rename from cmd/promtool/testdata/bad-sd-file-extension.nonexistant rename to cmd/promtool/testdata/bad-sd-file-extension.nonexistent diff --git a/cmd/promtool/unittest.go b/cmd/promtool/unittest.go index 7f494e27aa..06b0e28c51 100644 --- a/cmd/promtool/unittest.go +++ b/cmd/promtool/unittest.go @@ -224,7 +224,7 @@ func (tg *testGroup) test(testname string, evalInterval time.Duration, groupOrde QueryFunc: rules.EngineQueryFunc(suite.QueryEngine(), suite.Storage()), Appendable: suite.Storage(), Context: context.Background(), - NotifyFunc: func(ctx context.Context, expr string, alerts ...*rules.Alert) {}, + NotifyFunc: func(_ context.Context, _ string, _ ...*rules.Alert) {}, Logger: promslog.NewNopLogger(), } m := rules.NewManager(opts) diff --git a/config/config.go b/config/config.go index 465affe082..a38080f22a 100644 --- a/config/config.go +++ b/config/config.go @@ -156,6 +156,7 @@ var ( // DefaultConfig is the default top-level configuration. DefaultConfig = Config{ GlobalConfig: DefaultGlobalConfig, + Runtime: DefaultRuntimeConfig, } // DefaultGlobalConfig is the default global configuration. @@ -836,12 +837,12 @@ func (c *ScrapeConfig) Validate(globalConfig GlobalConfig) error { } } + //nolint:staticcheck + if model.NameValidationScheme != model.UTF8Validation { + return errors.New("model.NameValidationScheme must be set to UTF8") + } switch globalConfig.MetricNameValidationScheme { - case LegacyValidationConfig: - case "", UTF8ValidationConfig: - if model.NameValidationScheme != model.UTF8Validation { - panic("utf8 name validation requested but model.NameValidationScheme is not set to UTF8") - } + case "", LegacyValidationConfig, UTF8ValidationConfig: default: return fmt.Errorf("unknown name validation method specified, must be either 'legacy' or 'utf8', got %s", globalConfig.MetricNameValidationScheme) } diff --git a/config/config_test.go b/config/config_test.go index 437b858b00..295e835f1e 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -15,7 +15,6 @@ package config import ( "crypto/tls" - "encoding/json" "fmt" "net/url" "os" @@ -62,11 +61,6 @@ import ( "github.com/prometheus/prometheus/util/testutil" ) -func init() { - // This can be removed when the default validation scheme in common is updated. - model.NameValidationScheme = model.UTF8Validation -} - func mustParseURL(u string) *config.URL { parsed, err := url.Parse(u) if err != nil { @@ -1716,11 +1710,7 @@ var expectedErrors = []struct { }, { filename: "labelname.bad.yml", - errMsg: `"not$allowed" is not a valid label name`, - }, - { - filename: "labelname2.bad.yml", - errMsg: `"not:allowed" is not a valid label name`, + errMsg: `"\xff" is not a valid label name`, }, { filename: "labelvalue.bad.yml", @@ -1792,16 +1782,12 @@ var expectedErrors = []struct { }, { filename: "labelmap.bad.yml", - errMsg: "\"l-$1\" is invalid 'replacement' for labelmap action", + errMsg: "!!binary value contains invalid base64 data", }, { filename: "lowercase.bad.yml", errMsg: "relabel configuration for lowercase action requires 'target_label' value", }, - { - filename: "lowercase2.bad.yml", - errMsg: "\"42lab\" is invalid 'target_label' for lowercase action", - }, { filename: "lowercase3.bad.yml", errMsg: "'replacement' can not be set for lowercase action", @@ -1810,10 +1796,6 @@ var expectedErrors = []struct { filename: "uppercase.bad.yml", errMsg: "relabel configuration for uppercase action requires 'target_label' value", }, - { - filename: "uppercase2.bad.yml", - errMsg: "\"42lab\" is invalid 'target_label' for uppercase action", - }, { filename: "uppercase3.bad.yml", errMsg: "'replacement' can not be set for uppercase action", @@ -2181,10 +2163,6 @@ var expectedErrors = []struct { } func TestBadConfigs(t *testing.T) { - model.NameValidationScheme = model.LegacyValidation - defer func() { - model.NameValidationScheme = model.UTF8Validation - }() for _, ee := range expectedErrors { _, err := LoadFile("testdata/"+ee.filename, false, promslog.NewNopLogger()) require.ErrorContains(t, err, ee.errMsg, @@ -2192,23 +2170,7 @@ func TestBadConfigs(t *testing.T) { } } -func TestBadStaticConfigsJSON(t *testing.T) { - model.NameValidationScheme = model.LegacyValidation - defer func() { - model.NameValidationScheme = model.UTF8Validation - }() - content, err := os.ReadFile("testdata/static_config.bad.json") - require.NoError(t, err) - var tg targetgroup.Group - err = json.Unmarshal(content, &tg) - require.Error(t, err) -} - func TestBadStaticConfigsYML(t *testing.T) { - model.NameValidationScheme = model.LegacyValidation - defer func() { - model.NameValidationScheme = model.UTF8Validation - }() content, err := os.ReadFile("testdata/static_config.bad.yml") require.NoError(t, err) var tg targetgroup.Group @@ -2222,6 +2184,7 @@ func TestEmptyConfig(t *testing.T) { exp := DefaultConfig exp.loaded = true require.Equal(t, exp, *c) + require.Equal(t, 75, c.Runtime.GoGC) } func TestExpandExternalLabels(t *testing.T) { @@ -2269,7 +2232,6 @@ func TestEmptyGlobalBlock(t *testing.T) { c, err := Load("global:\n", promslog.NewNopLogger()) require.NoError(t, err) exp := DefaultConfig - exp.Runtime = DefaultRuntimeConfig exp.loaded = true require.Equal(t, exp, *c) } @@ -2453,11 +2415,6 @@ func TestScrapeConfigDisableCompression(t *testing.T) { } func TestScrapeConfigNameValidationSettings(t *testing.T) { - model.NameValidationScheme = model.UTF8Validation - defer func() { - model.NameValidationScheme = model.LegacyValidation - }() - tests := []struct { name string inputFile string diff --git a/config/testdata/labelmap.bad.yml b/config/testdata/labelmap.bad.yml index 29d2653990..b8aa117acf 100644 --- a/config/testdata/labelmap.bad.yml +++ b/config/testdata/labelmap.bad.yml @@ -2,4 +2,4 @@ scrape_configs: - job_name: prometheus relabel_configs: - action: labelmap - replacement: l-$1 + replacement: !!binary "/w==$1" diff --git a/config/testdata/labelname.bad.yml b/config/testdata/labelname.bad.yml index c06853a26b..0c9c5ef3b2 100644 --- a/config/testdata/labelname.bad.yml +++ b/config/testdata/labelname.bad.yml @@ -1,3 +1,3 @@ global: external_labels: - not$allowed: value + !!binary "/w==": value diff --git a/config/testdata/labelname2.bad.yml b/config/testdata/labelname2.bad.yml deleted file mode 100644 index 7afcd6bcfc..0000000000 --- a/config/testdata/labelname2.bad.yml +++ /dev/null @@ -1,3 +0,0 @@ -global: - external_labels: - 'not:allowed': value diff --git a/config/testdata/lowercase2.bad.yml b/config/testdata/lowercase2.bad.yml deleted file mode 100644 index bde8862c66..0000000000 --- a/config/testdata/lowercase2.bad.yml +++ /dev/null @@ -1,6 +0,0 @@ -scrape_configs: - - job_name: prometheus - relabel_configs: - - action: lowercase - source_labels: [__name__] - target_label: 42lab diff --git a/config/testdata/static_config.bad.json b/config/testdata/static_config.bad.json deleted file mode 100644 index 6050ed9c50..0000000000 --- a/config/testdata/static_config.bad.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "targets": ["1.2.3.4:9100"], - "labels": { - "some_valid_label": "foo", - "oops:this-label-is-invalid": "bar" - } -} diff --git a/config/testdata/static_config.bad.yml b/config/testdata/static_config.bad.yml index 1d229ec5e7..7e9003dcbf 100644 --- a/config/testdata/static_config.bad.yml +++ b/config/testdata/static_config.bad.yml @@ -1,4 +1,4 @@ targets: ['1.2.3.4:9001', '1.2.3.5:9090'] labels: valid_label: foo - not:valid_label: bar + !!binary "/w==": bar diff --git a/config/testdata/uppercase2.bad.yml b/config/testdata/uppercase2.bad.yml deleted file mode 100644 index 330b9aceb6..0000000000 --- a/config/testdata/uppercase2.bad.yml +++ /dev/null @@ -1,6 +0,0 @@ -scrape_configs: - - job_name: prometheus - relabel_configs: - - action: uppercase - source_labels: [__name__] - target_label: 42lab diff --git a/discovery/aws/ec2.go b/discovery/aws/ec2.go index 0f35c401e6..7e35a1807f 100644 --- a/discovery/aws/ec2.go +++ b/discovery/aws/ec2.go @@ -101,7 +101,7 @@ type EC2SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*EC2SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*EC2SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &ec2Metrics{ refreshMetrics: rmi, } @@ -262,7 +262,7 @@ func (d *EC2Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error } input := &ec2.DescribeInstancesInput{Filters: filters} - if err := ec2Client.DescribeInstancesPagesWithContext(ctx, input, func(p *ec2.DescribeInstancesOutput, lastPage bool) bool { + if err := ec2Client.DescribeInstancesPagesWithContext(ctx, input, func(p *ec2.DescribeInstancesOutput, _ bool) bool { for _, r := range p.Reservations { for _, inst := range r.Instances { if inst.PrivateIpAddress == nil { diff --git a/discovery/aws/ec2_test.go b/discovery/aws/ec2_test.go index f34065c23e..2955e0e02e 100644 --- a/discovery/aws/ec2_test.go +++ b/discovery/aws/ec2_test.go @@ -217,7 +217,7 @@ func TestEC2DiscoveryRefresh(t *testing.T) { State: &ec2.InstanceState{Name: strptr("running")}, SubnetId: strptr("azid-3"), VpcId: strptr("vpc-ipv4"), - // network intefaces + // network interfaces NetworkInterfaces: []*ec2.InstanceNetworkInterface{ // interface without subnet -> should be ignored { @@ -285,7 +285,7 @@ func TestEC2DiscoveryRefresh(t *testing.T) { State: &ec2.InstanceState{Name: strptr("running")}, SubnetId: strptr("azid-2"), VpcId: strptr("vpc-ipv6"), - // network intefaces + // network interfaces NetworkInterfaces: []*ec2.InstanceNetworkInterface{ // interface without primary IPv6, index 2 { @@ -399,7 +399,7 @@ func newMockEC2Client(ec2Data *ec2DataStore) *mockEC2Client { return &client } -func (m *mockEC2Client) DescribeAvailabilityZonesWithContext(ctx aws.Context, input *ec2.DescribeAvailabilityZonesInput, opts ...request.Option) (*ec2.DescribeAvailabilityZonesOutput, error) { +func (m *mockEC2Client) DescribeAvailabilityZonesWithContext(_ aws.Context, _ *ec2.DescribeAvailabilityZonesInput, _ ...request.Option) (*ec2.DescribeAvailabilityZonesOutput, error) { if len(m.ec2Data.azToAZID) == 0 { return nil, errors.New("No AZs found") } @@ -420,7 +420,7 @@ func (m *mockEC2Client) DescribeAvailabilityZonesWithContext(ctx aws.Context, in }, nil } -func (m *mockEC2Client) DescribeInstancesPagesWithContext(ctx aws.Context, input *ec2.DescribeInstancesInput, fn func(*ec2.DescribeInstancesOutput, bool) bool, opts ...request.Option) error { +func (m *mockEC2Client) DescribeInstancesPagesWithContext(_ aws.Context, _ *ec2.DescribeInstancesInput, fn func(*ec2.DescribeInstancesOutput, bool) bool, _ ...request.Option) error { r := ec2.Reservation{} r.SetInstances(m.ec2Data.instances) r.SetOwnerId(m.ec2Data.ownerID) diff --git a/discovery/aws/lightsail.go b/discovery/aws/lightsail.go index b892867f1b..fb249b8256 100644 --- a/discovery/aws/lightsail.go +++ b/discovery/aws/lightsail.go @@ -83,7 +83,7 @@ type LightsailSDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*LightsailSDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*LightsailSDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &lightsailMetrics{ refreshMetrics: rmi, } diff --git a/discovery/azure/azure_test.go b/discovery/azure/azure_test.go index b905e9fcef..d7141561e2 100644 --- a/discovery/azure/azure_test.go +++ b/discovery/azure/azure_test.go @@ -723,11 +723,11 @@ func createMockAzureClient(t *testing.T, vmResp []armcompute.VirtualMachinesClie func defaultMockInterfaceServer(interfaceResp armnetwork.Interface) fakenetwork.InterfacesServer { return fakenetwork.InterfacesServer{ - Get: func(ctx context.Context, resourceGroupName, networkInterfaceName string, options *armnetwork.InterfacesClientGetOptions) (resp azfake.Responder[armnetwork.InterfacesClientGetResponse], errResp azfake.ErrorResponder) { + Get: func(_ context.Context, _, _ string, _ *armnetwork.InterfacesClientGetOptions) (resp azfake.Responder[armnetwork.InterfacesClientGetResponse], errResp azfake.ErrorResponder) { resp.SetResponse(http.StatusOK, armnetwork.InterfacesClientGetResponse{Interface: interfaceResp}, nil) return }, - GetVirtualMachineScaleSetNetworkInterface: func(ctx context.Context, resourceGroupName, virtualMachineScaleSetName, virtualmachineIndex, networkInterfaceName string, options *armnetwork.InterfacesClientGetVirtualMachineScaleSetNetworkInterfaceOptions) (resp azfake.Responder[armnetwork.InterfacesClientGetVirtualMachineScaleSetNetworkInterfaceResponse], errResp azfake.ErrorResponder) { + GetVirtualMachineScaleSetNetworkInterface: func(_ context.Context, _, _, _, _ string, _ *armnetwork.InterfacesClientGetVirtualMachineScaleSetNetworkInterfaceOptions) (resp azfake.Responder[armnetwork.InterfacesClientGetVirtualMachineScaleSetNetworkInterfaceResponse], errResp azfake.ErrorResponder) { resp.SetResponse(http.StatusOK, armnetwork.InterfacesClientGetVirtualMachineScaleSetNetworkInterfaceResponse{Interface: interfaceResp}, nil) return }, @@ -736,7 +736,7 @@ func defaultMockInterfaceServer(interfaceResp armnetwork.Interface) fakenetwork. func defaultMockVMServer(vmResp []armcompute.VirtualMachinesClientListAllResponse) fake.VirtualMachinesServer { return fake.VirtualMachinesServer{ - NewListAllPager: func(options *armcompute.VirtualMachinesClientListAllOptions) (resp azfake.PagerResponder[armcompute.VirtualMachinesClientListAllResponse]) { + NewListAllPager: func(_ *armcompute.VirtualMachinesClientListAllOptions) (resp azfake.PagerResponder[armcompute.VirtualMachinesClientListAllResponse]) { for _, page := range vmResp { resp.AddPage(http.StatusOK, page, nil) } @@ -747,7 +747,7 @@ func defaultMockVMServer(vmResp []armcompute.VirtualMachinesClientListAllRespons func defaultMockVMSSServer(vmssResp []armcompute.VirtualMachineScaleSetsClientListAllResponse) fake.VirtualMachineScaleSetsServer { return fake.VirtualMachineScaleSetsServer{ - NewListAllPager: func(options *armcompute.VirtualMachineScaleSetsClientListAllOptions) (resp azfake.PagerResponder[armcompute.VirtualMachineScaleSetsClientListAllResponse]) { + NewListAllPager: func(_ *armcompute.VirtualMachineScaleSetsClientListAllOptions) (resp azfake.PagerResponder[armcompute.VirtualMachineScaleSetsClientListAllResponse]) { for _, page := range vmssResp { resp.AddPage(http.StatusOK, page, nil) } @@ -758,7 +758,7 @@ func defaultMockVMSSServer(vmssResp []armcompute.VirtualMachineScaleSetsClientLi func defaultMockVMSSVMServer(vmssvmResp []armcompute.VirtualMachineScaleSetVMsClientListResponse) fake.VirtualMachineScaleSetVMsServer { return fake.VirtualMachineScaleSetVMsServer{ - NewListPager: func(resourceGroupName, virtualMachineScaleSetName string, options *armcompute.VirtualMachineScaleSetVMsClientListOptions) (resp azfake.PagerResponder[armcompute.VirtualMachineScaleSetVMsClientListResponse]) { + NewListPager: func(_, _ string, _ *armcompute.VirtualMachineScaleSetVMsClientListOptions) (resp azfake.PagerResponder[armcompute.VirtualMachineScaleSetVMsClientListResponse]) { for _, page := range vmssvmResp { resp.AddPage(http.StatusOK, page, nil) } diff --git a/discovery/consul/consul_test.go b/discovery/consul/consul_test.go index cdbb80baba..ba3f63ccb5 100644 --- a/discovery/consul/consul_test.go +++ b/discovery/consul/consul_test.go @@ -399,14 +399,14 @@ func TestGetDatacenterShouldReturnError(t *testing.T) { }{ { // Define a handler that will return status 500. - handler: func(w http.ResponseWriter, r *http.Request) { + handler: func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) }, errMessage: "Unexpected response code: 500 ()", }, { // Define a handler that will return incorrect response. - handler: func(w http.ResponseWriter, r *http.Request) { + handler: func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte(`{"Config": {"Not-Datacenter": "test-dc"}}`)) }, errMessage: "invalid value '' for Config.Datacenter", diff --git a/discovery/consul/metrics.go b/discovery/consul/metrics.go index 8266e7cc60..b49509bd8f 100644 --- a/discovery/consul/metrics.go +++ b/discovery/consul/metrics.go @@ -31,7 +31,7 @@ type consulMetrics struct { metricRegisterer discovery.MetricRegisterer } -func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func newDiscovererMetrics(reg prometheus.Registerer, _ discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { m := &consulMetrics{ rpcFailuresCount: prometheus.NewCounter( prometheus.CounterOpts{ diff --git a/discovery/digitalocean/digitalocean.go b/discovery/digitalocean/digitalocean.go index eeaedd8869..d0ececd9e9 100644 --- a/discovery/digitalocean/digitalocean.go +++ b/discovery/digitalocean/digitalocean.go @@ -65,7 +65,7 @@ func init() { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &digitaloceanMetrics{ refreshMetrics: rmi, } diff --git a/discovery/dns/dns_test.go b/discovery/dns/dns_test.go index f01a075c45..ea46ad3237 100644 --- a/discovery/dns/dns_test.go +++ b/discovery/dns/dns_test.go @@ -52,7 +52,7 @@ func TestDNS(t *testing.T) { Port: 80, Type: "A", }, - lookup: func(name string, qtype uint16, logger *slog.Logger) (*dns.Msg, error) { + lookup: func(_ string, _ uint16, _ *slog.Logger) (*dns.Msg, error) { return nil, errors.New("some error") }, expected: []*targetgroup.Group{}, @@ -65,7 +65,7 @@ func TestDNS(t *testing.T) { Port: 80, Type: "A", }, - lookup: func(name string, qtype uint16, logger *slog.Logger) (*dns.Msg, error) { + lookup: func(_ string, _ uint16, _ *slog.Logger) (*dns.Msg, error) { return &dns.Msg{ Answer: []dns.RR{ &dns.A{A: net.IPv4(192, 0, 2, 2)}, @@ -97,7 +97,7 @@ func TestDNS(t *testing.T) { Port: 80, Type: "AAAA", }, - lookup: func(name string, qtype uint16, logger *slog.Logger) (*dns.Msg, error) { + lookup: func(_ string, _ uint16, _ *slog.Logger) (*dns.Msg, error) { return &dns.Msg{ Answer: []dns.RR{ &dns.AAAA{AAAA: net.IPv6loopback}, @@ -128,7 +128,7 @@ func TestDNS(t *testing.T) { Type: "SRV", RefreshInterval: model.Duration(time.Minute), }, - lookup: func(name string, qtype uint16, logger *slog.Logger) (*dns.Msg, error) { + lookup: func(_ string, _ uint16, _ *slog.Logger) (*dns.Msg, error) { return &dns.Msg{ Answer: []dns.RR{ &dns.SRV{Port: 3306, Target: "db1.example.com."}, @@ -167,7 +167,7 @@ func TestDNS(t *testing.T) { Names: []string{"_mysql._tcp.db.example.com."}, RefreshInterval: model.Duration(time.Minute), }, - lookup: func(name string, qtype uint16, logger *slog.Logger) (*dns.Msg, error) { + lookup: func(_ string, _ uint16, _ *slog.Logger) (*dns.Msg, error) { return &dns.Msg{ Answer: []dns.RR{ &dns.SRV{Port: 3306, Target: "db1.example.com."}, @@ -198,7 +198,7 @@ func TestDNS(t *testing.T) { Names: []string{"_mysql._tcp.db.example.com."}, RefreshInterval: model.Duration(time.Minute), }, - lookup: func(name string, qtype uint16, logger *slog.Logger) (*dns.Msg, error) { + lookup: func(_ string, _ uint16, _ *slog.Logger) (*dns.Msg, error) { return &dns.Msg{}, nil }, expected: []*targetgroup.Group{ @@ -215,7 +215,7 @@ func TestDNS(t *testing.T) { Port: 25, RefreshInterval: model.Duration(time.Minute), }, - lookup: func(name string, qtype uint16, logger *slog.Logger) (*dns.Msg, error) { + lookup: func(_ string, _ uint16, _ *slog.Logger) (*dns.Msg, error) { return &dns.Msg{ Answer: []dns.RR{ &dns.MX{Preference: 0, Mx: "smtp1.example.com."}, diff --git a/discovery/eureka/client_test.go b/discovery/eureka/client_test.go index 83f6fd5ff1..f85409a11e 100644 --- a/discovery/eureka/client_test.go +++ b/discovery/eureka/client_test.go @@ -172,7 +172,7 @@ func TestFetchApps(t *testing.T) { ` // Simulate apps with a valid XML response. - respHandler := func(w http.ResponseWriter, r *http.Request) { + respHandler := func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/xml") io.WriteString(w, appsXML) @@ -199,7 +199,7 @@ func TestFetchApps(t *testing.T) { func Test500ErrorHttpResponse(t *testing.T) { // Simulate 500 error. - respHandler := func(w http.ResponseWriter, r *http.Request) { + respHandler := func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) w.Header().Set("Content-Type", "application/xml") io.WriteString(w, ``) diff --git a/discovery/eureka/eureka.go b/discovery/eureka/eureka.go index 3cac667f85..459b608e96 100644 --- a/discovery/eureka/eureka.go +++ b/discovery/eureka/eureka.go @@ -77,7 +77,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &eurekaMetrics{ refreshMetrics: rmi, } diff --git a/discovery/eureka/eureka_test.go b/discovery/eureka/eureka_test.go index b499410bfc..5ea9a6c74e 100644 --- a/discovery/eureka/eureka_test.go +++ b/discovery/eureka/eureka_test.go @@ -58,7 +58,7 @@ func testUpdateServices(respHandler http.HandlerFunc) ([]*targetgroup.Group, err func TestEurekaSDHandleError(t *testing.T) { var ( errTesting = "non 2xx status '500' response during eureka service discovery" - respHandler = func(w http.ResponseWriter, r *http.Request) { + respHandler = func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) w.Header().Set("Content-Type", "application/xml") io.WriteString(w, ``) @@ -76,7 +76,7 @@ func TestEurekaSDEmptyList(t *testing.T) { 1 ` - respHandler = func(w http.ResponseWriter, r *http.Request) { + respHandler = func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/xml") io.WriteString(w, appsXML) @@ -235,7 +235,7 @@ func TestEurekaSDSendGroup(t *testing.T) { ` - respHandler = func(w http.ResponseWriter, r *http.Request) { + respHandler = func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/xml") io.WriteString(w, appsXML) diff --git a/discovery/file/file_test.go b/discovery/file/file_test.go index 179ac5cd1c..46b2ff0262 100644 --- a/discovery/file/file_test.go +++ b/discovery/file/file_test.go @@ -19,6 +19,7 @@ import ( "io" "os" "path/filepath" + "runtime" "sort" "sync" "testing" @@ -319,6 +320,9 @@ func valid2Tg(file string) []*targetgroup.Group { } func TestInitialUpdate(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("flaky test, see https://github.com/prometheus/prometheus/issues/16212") + } for _, tc := range []string{ "fixtures/valid.yml", "fixtures/valid.json", @@ -363,6 +367,9 @@ func TestInvalidFile(t *testing.T) { } func TestNoopFileUpdate(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("flaky test, see https://github.com/prometheus/prometheus/issues/16212") + } t.Parallel() runner := newTestRunner(t) @@ -381,6 +388,9 @@ func TestNoopFileUpdate(t *testing.T) { } func TestFileUpdate(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("flaky test, see https://github.com/prometheus/prometheus/issues/16212") + } t.Parallel() runner := newTestRunner(t) @@ -399,6 +409,9 @@ func TestFileUpdate(t *testing.T) { } func TestInvalidFileUpdate(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("flaky test, see https://github.com/prometheus/prometheus/issues/16212") + } t.Parallel() runner := newTestRunner(t) @@ -421,6 +434,9 @@ func TestInvalidFileUpdate(t *testing.T) { } func TestUpdateFileWithPartialWrites(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("flaky test, see https://github.com/prometheus/prometheus/issues/16212") + } t.Parallel() runner := newTestRunner(t) diff --git a/discovery/file/metrics.go b/discovery/file/metrics.go index c01501e4ef..3e3df7bbf6 100644 --- a/discovery/file/metrics.go +++ b/discovery/file/metrics.go @@ -30,7 +30,7 @@ type fileMetrics struct { metricRegisterer discovery.MetricRegisterer } -func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func newDiscovererMetrics(reg prometheus.Registerer, _ discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { fm := &fileMetrics{ fileSDReadErrorsCount: prometheus.NewCounter( prometheus.CounterOpts{ diff --git a/discovery/gce/gce.go b/discovery/gce/gce.go index 9a5b0e856e..32f1bb6722 100644 --- a/discovery/gce/gce.go +++ b/discovery/gce/gce.go @@ -83,7 +83,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &gceMetrics{ refreshMetrics: rmi, } diff --git a/discovery/hetzner/hetzner.go b/discovery/hetzner/hetzner.go index 02e2272999..97d48f6d70 100644 --- a/discovery/hetzner/hetzner.go +++ b/discovery/hetzner/hetzner.go @@ -64,7 +64,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &hetznerMetrics{ refreshMetrics: rmi, } diff --git a/discovery/http/http_test.go b/discovery/http/http_test.go index 9d3a3fb5e7..3af9e4e504 100644 --- a/discovery/http/http_test.go +++ b/discovery/http/http_test.go @@ -75,7 +75,7 @@ func TestHTTPValidRefresh(t *testing.T) { } func TestHTTPInvalidCode(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) })) @@ -104,7 +104,7 @@ func TestHTTPInvalidCode(t *testing.T) { } func TestHTTPInvalidFormat(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { fmt.Fprintln(w, "{}") })) @@ -212,7 +212,7 @@ func TestContentTypeRegex(t *testing.T) { func TestSourceDisappeared(t *testing.T) { var stubResponse string - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprintln(w, stubResponse) })) diff --git a/discovery/ionos/ionos.go b/discovery/ionos/ionos.go index 1badda48cb..475e6c30eb 100644 --- a/discovery/ionos/ionos.go +++ b/discovery/ionos/ionos.go @@ -89,7 +89,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &ionosMetrics{ refreshMetrics: rmi, } diff --git a/discovery/kubernetes/kubernetes_test.go b/discovery/kubernetes/kubernetes_test.go index e34bed899c..68d2d0ce35 100644 --- a/discovery/kubernetes/kubernetes_test.go +++ b/discovery/kubernetes/kubernetes_test.go @@ -312,7 +312,7 @@ func TestFailuresCountMetric(t *testing.T) { require.Equal(t, float64(0), prom_testutil.ToFloat64(n.metrics.failuresCount)) // Simulate an error on watch requests. - c.Discovery().(*fakediscovery.FakeDiscovery).PrependWatchReactor("*", func(action kubetesting.Action) (bool, watch.Interface, error) { + c.Discovery().(*fakediscovery.FakeDiscovery).PrependWatchReactor("*", func(_ kubetesting.Action) (bool, watch.Interface, error) { return true, nil, apierrors.NewUnauthorized("unauthorized") }) diff --git a/discovery/kubernetes/metrics.go b/discovery/kubernetes/metrics.go index fe419bc782..ba3cb1d32a 100644 --- a/discovery/kubernetes/metrics.go +++ b/discovery/kubernetes/metrics.go @@ -28,7 +28,7 @@ type kubernetesMetrics struct { metricRegisterer discovery.MetricRegisterer } -func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func newDiscovererMetrics(reg prometheus.Registerer, _ discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { m := &kubernetesMetrics{ eventCount: prometheus.NewCounterVec( prometheus.CounterOpts{ diff --git a/discovery/marathon/marathon.go b/discovery/marathon/marathon.go index 9c93e43f51..0c2c2e9702 100644 --- a/discovery/marathon/marathon.go +++ b/discovery/marathon/marathon.go @@ -80,7 +80,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &marathonMetrics{ refreshMetrics: rmi, } diff --git a/discovery/marathon/marathon_test.go b/discovery/marathon/marathon_test.go index 659899f163..61d8ef900d 100644 --- a/discovery/marathon/marathon_test.go +++ b/discovery/marathon/marathon_test.go @@ -243,7 +243,7 @@ func TestMarathonZeroTaskPorts(t *testing.T) { func Test500ErrorHttpResponseWithValidJSONBody(t *testing.T) { // Simulate 500 error with a valid JSON response. - respHandler := func(w http.ResponseWriter, r *http.Request) { + respHandler := func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) w.Header().Set("Content-Type", "application/json") io.WriteString(w, `{}`) diff --git a/discovery/moby/docker.go b/discovery/moby/docker.go index fca97ccd47..53a8b2e135 100644 --- a/discovery/moby/docker.go +++ b/discovery/moby/docker.go @@ -25,7 +25,6 @@ import ( "strconv" "time" - "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/network" @@ -211,7 +210,7 @@ func (d *DockerDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group, er return nil, fmt.Errorf("error while computing network labels: %w", err) } - allContainers := make(map[string]types.Container) + allContainers := make(map[string]container.Summary) for _, c := range containers { allContainers[c.ID] = c } diff --git a/discovery/moby/dockerswarm.go b/discovery/moby/dockerswarm.go index ae12116301..57c0af7171 100644 --- a/discovery/moby/dockerswarm.go +++ b/discovery/moby/dockerswarm.go @@ -70,7 +70,7 @@ type Filter struct { } // NewDiscovererMetrics implements discovery.Config. -func (*DockerSwarmSDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*DockerSwarmSDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &dockerswarmMetrics{ refreshMetrics: rmi, } diff --git a/discovery/nomad/nomad_test.go b/discovery/nomad/nomad_test.go index c08f017496..a73b45785d 100644 --- a/discovery/nomad/nomad_test.go +++ b/discovery/nomad/nomad_test.go @@ -76,7 +76,7 @@ func (s *NomadSDTestSuite) SetupTest(t *testing.T) { } func (m *SDMock) HandleServicesList() { - m.Mux.HandleFunc("/v1/services", func(w http.ResponseWriter, r *http.Request) { + m.Mux.HandleFunc("/v1/services", func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("content-type", "application/json; charset=utf-8") w.WriteHeader(http.StatusOK) @@ -99,7 +99,7 @@ func (m *SDMock) HandleServicesList() { } func (m *SDMock) HandleServiceHashiCupsGet() { - m.Mux.HandleFunc("/v1/service/hashicups", func(w http.ResponseWriter, r *http.Request) { + m.Mux.HandleFunc("/v1/service/hashicups", func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("content-type", "application/json; charset=utf-8") w.WriteHeader(http.StatusOK) diff --git a/discovery/openstack/hypervisor.go b/discovery/openstack/hypervisor.go index 5cea68c4a5..e7a6362052 100644 --- a/discovery/openstack/hypervisor.go +++ b/discovery/openstack/hypervisor.go @@ -77,7 +77,7 @@ func (h *HypervisorDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group // OpenStack API reference // https://developer.openstack.org/api-ref/compute/#list-hypervisors-details pagerHypervisors := hypervisors.List(client, nil) - err = pagerHypervisors.EachPage(ctx, func(ctx context.Context, page pagination.Page) (bool, error) { + err = pagerHypervisors.EachPage(ctx, func(_ context.Context, page pagination.Page) (bool, error) { hypervisorList, err := hypervisors.ExtractHypervisors(page) if err != nil { return false, fmt.Errorf("could not extract hypervisors: %w", err) diff --git a/discovery/openstack/instance.go b/discovery/openstack/instance.go index dea327afe3..6c2f79b3a4 100644 --- a/discovery/openstack/instance.go +++ b/discovery/openstack/instance.go @@ -119,7 +119,7 @@ func (i *InstanceDiscovery) refresh(ctx context.Context) ([]*targetgroup.Group, pagerFIP := floatingips.List(networkClient, floatingips.ListOpts{}) floatingIPList := make(map[floatingIPKey]string) floatingIPPresent := make(map[string]struct{}) - err = pagerFIP.EachPage(ctx, func(ctx context.Context, page pagination.Page) (bool, error) { + err = pagerFIP.EachPage(ctx, func(_ context.Context, page pagination.Page) (bool, error) { result, err := floatingips.ExtractFloatingIPs(page) if err != nil { return false, fmt.Errorf("could not extract floatingips: %w", err) diff --git a/discovery/openstack/loadbalancer.go b/discovery/openstack/loadbalancer.go index 32e0f24f8d..612c59567e 100644 --- a/discovery/openstack/loadbalancer.go +++ b/discovery/openstack/loadbalancer.go @@ -118,9 +118,6 @@ func (i *LoadBalancerDiscovery) refresh(ctx context.Context) ([]*targetgroup.Gro // Fetch all floating IPs fipPages, err := floatingips.List(networkClient, floatingips.ListOpts{}).AllPages(ctx) - if err != nil { - return nil, fmt.Errorf("failed to list all fips: %w", err) - } if err != nil { return nil, fmt.Errorf("failed to list floating IPs: %w", err) } diff --git a/discovery/openstack/mock_test.go b/discovery/openstack/mock_test.go index 36620defeb..34e09c710f 100644 --- a/discovery/openstack/mock_test.go +++ b/discovery/openstack/mock_test.go @@ -62,7 +62,7 @@ func testHeader(t *testing.T, r *http.Request, header, expected string) { // HandleVersionsSuccessfully mocks version call. func (m *SDMock) HandleVersionsSuccessfully() { - m.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + m.Mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprintf(w, ` { "versions": { @@ -90,7 +90,7 @@ func (m *SDMock) HandleVersionsSuccessfully() { // HandleAuthSuccessfully mocks auth call. func (m *SDMock) HandleAuthSuccessfully() { - m.Mux.HandleFunc("/v3/auth/tokens", func(w http.ResponseWriter, r *http.Request) { + m.Mux.HandleFunc("/v3/auth/tokens", func(w http.ResponseWriter, _ *http.Request) { w.Header().Add("X-Subject-Token", tokenID) w.WriteHeader(http.StatusCreated) diff --git a/discovery/openstack/openstack.go b/discovery/openstack/openstack.go index eb1d4d5a4d..d7b58787a1 100644 --- a/discovery/openstack/openstack.go +++ b/discovery/openstack/openstack.go @@ -67,7 +67,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &openstackMetrics{ refreshMetrics: rmi, } diff --git a/discovery/ovhcloud/ovhcloud.go b/discovery/ovhcloud/ovhcloud.go index a75e9694fe..492bca603a 100644 --- a/discovery/ovhcloud/ovhcloud.go +++ b/discovery/ovhcloud/ovhcloud.go @@ -54,7 +54,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &ovhcloudMetrics{ refreshMetrics: rmi, } diff --git a/discovery/puppetdb/puppetdb.go b/discovery/puppetdb/puppetdb.go index b71842ff52..e249bc4afa 100644 --- a/discovery/puppetdb/puppetdb.go +++ b/discovery/puppetdb/puppetdb.go @@ -82,7 +82,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &puppetdbMetrics{ refreshMetrics: rmi, } diff --git a/discovery/puppetdb/puppetdb_test.go b/discovery/puppetdb/puppetdb_test.go index 4585b78223..57e198e131 100644 --- a/discovery/puppetdb/puppetdb_test.go +++ b/discovery/puppetdb/puppetdb_test.go @@ -184,7 +184,7 @@ func TestPuppetDBRefreshWithParameters(t *testing.T) { } func TestPuppetDBInvalidCode(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) })) @@ -212,7 +212,7 @@ func TestPuppetDBInvalidCode(t *testing.T) { } func TestPuppetDBInvalidFormat(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { fmt.Fprintln(w, "{}") })) diff --git a/discovery/refresh/refresh_test.go b/discovery/refresh/refresh_test.go index 0d4460ffa6..7c57d0532a 100644 --- a/discovery/refresh/refresh_test.go +++ b/discovery/refresh/refresh_test.go @@ -56,7 +56,7 @@ func TestRefresh(t *testing.T) { } var i int - refresh := func(ctx context.Context) ([]*targetgroup.Group, error) { + refresh := func(_ context.Context) ([]*targetgroup.Group, error) { i++ switch i { case 1: diff --git a/discovery/scaleway/scaleway.go b/discovery/scaleway/scaleway.go index bc9282feaa..47ac092000 100644 --- a/discovery/scaleway/scaleway.go +++ b/discovery/scaleway/scaleway.go @@ -105,7 +105,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &scalewayMetrics{ refreshMetrics: rmi, } diff --git a/discovery/triton/triton.go b/discovery/triton/triton.go index 5ec7b65215..5efe49e23d 100644 --- a/discovery/triton/triton.go +++ b/discovery/triton/triton.go @@ -71,7 +71,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &tritonMetrics{ refreshMetrics: rmi, } diff --git a/discovery/triton/triton_test.go b/discovery/triton/triton_test.go index b2d06afaf6..b0dccbf898 100644 --- a/discovery/triton/triton_test.go +++ b/discovery/triton/triton_test.go @@ -230,7 +230,7 @@ func TestTritonSDRefreshCNsWithHostname(t *testing.T) { func testTritonSDRefresh(t *testing.T, c SDConfig, dstr string) []model.LabelSet { var ( td, m, _ = newTritonDiscovery(c) - s = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { fmt.Fprintln(w, dstr) })) ) diff --git a/discovery/uyuni/uyuni.go b/discovery/uyuni/uyuni.go index a37083575c..11b1888db4 100644 --- a/discovery/uyuni/uyuni.go +++ b/discovery/uyuni/uyuni.go @@ -113,7 +113,7 @@ type Discovery struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &uyuniMetrics{ refreshMetrics: rmi, } diff --git a/discovery/uyuni/uyuni_test.go b/discovery/uyuni/uyuni_test.go index 09be23e2b4..40d92fe79c 100644 --- a/discovery/uyuni/uyuni_test.go +++ b/discovery/uyuni/uyuni_test.go @@ -59,7 +59,7 @@ func testUpdateServices(respHandler http.HandlerFunc) ([]*targetgroup.Group, err func TestUyuniSDHandleError(t *testing.T) { var ( errTesting = "unable to login to Uyuni API: request error: bad status code - 500" - respHandler = func(w http.ResponseWriter, r *http.Request) { + respHandler = func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) w.Header().Set("Content-Type", "application/xml") io.WriteString(w, ``) @@ -75,7 +75,7 @@ func TestUyuniSDLogin(t *testing.T) { var ( errTesting = "unable to get the managed system groups information of monitored clients: request error: bad status code - 500" call = 0 - respHandler = func(w http.ResponseWriter, r *http.Request) { + respHandler = func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/xml") switch call { case 0: @@ -106,7 +106,7 @@ func TestUyuniSDLogin(t *testing.T) { func TestUyuniSDSkipLogin(t *testing.T) { var ( errTesting = "unable to get the managed system groups information of monitored clients: request error: bad status code - 500" - respHandler = func(w http.ResponseWriter, r *http.Request) { + respHandler = func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) w.Header().Set("Content-Type", "application/xml") io.WriteString(w, ``) diff --git a/discovery/vultr/vultr.go b/discovery/vultr/vultr.go index 3e9f68864a..24eebe2938 100644 --- a/discovery/vultr/vultr.go +++ b/discovery/vultr/vultr.go @@ -76,7 +76,7 @@ type SDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*SDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*SDConfig) NewDiscovererMetrics(_ prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &vultrMetrics{ refreshMetrics: rmi, } diff --git a/discovery/xds/client_test.go b/discovery/xds/client_test.go index 2cf5b2f9cb..bf0e53b348 100644 --- a/discovery/xds/client_test.go +++ b/discovery/xds/client_test.go @@ -106,7 +106,7 @@ func createTestHTTPResourceClient(t *testing.T, conf *HTTPResourceClientConfig, } func TestHTTPResourceClientFetchEmptyResponse(t *testing.T) { - client, cleanup := createTestHTTPResourceClient(t, testHTTPResourceConfig(), ProtocolV3, func(request *v3.DiscoveryRequest) (*v3.DiscoveryResponse, error) { + client, cleanup := createTestHTTPResourceClient(t, testHTTPResourceConfig(), ProtocolV3, func(_ *v3.DiscoveryRequest) (*v3.DiscoveryResponse, error) { return nil, nil }) defer cleanup() @@ -146,7 +146,7 @@ func TestHTTPResourceClientFetchFullResponse(t *testing.T) { } func TestHTTPResourceClientServerError(t *testing.T) { - client, cleanup := createTestHTTPResourceClient(t, testHTTPResourceConfig(), ProtocolV3, func(request *v3.DiscoveryRequest) (*v3.DiscoveryResponse, error) { + client, cleanup := createTestHTTPResourceClient(t, testHTTPResourceConfig(), ProtocolV3, func(_ *v3.DiscoveryRequest) (*v3.DiscoveryResponse, error) { return nil, errors.New("server error") }) defer cleanup() diff --git a/discovery/xds/metrics.go b/discovery/xds/metrics.go index 597d516566..bdc9598f2c 100644 --- a/discovery/xds/metrics.go +++ b/discovery/xds/metrics.go @@ -29,7 +29,7 @@ type xdsMetrics struct { metricRegisterer discovery.MetricRegisterer } -func newDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func newDiscovererMetrics(reg prometheus.Registerer, _ discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { m := &xdsMetrics{ fetchFailuresCount: prometheus.NewCounter( prometheus.CounterOpts{ diff --git a/discovery/xds/xds_test.go b/discovery/xds/xds_test.go index db10adc1a2..af2784bcb2 100644 --- a/discovery/xds/xds_test.go +++ b/discovery/xds/xds_test.go @@ -85,7 +85,7 @@ func createTestHTTPServer(t *testing.T, responder discoveryResponder) *httptest. } func constantResourceParser(targets []model.LabelSet, err error) resourceParser { - return func(resources []*anypb.Any, typeUrl string) ([]model.LabelSet, error) { + return func(_ []*anypb.Any, _ string) ([]model.LabelSet, error) { return targets, err } } @@ -120,7 +120,7 @@ func (rc testResourceClient) Close() { func TestPollingRefreshSkipUpdate(t *testing.T) { rc := &testResourceClient{ - fetch: func(ctx context.Context) (*v3.DiscoveryResponse, error) { + fetch: func(_ context.Context) (*v3.DiscoveryResponse, error) { return nil, nil }, } @@ -167,7 +167,7 @@ func TestPollingRefreshAttachesGroupMetadata(t *testing.T) { rc := &testResourceClient{ server: server, protocolVersion: ProtocolV3, - fetch: func(ctx context.Context) (*v3.DiscoveryResponse, error) { + fetch: func(_ context.Context) (*v3.DiscoveryResponse, error) { return &v3.DiscoveryResponse{}, nil }, } @@ -223,14 +223,14 @@ func TestPollingDisappearingTargets(t *testing.T) { rc := &testResourceClient{ server: server, protocolVersion: ProtocolV3, - fetch: func(ctx context.Context) (*v3.DiscoveryResponse, error) { + fetch: func(_ context.Context) (*v3.DiscoveryResponse, error) { return &v3.DiscoveryResponse{}, nil }, } // On the first poll, send back two targets. On the next, send just one. counter := 0 - parser := func(resources []*anypb.Any, typeUrl string) ([]model.LabelSet, error) { + parser := func(_ []*anypb.Any, _ string) ([]model.LabelSet, error) { counter++ if counter == 1 { return []model.LabelSet{ diff --git a/discovery/zookeeper/zookeeper.go b/discovery/zookeeper/zookeeper.go index a1cfe3d055..af26cc5a0e 100644 --- a/discovery/zookeeper/zookeeper.go +++ b/discovery/zookeeper/zookeeper.go @@ -59,7 +59,7 @@ type ServersetSDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*ServersetSDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*ServersetSDConfig) NewDiscovererMetrics(_ prometheus.Registerer, _ discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &discovery.NoopDiscovererMetrics{} } @@ -101,7 +101,7 @@ type NerveSDConfig struct { } // NewDiscovererMetrics implements discovery.Config. -func (*NerveSDConfig) NewDiscovererMetrics(reg prometheus.Registerer, rmi discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { +func (*NerveSDConfig) NewDiscovererMetrics(_ prometheus.Registerer, _ discovery.RefreshMetricsInstantiator) discovery.DiscovererMetrics { return &discovery.NoopDiscovererMetrics{} } diff --git a/discovery/zookeeper/zookeeper_test.go b/discovery/zookeeper/zookeeper_test.go index c2b41ce7a3..5f1b75c088 100644 --- a/discovery/zookeeper/zookeeper_test.go +++ b/discovery/zookeeper/zookeeper_test.go @@ -31,6 +31,6 @@ func TestNewDiscoveryError(t *testing.T) { []string{"unreachable.test"}, time.Second, []string{"/"}, nil, - func(data []byte, path string) (model.LabelSet, error) { return nil, nil }) + func(_ []byte, _ string) (model.LabelSet, error) { return nil, nil }) require.Error(t, err) } diff --git a/docs/command-line/prometheus.md b/docs/command-line/prometheus.md index 9b4ec8b736..0f58ff4b18 100644 --- a/docs/command-line/prometheus.md +++ b/docs/command-line/prometheus.md @@ -42,7 +42,7 @@ The Prometheus monitoring server | --storage.tsdb.no-lockfile | Do not create lockfile in data directory. Use with server mode only. | `false` | | --storage.tsdb.head-chunks-write-queue-size | Size of the queue through which head chunks are written to the disk to be m-mapped, 0 disables the queue completely. Experimental. Use with server mode only. | `0` | | --storage.agent.path | Base path for metrics storage. Use with agent mode only. | `data-agent/` | -| --storage.agent.wal-compression | Compress the agent WAL. Use with agent mode only. | `true` | +| --storage.agent.wal-compression | Compress the agent WAL. If false, the --storage.agent.wal-compression-type flag is ignored. Use with agent mode only. | `true` | | --storage.agent.retention.min-time | Minimum age samples may be before being considered for deletion when the WAL is truncated Use with agent mode only. | | | --storage.agent.retention.max-time | Maximum age samples may be before being forcibly deleted when the WAL is truncated Use with agent mode only. | | | --storage.agent.no-lockfile | Do not create lockfile in data directory. Use with agent mode only. | `false` | diff --git a/docs/configuration/alerting_rules.md b/docs/configuration/alerting_rules.md index cd33dba8e3..0a442876c3 100644 --- a/docs/configuration/alerting_rules.md +++ b/docs/configuration/alerting_rules.md @@ -46,7 +46,7 @@ this alert firing for the specified duration after the firing condition was last This can be used to prevent situations such as flapping alerts, false resolutions due to lack of data loss, etc. Alerting rules without the `keep_firing_for` clause will deactivate on the first evaluation where the condition is not met (assuming -any optional `for` duration desribed above has been satisfied). +any optional `for` duration described above has been satisfied). The `labels` clause allows specifying a set of additional labels to be attached to the alert. Any existing conflicting labels will be overwritten. The label diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index 9b1514942a..3550094ff2 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -2551,7 +2551,8 @@ input to a subsequent relabeling step), use the `__tmp` label name prefix. This prefix is guaranteed to never be used by Prometheus itself. ```yaml -# The source labels select values from existing labels. Their content is concatenated +# The source_labels tells the rule what labels to fetch from the series. Any +# labels which do not exist get a blank value (""). Their content is concatenated # using the configured separator and matched against the configured regular expression # for the replace, keep, and drop actions. [ source_labels: '[' [, ...] ']' ] diff --git a/docs/migration.md b/docs/migration.md index 34dae93e85..44cd466b3d 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -26,7 +26,7 @@ This document offers guidance on migrating from Prometheus 2.x to Prometheus 3.0 - Prometheus v3 will no longer add ports to scrape targets according to the specified scheme. Target will now appear in labels as configured. - If you rely on scrape targets like - `https://example.com/metrics` or `http://exmaple.com/metrics` to be + `https://example.com/metrics` or `http://example.com/metrics` to be represented as `https://example.com/metrics:443` and `http://example.com/metrics:80` respectively, add them to your target URLs - `agent` @@ -139,7 +139,7 @@ may now fail if this fallback protocol is not specified. The TSDB format has been changed slightly in Prometheus v2.55 in preparation for changes to the index format. Consequently, a Prometheus v3 TSDB can only be read by a Prometheus v2.55 or newer. Keep that in mind when upgrading to v3 -- you will be only -able to downgrade to v2.55, not lower, without losing your TSDB persitent data. +able to downgrade to v2.55, not lower, without losing your TSDB persistent data. As an extra safety measure, you could optionally consider upgrading to v2.55 first and confirm Prometheus works as expected, before upgrading to v3. diff --git a/docs/querying/api.md b/docs/querying/api.md index 1366dc02c2..033a2dfcf5 100644 --- a/docs/querying/api.md +++ b/docs/querying/api.md @@ -45,7 +45,7 @@ The JSON response envelope format is as follows: // Only set if there were warnings while executing the request. // There will still be data in the data field. "warnings": [""], - // Only set if there were info-level annnotations while executing the request. + // Only set if there were info-level annotations while executing the request. "infos": [""] } ``` @@ -692,6 +692,7 @@ $ curl http://localhost:9090/api/v1/targets "__scrape_timeout__": "10s", "job": "node" }, + "scrapePool": "node" } ] } diff --git a/documentation/examples/remote_storage/go.mod b/documentation/examples/remote_storage/go.mod index 541a8b382d..b8a1003839 100644 --- a/documentation/examples/remote_storage/go.mod +++ b/documentation/examples/remote_storage/go.mod @@ -1,13 +1,13 @@ module github.com/prometheus/prometheus/documentation/examples/remote_storage -go 1.22.7 +go 1.23.0 require ( github.com/alecthomas/kingpin/v2 v2.4.0 github.com/gogo/protobuf v1.3.2 github.com/golang/snappy v0.0.4 github.com/influxdata/influxdb-client-go/v2 v2.14.0 - github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_golang v1.21.0 github.com/prometheus/common v0.62.0 github.com/prometheus/prometheus v1.99.0 github.com/stretchr/testify v1.10.0 @@ -37,7 +37,7 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/documentation/examples/remote_storage/go.sum b/documentation/examples/remote_storage/go.sum index bea6b8e68b..5f0ec55416 100644 --- a/documentation/examples/remote_storage/go.sum +++ b/documentation/examples/remote_storage/go.sum @@ -194,8 +194,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -262,8 +262,8 @@ 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.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= +github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= 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= diff --git a/documentation/examples/remote_storage/remote_storage_adapter/influxdb/client_test.go b/documentation/examples/remote_storage/remote_storage_adapter/influxdb/client_test.go index 3f756a9be4..f78d4db794 100644 --- a/documentation/examples/remote_storage/remote_storage_adapter/influxdb/client_test.go +++ b/documentation/examples/remote_storage/remote_storage_adapter/influxdb/client_test.go @@ -72,7 +72,7 @@ testmetric,test_label=test_label_value2 value=5.1234 123456789123 ` server := httptest.NewServer(http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(_ http.ResponseWriter, r *http.Request) { require.Equal(t, http.MethodPost, r.Method, "Unexpected method.") require.Equal(t, "/api/v2/write", r.URL.Path, "Unexpected path.") b, err := io.ReadAll(r.Body) diff --git a/go.mod b/go.mod index ac4e3f1ac6..3466b72a5c 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,16 @@ module github.com/prometheus/prometheus -go 1.22.7 +go 1.23.0 toolchain go1.23.4 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 github.com/Code-Hex/go-generics-cache v1.5.1 - github.com/KimMachineGun/automemlimit v0.7.0 + github.com/KimMachineGun/automemlimit v0.7.1 github.com/alecthomas/kingpin/v2 v2.4.0 github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b github.com/aws/aws-sdk-go v1.55.6 @@ -18,9 +18,9 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 github.com/dennwc/varint v1.0.0 github.com/digitalocean/godo v1.136.0 - github.com/docker/docker v27.5.1+incompatible + github.com/docker/docker v28.0.1+incompatible github.com/edsrzf/mmap-go v1.2.0 - github.com/envoyproxy/go-control-plane/envoy v1.32.3 + github.com/envoyproxy/go-control-plane/envoy v1.32.4 github.com/envoyproxy/protoc-gen-validate v1.2.1 github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb github.com/fsnotify/fsnotify v1.8.0 @@ -28,18 +28,18 @@ require ( github.com/go-zookeeper/zk v1.0.4 github.com/gogo/protobuf v1.3.2 github.com/golang/snappy v0.0.4 - github.com/google/go-cmp v0.6.0 + github.com/google/go-cmp v0.7.0 github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad github.com/google/uuid v1.6.0 - github.com/gophercloud/gophercloud/v2 v2.4.0 + github.com/gophercloud/gophercloud/v2 v2.6.0 github.com/grafana/regexp v0.0.0-20240607082908-2cb410fa05da github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/hashicorp/consul/api v1.31.0 + github.com/hashicorp/consul/api v1.31.2 github.com/hashicorp/nomad/api v0.0.0-20241218080744-e3ac00f30eec - github.com/hetznercloud/hcloud-go/v2 v2.19.0 + github.com/hetznercloud/hcloud-go/v2 v2.19.1 github.com/ionos-cloud/sdk-go/v6 v6.3.2 github.com/json-iterator/go v1.1.12 - github.com/klauspost/compress v1.17.11 + github.com/klauspost/compress v1.18.0 github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b github.com/linode/linodego v1.47.0 github.com/miekg/dns v1.1.63 @@ -47,69 +47,69 @@ require ( github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 github.com/oklog/run v1.1.0 - github.com/oklog/ulid v1.3.1 - github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.118.0 - github.com/ovh/go-ovh v1.6.0 + github.com/oklog/ulid/v2 v2.1.0 + github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.121.0 + github.com/ovh/go-ovh v1.7.0 github.com/prometheus/alertmanager v0.28.0 github.com/prometheus/client_golang v1.21.0-rc.0 github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.62.0 + github.com/prometheus/common v0.63.0 github.com/prometheus/common/assets v0.2.0 - github.com/prometheus/exporter-toolkit v0.13.2 + github.com/prometheus/exporter-toolkit v0.14.0 github.com/prometheus/sigv4 v0.1.2 - github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 + github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32 github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c github.com/stretchr/testify v1.10.0 github.com/vultr/govultr/v2 v2.17.2 - go.opentelemetry.io/collector/component v0.118.0 - go.opentelemetry.io/collector/consumer v1.24.0 - go.opentelemetry.io/collector/pdata v1.24.0 - go.opentelemetry.io/collector/processor v0.118.0 - go.opentelemetry.io/collector/semconv v0.118.0 - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.59.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 - go.opentelemetry.io/otel v1.34.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 - go.opentelemetry.io/otel/metric v1.34.0 - go.opentelemetry.io/otel/sdk v1.34.0 - go.opentelemetry.io/otel/trace v1.34.0 + go.opentelemetry.io/collector/component v1.27.0 + go.opentelemetry.io/collector/consumer v1.27.0 + go.opentelemetry.io/collector/pdata v1.27.0 + go.opentelemetry.io/collector/processor v0.121.0 + go.opentelemetry.io/collector/semconv v0.121.0 + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 + go.opentelemetry.io/otel v1.35.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 + go.opentelemetry.io/otel/metric v1.35.0 + go.opentelemetry.io/otel/sdk v1.35.0 + go.opentelemetry.io/otel/trace v1.35.0 go.uber.org/atomic v1.11.0 go.uber.org/automaxprocs v1.6.0 go.uber.org/goleak v1.3.0 go.uber.org/multierr v1.11.0 - golang.org/x/oauth2 v0.25.0 - golang.org/x/sync v0.10.0 - golang.org/x/sys v0.29.0 - golang.org/x/text v0.21.0 - golang.org/x/tools v0.29.0 - google.golang.org/api v0.219.0 - google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f - google.golang.org/grpc v1.70.0 - google.golang.org/protobuf v1.36.4 + golang.org/x/oauth2 v0.27.0 + golang.org/x/sync v0.12.0 + golang.org/x/sys v0.30.0 + golang.org/x/text v0.23.0 + golang.org/x/tools v0.30.0 + google.golang.org/api v0.224.0 + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a + google.golang.org/grpc v1.71.0 + google.golang.org/protobuf v1.36.5 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.31.3 - k8s.io/apimachinery v0.31.3 - k8s.io/client-go v0.31.3 + k8s.io/api v0.32.2 + k8s.io/apimachinery v0.32.2 + k8s.io/client-go v0.32.2 k8s.io/klog v1.0.0 k8s.io/klog/v2 v2.130.1 ) require ( - cloud.google.com/go/auth v0.14.0 // indirect + cloud.google.com/go/auth v0.15.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 // indirect github.com/DmitriyVTitov/size v1.5.0 github.com/Microsoft/go-winio v0.6.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 // indirect + github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 // indirect github.com/containerd/log v0.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -134,17 +134,18 @@ require ( github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect github.com/go-resty/resty/v2 v2.16.3 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect - github.com/golang/glog v1.2.3 // indirect + github.com/golang/glog v1.2.4 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.9 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.5 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect github.com/hashicorp/cronexpr v1.1.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -155,26 +156,31 @@ require ( github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/serf v0.10.1 // indirect - github.com/imdario/mergo v0.3.6 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect + github.com/knadh/koanf/maps v0.1.1 // indirect + github.com/knadh/koanf/providers/confmap v0.1.0 // indirect + github.com/knadh/koanf/v2 v2.1.2 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/vsock v1.2.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.118.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.118.0 // indirect + github.com/oklog/ulid v1.3.1 + github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.121.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.121.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect @@ -189,25 +195,26 @@ require ( github.com/xhit/go-str2duration/v2 v2.1.0 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.118.0 // indirect - go.opentelemetry.io/collector/pipeline v0.118.0 // indirect + go.opentelemetry.io/collector/confmap v1.27.0 // indirect + go.opentelemetry.io/collector/confmap/xconfmap v0.121.0 // indirect + go.opentelemetry.io/collector/pipeline v0.121.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.32.0 // indirect - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/net v0.34.0 // indirect - golang.org/x/term v0.28.0 // indirect - golang.org/x/time v0.9.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 // indirect + golang.org/x/crypto v0.35.0 // indirect + golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/term v0.29.0 // indirect + golang.org/x/time v0.10.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gotest.tools/v3 v3.0.3 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 6cb2b83b05..4c2f5c41aa 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,17 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/auth v0.14.0 h1:A5C4dKV/Spdvxcl0ggWwWEzzP7AZMJSEIgrkngwhGYM= -cloud.google.com/go/auth v0.14.0/go.mod h1:CYsoRL1PdiDuqeQpZE0bP2pnPrGqFcOkI0nldEQis+A= +cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps= +cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8= cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1/go.mod h1:75I/mXtme1JyWFtz8GocPHVFyH421IBoZErnO16dd0k= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1 h1:Bk5uOhSAenHyR5P61D/NzeQCv+4fEVV8mOkJ82NqpWw= -github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.1/go.mod h1:QZ4pw3or1WPmRBxf0cHd1tknzrT54WPBOQoGutCPvSU= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= @@ -26,16 +26,16 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 h1:H5xDQaE3XowWfhZRUpnfC+rGZMEVoSiji+b+/HFAPU4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU= github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DmitriyVTitov/size v1.5.0 h1:/PzqxYrOyOUX1BXj6J9OuVRVGe+66VL4D9FlUaW515g= github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0= -github.com/KimMachineGun/automemlimit v0.7.0 h1:7G06p/dMSf7G8E6oq+f2uOPuVncFyIlDI/pBWK49u88= -github.com/KimMachineGun/automemlimit v0.7.0/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM= +github.com/KimMachineGun/automemlimit v0.7.1 h1:QcG/0iCOLChjfUweIMC3YL5Xy9C3VBeNmCZHrZfJMBw= +github.com/KimMachineGun/automemlimit v0.7.1/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= @@ -74,8 +74,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= -github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 h1:boJj011Hh+874zpIySeApCX4GeOjPl9qhRF3QuIZq+Q= +github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/colega/go-yaml-yaml v0.0.0-20220720105220-255a8d16d094 h1:FpZSn61BWXbtyH68+uSv416veEswX1M2HRyQfdHnOyQ= github.com/colega/go-yaml-yaml v0.0.0-20220720105220-255a8d16d094/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -101,8 +101,8 @@ github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8= -github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= +github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -116,8 +116,8 @@ github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane/envoy v1.32.3 h1:hVEaommgvzTjTd4xCaFd+kEQ2iYBtGxP6luyLrx6uOk= -github.com/envoyproxy/go-control-plane/envoy v1.32.3/go.mod h1:F6hWupPfh75TBXGKA++MCT/CZHFq5r9/uwt/kQYkZfE= +github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= @@ -180,8 +180,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.3 h1:oDTdz9f5VGVVNGu/Q7UXKWYsD0873HXLHdJUNBsSEKM= -github.com/golang/glog v1.2.3/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= +github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -204,8 +204,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -218,22 +218,22 @@ github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/enterprise-certificate-proxy v0.3.5 h1:VgzTY2jogw3xt39CusEnFJWm7rlsq5yL5q9XdLOuP5g= +github.com/googleapis/enterprise-certificate-proxy v0.3.5/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= -github.com/gophercloud/gophercloud/v2 v2.4.0 h1:XhP5tVEH3ni66NSNK1+0iSO6kaGPH/6srtx6Cr+8eCg= -github.com/gophercloud/gophercloud/v2 v2.4.0/go.mod h1:uJWNpTgJPSl2gyzJqcU/pIAhFUWvIkp8eE8M15n9rs4= +github.com/gophercloud/gophercloud/v2 v2.6.0 h1:XJKQ0in3iHOZHVAFMXq/OhjCuvvG+BKR0unOqRfG1EI= +github.com/gophercloud/gophercloud/v2 v2.6.0/go.mod h1:Ki/ILhYZr/5EPebrPL9Ej+tUg4lqx71/YH2JWVeU+Qk= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grafana/regexp v0.0.0-20240607082908-2cb410fa05da h1:BML5sNe+bw2uO8t8cQSwe5QhvoP04eHPF7bnaQma0Kw= github.com/grafana/regexp v0.0.0-20240607082908-2cb410fa05da/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= -github.com/hashicorp/consul/api v1.31.0 h1:32BUNLembeSRek0G/ZAM6WNfdEwYdYo8oQ4+JoqGkNQ= -github.com/hashicorp/consul/api v1.31.0/go.mod h1:2ZGIiXM3A610NmDULmCHd/aqBJj8CkMfOhswhOafxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/hashicorp/consul/api v1.31.2 h1:NicObVJHcCmyOIl7Z9iHPvvFrocgTYo9cITSGg0/7pw= +github.com/hashicorp/consul/api v1.31.2/go.mod h1:Z8YgY0eVPukT/17ejW+l+C7zJmKwgPHtjU1q16v/Y40= github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= @@ -285,10 +285,8 @@ github.com/hashicorp/nomad/api v0.0.0-20241218080744-e3ac00f30eec h1:+YBzb977Vrm github.com/hashicorp/nomad/api v0.0.0-20241218080744-e3ac00f30eec/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hetznercloud/hcloud-go/v2 v2.19.0 h1:crqbWMywudvlPLLczFf2hBpTPIATjrWMmwfiKSTpUt0= -github.com/hetznercloud/hcloud-go/v2 v2.19.0/go.mod h1:r5RTzv+qi8IbLcDIskTzxkFIji7Ovc8yNgepQR9M+UA= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/hetznercloud/hcloud-go/v2 v2.19.1 h1:UU/7h3uc/rdgspM8xkQF7wokmwZXePWDXcLqrQRRzzY= +github.com/hetznercloud/hcloud-go/v2 v2.19.1/go.mod h1:r5RTzv+qi8IbLcDIskTzxkFIji7Ovc8yNgepQR9M+UA= github.com/ionos-cloud/sdk-go/v6 v6.3.2 h1:2mUmrZZz6cPyT9IRX0T8fBLc/7XU/eTxP2Y5tS7/09k= github.com/ionos-cloud/sdk-go/v6 v6.3.2/go.mod h1:SXrO9OGyWjd2rZhAhEpdYN6VUAODzzqRdqA9BCviQtI= github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww= @@ -312,8 +310,8 @@ github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKu github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU= @@ -399,29 +397,32 @@ github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= -github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.118.0 h1:PbknCwTbeTz8GNSfN4fOIp50YCDO19s1IAp6PGFcdpA= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.118.0/go.mod h1:cOY+YDFtxJH3eQzJDObvWFFSIvD2AstG5MZ9t8wqusQ= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.118.0 h1:DSoYrOjLv23HXpx72hl61br4ZZTj6dqtwZSGoypKWIA= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.118.0/go.mod h1:nR+r7aAbsktscJk4fGmzljblbZBMaiZcIWeKbXV+HmY= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.118.0 h1:aUTSkzJExtrlHN32g8hX/cRNEo2ZmucPg+vwPqOYvhg= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.118.0/go.mod h1:a3sewj4nEozMwcNwZTHPzddS+1BnA6BaAkO/CRIGHVU= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.118.0 h1:RZszYLp7sVMOD1rppjY+fP2PQh5qNAh5U6RoQNvd4Rg= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.118.0/go.mod h1:5i928mwS+Ojv41l3/IxcyK1SCy6WnpL3wjLWKDb4YKQ= +github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.121.0 h1:I+F6xdXQsiXXdce7yjHN+y4LX5MrZI1kNmhBunJffdA= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.121.0/go.mod h1:cRh3l2emFBwW96dHnlPLr1psbEYjYJmn5qFujOkbfRo= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.121.0 h1:efEcUMbyFWBx56TQDz2IMsuI0kQ5g8Im0DjQc9w9HBU= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.121.0/go.mod h1:9ghLP9djsDo5xzmzkADqeJjZb3l92XIRhpAz/ToX2QM= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.121.0 h1:D7mQQKd4rncv3PSsbDGayNENqmVwN1dFvPo3wHFzhI4= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.121.0/go.mod h1:swPiDfFHEiy9x2TwNO3uexCkwppLWfPRVoJdpJvKIQE= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.121.0 h1:+wj+Sw08WDdL/9lD4OUy1PFgQMsiyLuSmlmb3HbKPv4= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/deltatocumulativeprocessor v0.121.0/go.mod h1:YczZl2MmjOUdg5eXg+fAW0my/EG+77b27ue6vj7xPHU= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI= -github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= +github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw= +github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -452,12 +453,12 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= +github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM= github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= -github.com/prometheus/exporter-toolkit v0.13.2 h1:Z02fYtbqTMy2i/f+xZ+UK5jy/bl1Ex3ndzh06T/Q9DQ= -github.com/prometheus/exporter-toolkit v0.13.2/go.mod h1:tCqnfx21q6qN1KA4U3Bfb8uWzXfijIrJz3/kTIqMV7g= +github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg= +github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= @@ -471,8 +472,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dulL25rKloGadb3vm770= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32 h1:4+LP7qmsLSGbmc66m1s5dKRMBwztRppfxFKlYqYte/c= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.32/go.mod h1:kzh+BSAvpoyHHdHBCDhmSWtBc1NbLMZ2lWHqnBoxFks= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shoenig/test v1.7.1 h1:UJcjSAI3aUKx52kfcfhblgyhZceouhvvs3OYdWgn+PY= @@ -515,58 +516,58 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector/component v0.118.0 h1:sSO/ObxJ+yH77Z4DmT1mlSuxhbgUmY1ztt7xCA1F/8w= -go.opentelemetry.io/collector/component v0.118.0/go.mod h1:LUJ3AL2b+tmFr3hZol3hzKzCMvNdqNq0M5CF3SWdv4M= -go.opentelemetry.io/collector/component/componentstatus v0.118.0 h1:1aCIdUjqz0noKNQr1v04P+lwF89Lkua5U7BhH9IAxkE= -go.opentelemetry.io/collector/component/componentstatus v0.118.0/go.mod h1:ynO1Nyj0t1h6x/djIMJy35bhnnWEc2mlQaFgDNUO504= -go.opentelemetry.io/collector/component/componenttest v0.118.0 h1:knEHckoiL2fEWSIc0iehg39zP4IXzi9sHa45O+oxKo8= -go.opentelemetry.io/collector/component/componenttest v0.118.0/go.mod h1:aHc7t7zVwCpbhrWIWY+GMuaMxMCUP8C8P7pJOt8r/vU= -go.opentelemetry.io/collector/config/configtelemetry v0.118.0 h1:UlN46EViG2X42odWtXgWaqY7Y01ZKpsnswSwXTWx5mM= -go.opentelemetry.io/collector/config/configtelemetry v0.118.0/go.mod h1:SlBEwQg0qly75rXZ6W1Ig8jN25KBVBkFIIAUI1GiAAE= -go.opentelemetry.io/collector/confmap v1.24.0 h1:UUHVhkDCsVw14jPOarug9PDQE2vaB2ELPWMr7ARFBCA= -go.opentelemetry.io/collector/confmap v1.24.0/go.mod h1:Rrhs+MWoaP6AswZp+ReQ2VO9dfOfcUjdjiSHBsG+nec= -go.opentelemetry.io/collector/consumer v1.24.0 h1:7DeyBm9qdr1EPuCfPjWyChPK16DbVc0wZeSa9LZprFU= -go.opentelemetry.io/collector/consumer v1.24.0/go.mod h1:0G6jvZprIp4dpKMD1ZxCjriiP9GdFvFMObsQEtTk71s= -go.opentelemetry.io/collector/consumer/consumertest v0.118.0 h1:8AAS9ejQapP1zqt0+cI6u+AUBheT3X0171N9WtXWsVY= -go.opentelemetry.io/collector/consumer/consumertest v0.118.0/go.mod h1:spRM2wyGr4QZzqMHlLmZnqRCxqXN4Wd0piogC4Qb5PQ= -go.opentelemetry.io/collector/consumer/xconsumer v0.118.0 h1:guWnzzRqgCInjnYlOQ1BPrimppNGIVvnknAjlIbWXuY= -go.opentelemetry.io/collector/consumer/xconsumer v0.118.0/go.mod h1:C5V2d6Ys/Fi6k3tzjBmbdZ9v3J/rZSAMlhx4KVcMIIg= -go.opentelemetry.io/collector/pdata v1.24.0 h1:D6j92eAzmAbQgivNBUnt8r9juOl8ugb+ihYynoFZIEg= -go.opentelemetry.io/collector/pdata v1.24.0/go.mod h1:cf3/W9E/uIvPS4MR26SnMFJhraUCattzzM6qusuONuc= -go.opentelemetry.io/collector/pdata/pprofile v0.118.0 h1:VK/fr65VFOwEhsSGRPj5c3lCv0yIK1Kt0sZxv9WZBb8= -go.opentelemetry.io/collector/pdata/pprofile v0.118.0/go.mod h1:eJyP/vBm179EghV3dPSnamGAWQwLyd+4z/3yG54YFoQ= -go.opentelemetry.io/collector/pdata/testdata v0.118.0 h1:5N0w1SX9KIRkwvtkrpzQgXy9eGk3vfNG0ds6mhEPMIM= -go.opentelemetry.io/collector/pdata/testdata v0.118.0/go.mod h1:UY+GHV5bOC1BnFburOZ0wiHReJj1XbW12mi2Ogbc5Lw= -go.opentelemetry.io/collector/pipeline v0.118.0 h1:RI1DMe7L0+5hGkx0EDGxG00TaJoh96MEQppgOlGx1Oc= -go.opentelemetry.io/collector/pipeline v0.118.0/go.mod h1:qE3DmoB05AW0C3lmPvdxZqd/H4po84NPzd5MrqgtL74= -go.opentelemetry.io/collector/processor v0.118.0 h1:NlqWiTTpPP+EPbrqTcNP9nh/4O4/9U9RGWVB49xo4ws= -go.opentelemetry.io/collector/processor v0.118.0/go.mod h1:Y8OD7wk51oPuBqrbn1qXIK91AbprRHP76hlvEzC24U4= -go.opentelemetry.io/collector/processor/processortest v0.118.0 h1:VfTLHuIaJWGyUmrvAOvf63gPMf1vAW68/jtJClEsKtU= -go.opentelemetry.io/collector/processor/processortest v0.118.0/go.mod h1:ZFWxsSoafGNOEk83FtGz43M5ypUzAOvGnfT0aQTDHdU= -go.opentelemetry.io/collector/processor/xprocessor v0.118.0 h1:M/EMhPRbadHLpv7g99fBjfgyuYexBZmgQqb2vjTXjvM= -go.opentelemetry.io/collector/processor/xprocessor v0.118.0/go.mod h1:lkoQoCv2Cz+C0kf2VHgBUDYWDecZLLeaHEvHDXbBCXU= -go.opentelemetry.io/collector/semconv v0.118.0 h1:V4vlMIK7TIaemrrn2VawvQPwruIKpj7Xgw9P5+BL56w= -go.opentelemetry.io/collector/semconv v0.118.0/go.mod h1:N6XE8Q0JKgBN2fAhkUQtqK9LT7rEGR6+Wu/Rtbal1iI= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.59.0 h1:iQZYNQ7WwIcYXzOPR46FQv9O0dS1PW16RjvR0TjDOe8= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.59.0/go.mod h1:54CaSNqYEXvpzDh8KPjiMVoWm60t5R0dZRt0leEPgAs= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= -go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/collector/component v1.27.0 h1:6wk0K23YT9lSprX8BH9x5w8ssAORE109ekH/ix2S614= +go.opentelemetry.io/collector/component v1.27.0/go.mod h1:fIyBHoa7vDyZL3Pcidgy45cx24tBe7iHWne097blGgo= +go.opentelemetry.io/collector/component/componentstatus v0.121.0 h1:G4KqBUuAqnQ1kB3fUxXPwspjwnhGZzdArlO7vc343og= +go.opentelemetry.io/collector/component/componentstatus v0.121.0/go.mod h1:ufRv8q15XNdbr9nNzdepMHlLl2aC3NHQgecCzp5VRns= +go.opentelemetry.io/collector/component/componenttest v0.121.0 h1:4q1/7WnP9LPKaY4HAd8/OkzhllZpRACKAOlWsqbrzqc= +go.opentelemetry.io/collector/component/componenttest v0.121.0/go.mod h1:H7bEXDPMYNeWcHal0xyKlVfRPByVxale7hCJ+Myjq3Q= +go.opentelemetry.io/collector/confmap v1.27.0 h1:OIjPcjij1NxkVQsQVmHro4+t1eYNFiUGib9+J9YBZhM= +go.opentelemetry.io/collector/confmap v1.27.0/go.mod h1:tmOa6iw3FJsEgfBHKALqvcdfRtf71JZGor0wSM5MoH8= +go.opentelemetry.io/collector/confmap/xconfmap v0.121.0 h1:pZ7SOl/i3kUIPdUwIeHHsYqzOHNLCwiyXZnwQ7rLO3E= +go.opentelemetry.io/collector/confmap/xconfmap v0.121.0/go.mod h1:YI1Sp8mbYro/H3rqH4csTq68VUuie5WVb7LI1o5+tVc= +go.opentelemetry.io/collector/consumer v1.27.0 h1:JoXdoCeFDJG3d9TYrKHvTT4eBhzKXDVTkWW5mDfnLiY= +go.opentelemetry.io/collector/consumer v1.27.0/go.mod h1:1B/+kTDUI6u3mCIOAkm5ityIpv5uC0Ll78IA50SNZ24= +go.opentelemetry.io/collector/consumer/consumertest v0.121.0 h1:EIJPAXQY0w9j1k/e5OzJqOYVEr6WljKpJBjgkkp/hWw= +go.opentelemetry.io/collector/consumer/consumertest v0.121.0/go.mod h1:Hmj+TizzsLU0EmS2n/rJYScOybNmm3mrAjis6ed7qTw= +go.opentelemetry.io/collector/consumer/xconsumer v0.121.0 h1:/FJ7L6+G++FvktXc/aBnnYDIKLoYsWLh0pKbvzFFwF8= +go.opentelemetry.io/collector/consumer/xconsumer v0.121.0/go.mod h1:KKy8Qg/vOnyseoi7A9/x1a1oEqSmf0WBHkJFlnQH0Ow= +go.opentelemetry.io/collector/pdata v1.27.0 h1:66yI7FYkUDia74h48Fd2/KG2Vk8DxZnGw54wRXykCEU= +go.opentelemetry.io/collector/pdata v1.27.0/go.mod h1:18e8/xDZsqyj00h/5HM5GLdJgBzzG9Ei8g9SpNoiMtI= +go.opentelemetry.io/collector/pdata/pprofile v0.121.0 h1:DFBelDRsZYxEaSoxSRtseAazsHJfqfC/Yl64uPicl2g= +go.opentelemetry.io/collector/pdata/pprofile v0.121.0/go.mod h1:j/fjrd7ybJp/PXkba92QLzx7hykUVmU8x/WJvI2JWSg= +go.opentelemetry.io/collector/pdata/testdata v0.121.0 h1:FFz+rdb7o6JRZ82Zmp6WKEdKnEMaoF3jLb7F1F21ijg= +go.opentelemetry.io/collector/pdata/testdata v0.121.0/go.mod h1:UhiSwmVpBbuKlPdmhBytiVTHipSz/JO6c4mbD4kWOPg= +go.opentelemetry.io/collector/pipeline v0.121.0 h1:SOiocdyWCJCjWAb96HIxsy9enp2qyQ1NRFo26qyHlCE= +go.opentelemetry.io/collector/pipeline v0.121.0/go.mod h1:TO02zju/K6E+oFIOdi372Wk0MXd+Szy72zcTsFQwXl4= +go.opentelemetry.io/collector/processor v0.121.0 h1:OcLrJ2F17cU0oDtXEYbGvL8vbku/kRQgAafSZ3+8jLY= +go.opentelemetry.io/collector/processor v0.121.0/go.mod h1:BoFEMvPn5/p53eWz+R9cibIxCXzaRZ/RtcBPtvqXNaQ= +go.opentelemetry.io/collector/processor/processortest v0.121.0 h1:1c3mEABELrxdC1obSQjIlfh5jZljJlzUravmzy1Mofo= +go.opentelemetry.io/collector/processor/processortest v0.121.0/go.mod h1:oL4S/eguZ6XTK6IxAQXhXD9yWuRrG5/Maiskbf9HL0o= +go.opentelemetry.io/collector/processor/xprocessor v0.121.0 h1:AiqDKzpEYZpiP9y3RRp4G9ym6fG2f9HByu3yWkSdd2E= +go.opentelemetry.io/collector/processor/xprocessor v0.121.0/go.mod h1:Puk+6YYKyqLVKqpftUXg0blMrd3BlH/Av+oiajp1sHQ= +go.opentelemetry.io/collector/semconv v0.121.0 h1:dtdgh5TsKWGZXIBMsyCMVrY1VgmyWlXHgWx/VH9tL1U= +go.opentelemetry.io/collector/semconv v0.121.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 h1:0tY123n7CdWMem7MOVdKOt0YfshufLCwfE5Bob+hQuM= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0/go.mod h1:CosX/aS4eHnG9D7nESYpV753l4j9q5j3SL/PUYd2lR8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= +go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -584,18 +585,18 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= +golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= +golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -611,12 +612,12 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -624,8 +625,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -654,19 +655,19 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= -golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -677,32 +678,32 @@ golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.219.0 h1:nnKIvxKs/06jWawp2liznTBnMRQBEPpGo7I+oEypTX0= -google.golang.org/api v0.219.0/go.mod h1:K6OmjGm+NtLrIkHxv1U3a0qIf/0JOvAHd5O/6AoyKYE= +google.golang.org/api v0.224.0 h1:Ir4UPtDsNiwIOHdExr3fAj4xZ42QjK7uQte3lORLJwU= +google.golang.org/api v0.224.0/go.mod h1:3V39my2xAGkodXy0vEqcEtkqgw2GtrFL5WuBZlCTCOQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= -google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 h1:91mG8dNTpkC0uChJUQ9zCiRqx3GEEFOWaRZ0mI6Oj2I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e h1:YA5lmSs3zc/5w+xsRcHqpETkaYyK63ivEPzNTcUUlSA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250227231956-55c901821b1e/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= -google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 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= @@ -727,23 +728,23 @@ gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= -k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= -k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= -k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= -k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= +k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw= +k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y= +k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ= +k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA= +k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= -k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= +k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= +sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/model/labels/labels_common.go b/model/labels/labels_common.go index a232eeea5d..005eaa509e 100644 --- a/model/labels/labels_common.go +++ b/model/labels/labels_common.go @@ -104,14 +104,14 @@ func (ls Labels) IsValid(validationScheme model.ValidationScheme) bool { if l.Name == model.MetricNameLabel { // If the default validation scheme has been overridden with legacy mode, // we need to call the special legacy validation checker. - if validationScheme == model.LegacyValidation && model.NameValidationScheme == model.UTF8Validation && !model.IsValidLegacyMetricName(string(model.LabelValue(l.Value))) { + if validationScheme == model.LegacyValidation && !model.IsValidLegacyMetricName(string(model.LabelValue(l.Value))) { return strconv.ErrSyntax } if !model.IsValidMetricName(model.LabelValue(l.Value)) { return strconv.ErrSyntax } } - if validationScheme == model.LegacyValidation && model.NameValidationScheme == model.UTF8Validation { + if validationScheme == model.LegacyValidation { if !model.LabelName(l.Name).IsValidLegacy() || !model.LabelValue(l.Value).IsValid() { return strconv.ErrSyntax } diff --git a/model/labels/labels_test.go b/model/labels/labels_test.go index 06802d6f3e..a2a7734326 100644 --- a/model/labels/labels_test.go +++ b/model/labels/labels_test.go @@ -284,10 +284,9 @@ func TestLabels_IsValid(t *testing.T) { func TestLabels_ValidationModes(t *testing.T) { for _, test := range []struct { - input Labels - globalMode model.ValidationScheme - callMode model.ValidationScheme - expected bool + input Labels + callMode model.ValidationScheme + expected bool }{ { input: FromStrings( @@ -295,9 +294,8 @@ func TestLabels_ValidationModes(t *testing.T) { "hostname", "localhost", "job", "check", ), - globalMode: model.UTF8Validation, - callMode: model.UTF8Validation, - expected: true, + callMode: model.UTF8Validation, + expected: true, }, { input: FromStrings( @@ -305,31 +303,8 @@ func TestLabels_ValidationModes(t *testing.T) { "\xc5 bad utf8", "localhost", "job", "check", ), - globalMode: model.UTF8Validation, - callMode: model.UTF8Validation, - expected: false, - }, - { - // Setting the common model to legacy validation and then trying to check for UTF-8 on a - // per-call basis is not supported. - input: FromStrings( - "__name__", "test.utf8.metric", - "hostname", "localhost", - "job", "check", - ), - globalMode: model.LegacyValidation, - callMode: model.UTF8Validation, - expected: false, - }, - { - input: FromStrings( - "__name__", "test", - "hostname", "localhost", - "job", "check", - ), - globalMode: model.LegacyValidation, - callMode: model.LegacyValidation, - expected: true, + callMode: model.UTF8Validation, + expected: false, }, { input: FromStrings( @@ -337,9 +312,8 @@ func TestLabels_ValidationModes(t *testing.T) { "hostname", "localhost", "job", "check", ), - globalMode: model.UTF8Validation, - callMode: model.LegacyValidation, - expected: false, + callMode: model.LegacyValidation, + expected: false, }, { input: FromStrings( @@ -347,12 +321,10 @@ func TestLabels_ValidationModes(t *testing.T) { "host.name", "localhost", "job", "check", ), - globalMode: model.UTF8Validation, - callMode: model.LegacyValidation, - expected: false, + callMode: model.LegacyValidation, + expected: false, }, } { - model.NameValidationScheme = test.globalMode require.Equal(t, test.expected, test.input.IsValid(test.callMode)) } } diff --git a/model/labels/regexp.go b/model/labels/regexp.go index edad614a01..5fe49fc9a8 100644 --- a/model/labels/regexp.go +++ b/model/labels/regexp.go @@ -1037,7 +1037,7 @@ func optimizeEqualOrPrefixStringMatchers(input StringMatcher, threshold int) Str return true } - analysePrefixMatcherCallback := func(prefix string, prefixCaseSensitive bool, matcher StringMatcher) bool { + analysePrefixMatcherCallback := func(prefix string, prefixCaseSensitive bool, _ StringMatcher) bool { // Ensure we don't have mixed case sensitivity. if caseSensitiveSet && caseSensitive != prefixCaseSensitive { return false @@ -1072,7 +1072,7 @@ func optimizeEqualOrPrefixStringMatchers(input StringMatcher, threshold int) Str findEqualOrPrefixStringMatchers(input, func(matcher *equalStringMatcher) bool { multiMatcher.add(matcher.s) return true - }, func(prefix string, prefixCaseSensitive bool, matcher StringMatcher) bool { + }, func(prefix string, _ bool, matcher StringMatcher) bool { multiMatcher.addPrefix(prefix, caseSensitive, matcher) return true }) diff --git a/model/labels/regexp_test.go b/model/labels/regexp_test.go index 4826c0fe4a..7dd217c3ad 100644 --- a/model/labels/regexp_test.go +++ b/model/labels/regexp_test.go @@ -1355,7 +1355,7 @@ func TestFindEqualOrPrefixStringMatchers(t *testing.T) { ok = findEqualOrPrefixStringMatchers(input, func(matcher *equalStringMatcher) bool { matches = append(matches, match{matcher.s, matcher.caseSensitive}) return true - }, func(prefix string, prefixCaseSensitive bool, right StringMatcher) bool { + }, func(prefix string, prefixCaseSensitive bool, _ StringMatcher) bool { matches = append(matches, match{prefix, prefixCaseSensitive}) return true }) diff --git a/model/relabel/relabel.go b/model/relabel/relabel.go index 1373484426..70daef426f 100644 --- a/model/relabel/relabel.go +++ b/model/relabel/relabel.go @@ -135,11 +135,6 @@ func (c *Config) Validate() error { // Design escaping mechanism to allow that, once valid use case appears. return model.LabelName(value).IsValid() } - if model.NameValidationScheme == model.LegacyValidation { - isValidLabelNameWithRegexVarFn = func(value string) bool { - return relabelTargetLegacy.MatchString(value) - } - } if c.Action == Replace && varInRegexTemplate(c.TargetLabel) && !isValidLabelNameWithRegexVarFn(c.TargetLabel) { return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action) } diff --git a/model/textparse/benchmark_test.go b/model/textparse/benchmark_test.go index ce7845ed03..9abda92a26 100644 --- a/model/textparse/benchmark_test.go +++ b/model/textparse/benchmark_test.go @@ -262,3 +262,77 @@ func readTestdataFile(tb testing.TB, file string) []byte { require.NoError(tb, err) return buf } + +/* + export bench=v1 && go test ./model/textparse/... \ + -run '^$' -bench '^BenchmarkCreatedTimestampPromProto' \ + -benchtime 2s -count 6 -cpu 2 -benchmem -timeout 999m \ + | tee ${bench}.txt +*/ +func BenchmarkCreatedTimestampPromProto(b *testing.B) { + data := createTestProtoBuf(b).Bytes() + + st := labels.NewSymbolTable() + p := NewProtobufParser(data, true, st) + + found := false +Inner: + for { + t, err := p.Next() + switch t { + case EntryInvalid: + b.Fatal(err) + case EntryType: + m, _ := p.Type() + if string(m) == "go_memstats_alloc_bytes_total" { + found = true + break Inner + } + // Parser impl requires this (bug?) + case EntryHistogram: + _, _, _, _ = p.Histogram() + case EntrySeries: + _, _, _ = p.Series() + } + } + require.True(b, found) + b.Run("case=no-ct", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if p.CreatedTimestamp() != 0 { + b.Fatal("should be nil") + } + } + }) + + found = false +Inner2: + for { + t, err := p.Next() + switch t { + case EntryInvalid: + b.Fatal(err) + case EntryType: + m, _ := p.Type() + if string(m) == "test_counter_with_createdtimestamp" { + found = true + break Inner2 + } + case EntryHistogram: + _, _, _, _ = p.Histogram() + case EntrySeries: + _, _, _ = p.Series() + } + } + require.True(b, found) + b.Run("case=ct", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if p.CreatedTimestamp() == 0 { + b.Fatal("should be not nil") + } + } + }) +} diff --git a/model/textparse/interface.go b/model/textparse/interface.go index 58cdf52a03..6409e37232 100644 --- a/model/textparse/interface.go +++ b/model/textparse/interface.go @@ -29,12 +29,18 @@ import ( type Parser interface { // Series returns the bytes of a series with a simple float64 as a // value, the timestamp if set, and the value of the current sample. + // TODO(bwplotka): Similar to CreatedTimestamp, have ts == 0 meaning no timestamp provided. + // We already accepted in many places (PRW, proto parsing histograms) that 0 timestamp is not a + // a valid timestamp. If needed it can be represented as 0+1ms. Series() ([]byte, *int64, float64) // Histogram returns the bytes of a series with a sparse histogram as a // value, the timestamp if set, and the histogram in the current sample. // Depending on the parsed input, the function returns an (integer) Histogram // or a FloatHistogram, with the respective other return value being nil. + // TODO(bwplotka): Similar to CreatedTimestamp, have ts == 0 meaning no timestamp provided. + // We already accepted in many places (PRW, proto parsing histograms) that 0 timestamp is not a + // a valid timestamp. If needed it can be represented as 0+1ms. Histogram() ([]byte, *int64, *histogram.Histogram, *histogram.FloatHistogram) // Help returns the metric name and help text in the current entry. @@ -69,11 +75,9 @@ type Parser interface { Exemplar(l *exemplar.Exemplar) bool // CreatedTimestamp returns the created timestamp (in milliseconds) for the - // current sample. It returns nil if it is unknown e.g. if it wasn't set, + // current sample. It returns 0 if it is unknown e.g. if it wasn't set or // if the scrape protocol or metric type does not support created timestamps. - // Assume the CreatedTimestamp returned pointer is only valid until - // the Next iteration. - CreatedTimestamp() *int64 + CreatedTimestamp() int64 // Next advances the parser to the next sample. // It returns (EntryInvalid, io.EOF) if no samples were read. diff --git a/model/textparse/interface_test.go b/model/textparse/interface_test.go index a5ca12859e..701772b4cb 100644 --- a/model/textparse/interface_test.go +++ b/model/textparse/interface_test.go @@ -195,7 +195,7 @@ type parsedEntry struct { lset labels.Labels t *int64 es []exemplar.Exemplar - ct *int64 + ct int64 // In EntryType. typ model.MetricType @@ -255,11 +255,8 @@ func testParse(t *testing.T, p Parser) (ret []parsedEntry) { } got.m = string(m) p.Labels(&got.lset) + got.ct = p.CreatedTimestamp() - // Parser reuses int pointer. - if ct := p.CreatedTimestamp(); ct != nil { - got.ct = int64p(*ct) - } for e := (exemplar.Exemplar{}); p.Exemplar(&e); { got.es = append(got.es, e) } diff --git a/model/textparse/nhcbparse.go b/model/textparse/nhcbparse.go index d8c2317980..ea4941f2e2 100644 --- a/model/textparse/nhcbparse.go +++ b/model/textparse/nhcbparse.go @@ -83,7 +83,7 @@ type NHCBParser struct { fhNHCB *histogram.FloatHistogram lsetNHCB labels.Labels exemplars []exemplar.Exemplar - ctNHCB *int64 + ctNHCB int64 metricStringNHCB string // Collates values from the classic histogram series to build @@ -92,7 +92,7 @@ type NHCBParser struct { tempNHCB convertnhcb.TempHistogram tempExemplars []exemplar.Exemplar tempExemplarCount int - tempCT *int64 + tempCT int64 // Remembers the last base histogram metric name (assuming it's // a classic histogram) so we can tell if the next float series @@ -160,7 +160,7 @@ func (p *NHCBParser) Exemplar(ex *exemplar.Exemplar) bool { return p.parser.Exemplar(ex) } -func (p *NHCBParser) CreatedTimestamp() *int64 { +func (p *NHCBParser) CreatedTimestamp() int64 { switch p.state { case stateStart: if p.entry == EntrySeries || p.entry == EntryHistogram { @@ -171,7 +171,7 @@ func (p *NHCBParser) CreatedTimestamp() *int64 { case stateEmitting: return p.ctNHCB } - return nil + return 0 } func (p *NHCBParser) Next() (Entry, error) { @@ -375,6 +375,6 @@ func (p *NHCBParser) processNHCB() bool { } p.tempNHCB.Reset() p.tempExemplarCount = 0 - p.tempCT = nil + p.tempCT = 0 return err == nil } diff --git a/model/textparse/nhcbparse_test.go b/model/textparse/nhcbparse_test.go index f75c7f5677..8a5aa117a9 100644 --- a/model/textparse/nhcbparse_test.go +++ b/model/textparse/nhcbparse_test.go @@ -293,14 +293,14 @@ foobar{quantile="0.99"} 150.1` lset: labels.FromStrings("__name__", "foo_total"), t: int64p(1520879607789), es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, - ct: int64p(1520872607123), + ct: 1520872607123, }, { m: `foo_total{a="b"}`, v: 17.0, lset: labels.FromStrings("__name__", "foo_total", "a", "b"), t: int64p(1520879607789), es: []exemplar.Exemplar{{Labels: labels.FromStrings("id", "counter-test"), Value: 5}}, - ct: int64p(1520872607123), + ct: 1520872607123, }, { m: "bar", help: "Summary with CT at the end, making sure we find CT even if it's multiple lines a far", @@ -311,22 +311,22 @@ foobar{quantile="0.99"} 150.1` m: "bar_count", v: 17.0, lset: labels.FromStrings("__name__", "bar_count"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: "bar_sum", v: 324789.3, lset: labels.FromStrings("__name__", "bar_sum"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: `bar{quantile="0.95"}`, v: 123.7, lset: labels.FromStrings("__name__", "bar", "quantile", "0.95"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: `bar{quantile="0.99"}`, v: 150.0, lset: labels.FromStrings("__name__", "bar", "quantile", "0.99"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: "baz", help: "Histogram with the same objective as above's summary", @@ -344,7 +344,7 @@ foobar{quantile="0.99"} 150.1` CustomValues: []float64{0.0}, // We do not store the +Inf boundary. }, lset: labels.FromStrings("__name__", "baz"), - ct: int64p(1520872609125), + ct: 1520872609125, }, { m: "fizz_created", help: "Gauge which shouldn't be parsed as CT", @@ -372,7 +372,7 @@ foobar{quantile="0.99"} 150.1` CustomValues: []float64{0.0}, // We do not store the +Inf boundary. }, lset: labels.FromStrings("__name__", "something"), - ct: int64p(1520430001000), + ct: 1520430001000, }, { m: `something{a="b"}`, shs: &histogram.Histogram{ @@ -384,7 +384,7 @@ foobar{quantile="0.99"} 150.1` CustomValues: []float64{0.0}, // We do not store the +Inf boundary. }, lset: labels.FromStrings("__name__", "something", "a", "b"), - ct: int64p(1520430002000), + ct: 1520430002000, }, { m: "yum", help: "Summary with _created between sum and quantiles", @@ -395,22 +395,22 @@ foobar{quantile="0.99"} 150.1` m: `yum_count`, v: 20, lset: labels.FromStrings("__name__", "yum_count"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: `yum_sum`, v: 324789.5, lset: labels.FromStrings("__name__", "yum_sum"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: `yum{quantile="0.95"}`, v: 123.7, lset: labels.FromStrings("__name__", "yum", "quantile", "0.95"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: `yum{quantile="0.99"}`, v: 150.0, lset: labels.FromStrings("__name__", "yum", "quantile", "0.99"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: "foobar", help: "Summary with _created as the first line", @@ -421,22 +421,22 @@ foobar{quantile="0.99"} 150.1` m: `foobar_count`, v: 21, lset: labels.FromStrings("__name__", "foobar_count"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: `foobar_sum`, v: 324789.6, lset: labels.FromStrings("__name__", "foobar_sum"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: `foobar{quantile="0.95"}`, v: 123.8, lset: labels.FromStrings("__name__", "foobar", "quantile", "0.95"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: `foobar{quantile="0.99"}`, v: 150.1, lset: labels.FromStrings("__name__", "foobar", "quantile", "0.99"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: "metric", help: "foo\x00bar", @@ -604,14 +604,14 @@ func TestNHCBParser_NoNHCBWhenExponential(t *testing.T) { return "ProtoBuf", factory, []int{1, 2, 3}, parserOptions{useUTF8sep: true, hasCreatedTimeStamp: true} }, func() (string, parserFactory, []int, parserOptions) { - factory := func(keepClassic bool) Parser { + factory := func(_ bool) Parser { input := createTestOpenMetricsHistogram() return NewOpenMetricsParser([]byte(input), labels.NewSymbolTable(), WithOMParserCTSeriesSkipped()) } return "OpenMetrics", factory, []int{1}, parserOptions{hasCreatedTimeStamp: true} }, func() (string, parserFactory, []int, parserOptions) { - factory := func(keepClassic bool) Parser { + factory := func(_ bool) Parser { input := createTestPromHistogram() return NewPromParser([]byte(input), labels.NewSymbolTable()) } @@ -646,9 +646,9 @@ func TestNHCBParser_NoNHCBWhenExponential(t *testing.T) { typ: model.MetricTypeHistogram, }) - var ct *int64 + var ct int64 if options.hasCreatedTimeStamp { - ct = int64p(1000) + ct = 1000 } var bucketForMetric func(string) string @@ -973,7 +973,7 @@ something_bucket{a="b",le="+Inf"} 9 CustomValues: []float64{0.0}, // We do not store the +Inf boundary. }, lset: labels.FromStrings("__name__", "something", "a", "b"), - ct: int64p(1520430002000), + ct: 1520430002000, }, } diff --git a/model/textparse/openmetricsparse.go b/model/textparse/openmetricsparse.go index 2f4d5ab2c5..cea548ccbd 100644 --- a/model/textparse/openmetricsparse.go +++ b/model/textparse/openmetricsparse.go @@ -259,11 +259,11 @@ func (p *OpenMetricsParser) Exemplar(e *exemplar.Exemplar) bool { // CreatedTimestamp returns the created timestamp for a current Metric if exists or nil. // NOTE(Maniktherana): Might use additional CPU/mem resources due to deep copy of parser required for peeking given 1.0 OM specification on _created series. -func (p *OpenMetricsParser) CreatedTimestamp() *int64 { +func (p *OpenMetricsParser) CreatedTimestamp() int64 { if !typeRequiresCT(p.mtype) { // Not a CT supported metric type, fast path. p.ctHashSet = 0 // Use ctHashSet as a single way of telling "empty cache" - return nil + return 0 } var ( @@ -280,7 +280,7 @@ func (p *OpenMetricsParser) CreatedTimestamp() *int64 { currHash := p.seriesHash(&buf, currName) // Check cache, perhaps we fetched something already. if currHash == p.ctHashSet && p.ct > 0 { - return &p.ct + return p.ct } // Create a new lexer to reset the parser once this function is done executing. @@ -310,12 +310,12 @@ func (p *OpenMetricsParser) CreatedTimestamp() *int64 { // spec improvement would help. // TODO: Make sure OM 1.1/2.0 pass CT via metadata or exemplar-like to avoid this. p.resetCTParseValues() - return nil + return 0 } if eType != EntrySeries { // Assume we hit different family, no CT line found. p.resetCTParseValues() - return nil + return 0 } peekedName := p.series[p.offsets[0]-p.start : p.offsets[1]-p.start] @@ -329,14 +329,14 @@ func (p *OpenMetricsParser) CreatedTimestamp() *int64 { if peekedHash != currHash { // Found CT line for a different series, for our series no CT. p.resetCTParseValues() - return nil + return 0 } // All timestamps in OpenMetrics are Unix Epoch in seconds. Convert to milliseconds. // https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#timestamps ct := int64(p.val * 1000.0) p.setCTParseValues(ct, currHash, currName, true) - return &ct + return ct } } diff --git a/model/textparse/openmetricsparse_test.go b/model/textparse/openmetricsparse_test.go index a09c56a7ba..e7261a24c6 100644 --- a/model/textparse/openmetricsparse_test.go +++ b/model/textparse/openmetricsparse_test.go @@ -289,7 +289,7 @@ foobar{quantile="0.99"} 150.1` es: []exemplar.Exemplar{ {Labels: labels.FromStrings("id", "counter-test"), Value: 5}, }, - ct: int64p(1520872607123), + ct: 1520872607123, }, { m: `foo_total{a="b"}`, v: 17.0, @@ -298,12 +298,12 @@ foobar{quantile="0.99"} 150.1` es: []exemplar.Exemplar{ {Labels: labels.FromStrings("id", "counter-test"), Value: 5}, }, - ct: int64p(1520872607123), + ct: 1520872607123, }, { m: `foo_total{le="c"}`, v: 21.0, lset: labels.FromStrings("__name__", "foo_total", "le", "c"), - ct: int64p(1520872621123), + ct: 1520872621123, }, { m: `foo_total{le="1"}`, v: 10.0, @@ -318,22 +318,22 @@ foobar{quantile="0.99"} 150.1` m: "bar_count", v: 17.0, lset: labels.FromStrings("__name__", "bar_count"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: "bar_sum", v: 324789.3, lset: labels.FromStrings("__name__", "bar_sum"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: `bar{quantile="0.95"}`, v: 123.7, lset: labels.FromStrings("__name__", "bar", "quantile", "0.95"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: `bar{quantile="0.99"}`, v: 150.0, lset: labels.FromStrings("__name__", "bar", "quantile", "0.99"), - ct: int64p(1520872608124), + ct: 1520872608124, }, { m: "baz", help: "Histogram with the same objective as above's summary", @@ -344,22 +344,22 @@ foobar{quantile="0.99"} 150.1` m: `baz_bucket{le="0.0"}`, v: 0, lset: labels.FromStrings("__name__", "baz_bucket", "le", "0.0"), - ct: int64p(1520872609125), + ct: 1520872609125, }, { m: `baz_bucket{le="+Inf"}`, v: 17, lset: labels.FromStrings("__name__", "baz_bucket", "le", "+Inf"), - ct: int64p(1520872609125), + ct: 1520872609125, }, { m: `baz_count`, v: 17, lset: labels.FromStrings("__name__", "baz_count"), - ct: int64p(1520872609125), + ct: 1520872609125, }, { m: `baz_sum`, v: 324789.3, lset: labels.FromStrings("__name__", "baz_sum"), - ct: int64p(1520872609125), + ct: 1520872609125, }, { m: "fizz_created", help: "Gauge which shouldn't be parsed as CT", @@ -380,27 +380,27 @@ foobar{quantile="0.99"} 150.1` m: `something_count`, v: 18, lset: labels.FromStrings("__name__", "something_count"), - ct: int64p(1520430001000), + ct: 1520430001000, }, { m: `something_sum`, v: 324789.4, lset: labels.FromStrings("__name__", "something_sum"), - ct: int64p(1520430001000), + ct: 1520430001000, }, { m: `something_bucket{le="0.0"}`, v: 1, lset: labels.FromStrings("__name__", "something_bucket", "le", "0.0"), - ct: int64p(1520430001000), + ct: 1520430001000, }, { m: `something_bucket{le="1"}`, v: 2, lset: labels.FromStrings("__name__", "something_bucket", "le", "1.0"), - ct: int64p(1520430001000), + ct: 1520430001000, }, { m: `something_bucket{le="+Inf"}`, v: 18, lset: labels.FromStrings("__name__", "something_bucket", "le", "+Inf"), - ct: int64p(1520430001000), + ct: 1520430001000, }, { m: "yum", help: "Summary with _created between sum and quantiles", @@ -411,22 +411,22 @@ foobar{quantile="0.99"} 150.1` m: `yum_count`, v: 20, lset: labels.FromStrings("__name__", "yum_count"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: `yum_sum`, v: 324789.5, lset: labels.FromStrings("__name__", "yum_sum"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: `yum{quantile="0.95"}`, v: 123.7, lset: labels.FromStrings("__name__", "yum", "quantile", "0.95"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: `yum{quantile="0.99"}`, v: 150.0, lset: labels.FromStrings("__name__", "yum", "quantile", "0.99"), - ct: int64p(1520430003000), + ct: 1520430003000, }, { m: "foobar", help: "Summary with _created as the first line", @@ -437,22 +437,22 @@ foobar{quantile="0.99"} 150.1` m: `foobar_count`, v: 21, lset: labels.FromStrings("__name__", "foobar_count"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: `foobar_sum`, v: 324789.6, lset: labels.FromStrings("__name__", "foobar_sum"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: `foobar{quantile="0.95"}`, v: 123.8, lset: labels.FromStrings("__name__", "foobar", "quantile", "0.95"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: `foobar{quantile="0.99"}`, v: 150.1, lset: labels.FromStrings("__name__", "foobar", "quantile", "0.99"), - ct: int64p(1520430004000), + ct: 1520430004000, }, { m: "metric", help: "foo\x00bar", @@ -469,12 +469,6 @@ foobar{quantile="0.99"} 150.1` } func TestUTF8OpenMetricsParse(t *testing.T) { - oldValidationScheme := model.NameValidationScheme - model.NameValidationScheme = model.UTF8Validation - defer func() { - model.NameValidationScheme = oldValidationScheme - }() - input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations. # TYPE "go.gc_duration_seconds" summary # UNIT "go.gc_duration_seconds" seconds @@ -507,12 +501,12 @@ quotedexemplar2_count 1 # {"id.thing"="histogram-count-test",other="hello"} 4 m: `{"go.gc_duration_seconds",quantile="0"}`, v: 4.9351e-05, lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.0"), - ct: int64p(1520872607123), + ct: 1520872607123, }, { m: `{"go.gc_duration_seconds",quantile="0.25"}`, v: 7.424100000000001e-05, lset: labels.FromStrings("__name__", "go.gc_duration_seconds", "quantile", "0.25"), - ct: int64p(1520872607123), + ct: 1520872607123, }, { m: `{"go.gc_duration_seconds",quantile="0.5",a="b"}`, v: 8.3835e-05, @@ -966,19 +960,19 @@ thing_c_total 14123.232 }, { m: `thing_count`, - ct: nil, // Should be int64p(1520872607123). + ct: 0, // Should be int64p(1520872607123). }, { m: `thing_sum`, - ct: nil, // Should be int64p(1520872607123). + ct: 0, // Should be int64p(1520872607123). }, { m: `thing_bucket{le="0.0"}`, - ct: nil, // Should be int64p(1520872607123). + ct: 0, // Should be int64p(1520872607123). }, { m: `thing_bucket{le="+Inf"}`, - ct: nil, // Should be int64p(1520872607123), + ct: 0, // Should be int64p(1520872607123), }, { m: "thing_c", @@ -990,7 +984,7 @@ thing_c_total 14123.232 }, { m: `thing_c_total`, - ct: nil, // Should be int64p(1520872607123). + ct: 0, // Should be int64p(1520872607123). }, }, }, diff --git a/model/textparse/promparse.go b/model/textparse/promparse.go index f3f2571b00..4ecd93c37b 100644 --- a/model/textparse/promparse.go +++ b/model/textparse/promparse.go @@ -253,10 +253,10 @@ func (p *PromParser) Exemplar(*exemplar.Exemplar) bool { return false } -// CreatedTimestamp returns nil as it's not implemented yet. +// CreatedTimestamp returns 0 as it's not implemented yet. // TODO(bwplotka): https://github.com/prometheus/prometheus/issues/12980 -func (p *PromParser) CreatedTimestamp() *int64 { - return nil +func (p *PromParser) CreatedTimestamp() int64 { + return 0 } // nextToken returns the next token from the promlexer. It skips over tabs diff --git a/model/textparse/promparse_test.go b/model/textparse/promparse_test.go index e8cf66f539..203ff25ba5 100644 --- a/model/textparse/promparse_test.go +++ b/model/textparse/promparse_test.go @@ -205,12 +205,6 @@ testmetric{le="10"} 1` } func TestUTF8PromParse(t *testing.T) { - oldValidationScheme := model.NameValidationScheme - model.NameValidationScheme = model.UTF8Validation - defer func() { - model.NameValidationScheme = oldValidationScheme - }() - input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations. # TYPE "go.gc_duration_seconds" summary {"go.gc_duration_seconds",quantile="0"} 4.9351e-05 diff --git a/model/textparse/protobufparse.go b/model/textparse/protobufparse.go index 380c9918cf..75c51d3e73 100644 --- a/model/textparse/protobufparse.go +++ b/model/textparse/protobufparse.go @@ -379,9 +379,8 @@ func (p *ProtobufParser) Exemplar(ex *exemplar.Exemplar) bool { return true } -// CreatedTimestamp returns CT or nil if CT is not present or -// invalid (as timestamp e.g. negative value) on counters, summaries or histograms. -func (p *ProtobufParser) CreatedTimestamp() *int64 { +// CreatedTimestamp returns CT or 0 if CT is not present on counters, summaries or histograms. +func (p *ProtobufParser) CreatedTimestamp() int64 { var ct *types.Timestamp switch p.dec.GetType() { case dto.MetricType_COUNTER: @@ -392,13 +391,12 @@ func (p *ProtobufParser) CreatedTimestamp() *int64 { ct = p.dec.GetHistogram().GetCreatedTimestamp() default: } - ctAsTime, err := types.TimestampFromProto(ct) - if err != nil { - // Errors means ct == nil or invalid timestamp, which we silently ignore. - return nil + if ct == nil { + return 0 } - ctMilis := ctAsTime.UnixMilli() - return &ctMilis + // Same as the gogo proto types.TimestampFromProto but straight to integer. + // and without validation. + return ct.GetSeconds()*1e3 + int64(ct.GetNanos())/1e6 } // Next advances the parser to the next "sample" (emulating the behavior of a diff --git a/model/textparse/protobufparse_test.go b/model/textparse/protobufparse_test.go index 381e6a9355..8d5f1b26e6 100644 --- a/model/textparse/protobufparse_test.go +++ b/model/textparse/protobufparse_test.go @@ -582,8 +582,8 @@ metric: < counter: < value: 42 created_timestamp: < - seconds: 1 - nanos: 1 + seconds: 1625851153 + nanos: 146848499 > > > @@ -597,8 +597,8 @@ metric: < sample_count: 42 sample_sum: 1.234 created_timestamp: < - seconds: 1 - nanos: 1 + seconds: 1625851153 + nanos: 146848499 > > > @@ -610,8 +610,8 @@ type: HISTOGRAM metric: < histogram: < created_timestamp: < - seconds: 1 - nanos: 1 + seconds: 1625851153 + nanos: 146848499 > positive_span: < offset: 0 @@ -627,8 +627,8 @@ type: GAUGE_HISTOGRAM metric: < histogram: < created_timestamp: < - seconds: 1 - nanos: 1 + seconds: 1625851153 + nanos: 146848499 > positive_span: < offset: 0 @@ -1324,7 +1324,7 @@ func TestProtobufParse(t *testing.T) { { m: "test_counter_with_createdtimestamp", v: 42, - ct: int64p(1000), + ct: 1625851153146, lset: labels.FromStrings( "__name__", "test_counter_with_createdtimestamp", ), @@ -1340,7 +1340,7 @@ func TestProtobufParse(t *testing.T) { { m: "test_summary_with_createdtimestamp_count", v: 42, - ct: int64p(1000), + ct: 1625851153146, lset: labels.FromStrings( "__name__", "test_summary_with_createdtimestamp_count", ), @@ -1348,7 +1348,7 @@ func TestProtobufParse(t *testing.T) { { m: "test_summary_with_createdtimestamp_sum", v: 1.234, - ct: int64p(1000), + ct: 1625851153146, lset: labels.FromStrings( "__name__", "test_summary_with_createdtimestamp_sum", ), @@ -1363,7 +1363,7 @@ func TestProtobufParse(t *testing.T) { }, { m: "test_histogram_with_createdtimestamp", - ct: int64p(1000), + ct: 1625851153146, shs: &histogram.Histogram{ CounterResetHint: histogram.UnknownCounterReset, PositiveSpans: []histogram.Span{}, @@ -1383,7 +1383,7 @@ func TestProtobufParse(t *testing.T) { }, { m: "test_gaugehistogram_with_createdtimestamp", - ct: int64p(1000), + ct: 1625851153146, shs: &histogram.Histogram{ CounterResetHint: histogram.GaugeType, PositiveSpans: []histogram.Span{}, @@ -2277,7 +2277,7 @@ func TestProtobufParse(t *testing.T) { { m: "test_counter_with_createdtimestamp", v: 42, - ct: int64p(1000), + ct: 1625851153146, lset: labels.FromStrings( "__name__", "test_counter_with_createdtimestamp", ), @@ -2293,7 +2293,7 @@ func TestProtobufParse(t *testing.T) { { m: "test_summary_with_createdtimestamp_count", v: 42, - ct: int64p(1000), + ct: 1625851153146, lset: labels.FromStrings( "__name__", "test_summary_with_createdtimestamp_count", ), @@ -2301,7 +2301,7 @@ func TestProtobufParse(t *testing.T) { { m: "test_summary_with_createdtimestamp_sum", v: 1.234, - ct: int64p(1000), + ct: 1625851153146, lset: labels.FromStrings( "__name__", "test_summary_with_createdtimestamp_sum", ), @@ -2316,7 +2316,7 @@ func TestProtobufParse(t *testing.T) { }, { m: "test_histogram_with_createdtimestamp", - ct: int64p(1000), + ct: 1625851153146, shs: &histogram.Histogram{ CounterResetHint: histogram.UnknownCounterReset, PositiveSpans: []histogram.Span{}, @@ -2336,7 +2336,7 @@ func TestProtobufParse(t *testing.T) { }, { m: "test_gaugehistogram_with_createdtimestamp", - ct: int64p(1000), + ct: 1625851153146, shs: &histogram.Histogram{ CounterResetHint: histogram.GaugeType, PositiveSpans: []histogram.Span{}, diff --git a/notifier/notifier.go b/notifier/notifier.go index fbc37c29ef..153c1039f8 100644 --- a/notifier/notifier.go +++ b/notifier/notifier.go @@ -36,7 +36,6 @@ import ( "github.com/prometheus/common/promslog" "github.com/prometheus/common/version" "github.com/prometheus/sigv4" - "go.uber.org/atomic" "gopkg.in/yaml.v2" "github.com/prometheus/prometheus/config" @@ -552,10 +551,10 @@ func (n *Manager) sendAll(alerts ...*Alert) bool { n.mtx.RUnlock() var ( - wg sync.WaitGroup - numSuccess atomic.Uint64 + wg sync.WaitGroup + amSetCovered sync.Map ) - for _, ams := range amSets { + for k, ams := range amSets { var ( payload []byte err error @@ -611,24 +610,28 @@ func (n *Manager) sendAll(alerts ...*Alert) bool { cachedPayload = nil } + // Being here means len(ams.ams) > 0 + amSetCovered.Store(k, false) for _, am := range ams.ams { wg.Add(1) ctx, cancel := context.WithTimeout(context.Background(), time.Duration(ams.cfg.Timeout)) defer cancel() - go func(ctx context.Context, client *http.Client, url string, payload []byte, count int) { - if err := n.sendOne(ctx, client, url, payload); err != nil { + go func(ctx context.Context, k string, client *http.Client, url string, payload []byte, count int) { + err := n.sendOne(ctx, client, url, payload) + if err != nil { n.logger.Error("Error sending alerts", "alertmanager", url, "count", count, "err", err) n.metrics.errors.WithLabelValues(url).Add(float64(count)) } else { - numSuccess.Inc() + amSetCovered.CompareAndSwap(k, false, true) } + n.metrics.latency.WithLabelValues(url).Observe(time.Since(begin).Seconds()) n.metrics.sent.WithLabelValues(url).Add(float64(count)) wg.Done() - }(ctx, ams.client, am.url().String(), payload, len(amAlerts)) + }(ctx, k, ams.client, am.url().String(), payload, len(amAlerts)) } ams.mtx.RUnlock() @@ -636,7 +639,18 @@ func (n *Manager) sendAll(alerts ...*Alert) bool { wg.Wait() - return numSuccess.Load() > 0 + // Return false if there are any sets which were attempted (e.g. not filtered + // out) but have no successes. + allAmSetsCovered := true + amSetCovered.Range(func(_, value any) bool { + if !value.(bool) { + allAmSetsCovered = false + return false + } + return true + }) + + return allAmSetsCovered } func alertsToOpenAPIAlerts(alerts []*Alert) models.PostableAlerts { diff --git a/notifier/notifier_test.go b/notifier/notifier_test.go index 97b0274f29..7d63e4047b 100644 --- a/notifier/notifier_test.go +++ b/notifier/notifier_test.go @@ -140,17 +140,20 @@ func newTestHTTPServerBuilder(expected *[]*Alert, errc chan<- error, u, p string func TestHandlerSendAll(t *testing.T) { var ( - errc = make(chan error, 1) - expected = make([]*Alert, 0, maxBatchSize) - status1, status2 atomic.Int32 + errc = make(chan error, 1) + expected = make([]*Alert, 0, maxBatchSize) + status1, status2, status3 atomic.Int32 ) status1.Store(int32(http.StatusOK)) status2.Store(int32(http.StatusOK)) + status3.Store(int32(http.StatusOK)) server1 := newTestHTTPServerBuilder(&expected, errc, "prometheus", "testing_password", &status1) server2 := newTestHTTPServerBuilder(&expected, errc, "", "", &status2) + server3 := newTestHTTPServerBuilder(&expected, errc, "", "", &status3) defer server1.Close() defer server2.Close() + defer server3.Close() h := NewManager(&Options{}, nil) @@ -170,6 +173,9 @@ func TestHandlerSendAll(t *testing.T) { am2Cfg := config.DefaultAlertmanagerConfig am2Cfg.Timeout = model.Duration(time.Second) + am3Cfg := config.DefaultAlertmanagerConfig + am3Cfg.Timeout = model.Duration(time.Second) + h.alertmanagers["1"] = &alertmanagerSet{ ams: []alertmanager{ alertmanagerMock{ @@ -185,10 +191,18 @@ func TestHandlerSendAll(t *testing.T) { alertmanagerMock{ urlf: func() string { return server2.URL }, }, + alertmanagerMock{ + urlf: func() string { return server3.URL }, + }, }, cfg: &am2Cfg, } + h.alertmanagers["3"] = &alertmanagerSet{ + ams: []alertmanager{}, // empty set + cfg: &am3Cfg, + } + for i := range make([]struct{}, maxBatchSize) { h.queue = append(h.queue, &Alert{ Labels: labels.FromStrings("alertname", strconv.Itoa(i)), @@ -207,14 +221,25 @@ func TestHandlerSendAll(t *testing.T) { } } + // all ams in all sets are up require.True(t, h.sendAll(h.queue...), "all sends failed unexpectedly") checkNoErr() + // the only am in set 1 is down status1.Store(int32(http.StatusNotFound)) - require.True(t, h.sendAll(h.queue...), "all sends failed unexpectedly") + require.False(t, h.sendAll(h.queue...), "all sends failed unexpectedly") checkNoErr() + // reset it + status1.Store(int32(http.StatusOK)) + + // only one of the ams in set 2 is down status2.Store(int32(http.StatusInternalServerError)) + require.True(t, h.sendAll(h.queue...), "all sends succeeded unexpectedly") + checkNoErr() + + // both ams in set 2 are down + status3.Store(int32(http.StatusInternalServerError)) require.False(t, h.sendAll(h.queue...), "all sends succeeded unexpectedly") checkNoErr() } @@ -226,13 +251,15 @@ func TestHandlerSendAllRemapPerAm(t *testing.T) { expected2 = make([]*Alert, 0, maxBatchSize) expected3 = make([]*Alert, 0) - statusOK atomic.Int32 + status1, status2, status3 atomic.Int32 ) - statusOK.Store(int32(http.StatusOK)) + status1.Store(int32(http.StatusOK)) + status2.Store(int32(http.StatusOK)) + status3.Store(int32(http.StatusOK)) - server1 := newTestHTTPServerBuilder(&expected1, errc, "", "", &statusOK) - server2 := newTestHTTPServerBuilder(&expected2, errc, "", "", &statusOK) - server3 := newTestHTTPServerBuilder(&expected3, errc, "", "", &statusOK) + server1 := newTestHTTPServerBuilder(&expected1, errc, "", "", &status1) + server2 := newTestHTTPServerBuilder(&expected2, errc, "", "", &status2) + server3 := newTestHTTPServerBuilder(&expected3, errc, "", "", &status3) defer server1.Close() defer server2.Close() @@ -331,6 +358,21 @@ func TestHandlerSendAllRemapPerAm(t *testing.T) { } } + // all ams are up + require.True(t, h.sendAll(h.queue...), "all sends failed unexpectedly") + checkNoErr() + + // the only am in set 1 goes down + status1.Store(int32(http.StatusInternalServerError)) + require.False(t, h.sendAll(h.queue...), "all sends failed unexpectedly") + checkNoErr() + + // reset set 1 + status1.Store(int32(http.StatusOK)) + + // set 3 loses its only am, but all alerts were dropped + // so there was nothing to send, keeping sendAll true + status3.Store(int32(http.StatusInternalServerError)) require.True(t, h.sendAll(h.queue...), "all sends failed unexpectedly") checkNoErr() @@ -348,7 +390,7 @@ func TestCustomDo(t *testing.T) { var received bool h := NewManager(&Options{ - Do: func(_ context.Context, client *http.Client, req *http.Request) (*http.Response, error) { + Do: func(_ context.Context, _ *http.Client, req *http.Request) (*http.Response, error) { received = true body, err := io.ReadAll(req.Body) @@ -447,7 +489,7 @@ func TestHandlerQueuing(t *testing.T) { errc = make(chan error, 1) ) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { // Notify the test function that we have received something. select { case called <- struct{}{}: @@ -724,7 +766,7 @@ func TestHangingNotifier(t *testing.T) { // Set up a faulty Alertmanager. var faultyCalled atomic.Bool - faultyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + faultyServer := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { faultyCalled.Store(true) select { case <-done: @@ -736,7 +778,7 @@ func TestHangingNotifier(t *testing.T) { // Set up a functional Alertmanager. var functionalCalled atomic.Bool - functionalServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + functionalServer := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { functionalCalled.Store(true) })) functionalURL, err := url.Parse(functionalServer.URL) diff --git a/promql/engine.go b/promql/engine.go index 80cc72ea7d..14aba6ae80 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -559,7 +559,7 @@ func (ng *Engine) validateOpts(expr parser.Expr) error { var atModifierUsed, negativeOffsetUsed bool var validationErr error - parser.Inspect(expr, func(node parser.Node, path []parser.Node) error { + parser.Inspect(expr, func(node parser.Node, _ []parser.Node) error { switch n := node.(type) { case *parser.VectorSelector: if n.Timestamp != nil || n.StartOrEnd == parser.START || n.StartOrEnd == parser.END { @@ -1970,7 +1970,7 @@ func (ev *evaluator) eval(ctx context.Context, expr parser.Expr) (parser.Value, case *parser.NumberLiteral: span.SetAttributes(attribute.Float64("value", e.Val)) - return ev.rangeEval(ctx, nil, func(v []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, annotations.Annotations) { + return ev.rangeEval(ctx, nil, func(_ []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return append(enh.Out, Sample{F: e.Val, Metric: labels.EmptyLabels()}), nil }) @@ -2139,7 +2139,7 @@ func (ev *evaluator) rangeEvalTimestampFunctionOverVectorSelector(ctx context.Co seriesIterators[i] = storage.NewMemoizedIterator(it, durationMilliseconds(ev.lookbackDelta)-1) } - return ev.rangeEval(ctx, nil, func(v []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, annotations.Annotations) { + return ev.rangeEval(ctx, nil, func(_ []parser.Value, _ [][]EvalSeriesHelper, enh *EvalNodeHelper) (Vector, annotations.Annotations) { if vs.Timestamp != nil { // This is a special case for "timestamp()" when the @ modifier is used, to ensure that // we return a point for each time step in this case. @@ -3790,7 +3790,7 @@ func NewHashRatioSampler() *HashRatioSampler { return &HashRatioSampler{} } -func (s *HashRatioSampler) sampleOffset(ts int64, sample *Sample) float64 { +func (s *HashRatioSampler) sampleOffset(_ int64, sample *Sample) float64 { const ( float64MaxUint64 = float64(math.MaxUint64) ) diff --git a/promql/engine_test.go b/promql/engine_test.go index 5c4bb744f5..5dddebe5df 100644 --- a/promql/engine_test.go +++ b/promql/engine_test.go @@ -263,7 +263,7 @@ func TestQueryError(t *testing.T) { } engine := promqltest.NewTestEngineWithOpts(t, opts) errStorage := promql.ErrStorage{errors.New("storage error")} - queryable := storage.QueryableFunc(func(mint, maxt int64) (storage.Querier, error) { + queryable := storage.QueryableFunc(func(_, _ int64) (storage.Querier, error) { return &errQuerier{err: errStorage}, nil }) ctx, cancelCtx := context.WithCancel(context.Background()) @@ -2290,7 +2290,7 @@ func TestQueryLogger_error(t *testing.T) { ctx = promql.NewOriginContext(ctx, map[string]interface{}{"foo": "bar"}) defer cancelCtx() testErr := errors.New("failure") - query := engine.NewTestQuery(func(ctx context.Context) error { + query := engine.NewTestQuery(func(_ context.Context) error { return testErr }) diff --git a/promql/functions.go b/promql/functions.go index dcbbbc081c..3c79684b0f 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -59,7 +59,7 @@ import ( type FunctionCall func(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) // === time() float64 === -func funcTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcTime(_ []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return Vector{Sample{ F: float64(enh.Ts) / 1000, }}, nil @@ -367,10 +367,11 @@ func instantValue(vals []parser.Value, args parser.Expressions, out Vector, isRa } switch { case ss[1].H == nil && ss[0].H == nil: - if !isRate || ss[1].F >= ss[0].F { - // Gauge or counter without reset. + if !isRate || !(ss[1].F < ss[0].F) { + // Gauge, or counter without reset, or counter with NaN value. resultSample.F = ss[1].F - ss[0].F } + // In case of a counter reset, we leave resultSample at // its current value, which is already ss[1]. case ss[1].H != nil && ss[0].H != nil: @@ -498,7 +499,7 @@ func filterFloats(v Vector) Vector { } // === sort(node parser.ValueTypeVector) (Vector, Annotations) === -func funcSort(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSort(vals []parser.Value, _ parser.Expressions, _ *EvalNodeHelper) (Vector, annotations.Annotations) { // NaN should sort to the bottom, so take descending sort with NaN first and // reverse it. byValueSorter := vectorByReverseValueHeap(filterFloats(vals[0].(Vector))) @@ -507,7 +508,7 @@ func funcSort(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) } // === sortDesc(node parser.ValueTypeVector) (Vector, Annotations) === -func funcSortDesc(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSortDesc(vals []parser.Value, _ parser.Expressions, _ *EvalNodeHelper) (Vector, annotations.Annotations) { // NaN should sort to the bottom, so take ascending sort with NaN first and // reverse it. byValueSorter := vectorByValueHeap(filterFloats(vals[0].(Vector))) @@ -516,7 +517,7 @@ func funcSortDesc(vals []parser.Value, args parser.Expressions, enh *EvalNodeHel } // === sort_by_label(vector parser.ValueTypeVector, label parser.ValueTypeString...) (Vector, Annotations) === -func funcSortByLabel(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSortByLabel(vals []parser.Value, args parser.Expressions, _ *EvalNodeHelper) (Vector, annotations.Annotations) { lbls := stringSliceFromArgs(args[1:]) slices.SortFunc(vals[0].(Vector), func(a, b Sample) int { for _, label := range lbls { @@ -542,7 +543,7 @@ func funcSortByLabel(vals []parser.Value, args parser.Expressions, enh *EvalNode } // === sort_by_label_desc(vector parser.ValueTypeVector, label parser.ValueTypeString...) (Vector, Annotations) === -func funcSortByLabelDesc(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSortByLabelDesc(vals []parser.Value, args parser.Expressions, _ *EvalNodeHelper) (Vector, annotations.Annotations) { lbls := stringSliceFromArgs(args[1:]) slices.SortFunc(vals[0].(Vector), func(a, b Sample) int { for _, label := range lbls { @@ -589,7 +590,7 @@ func clamp(vec Vector, minVal, maxVal float64, enh *EvalNodeHelper) (Vector, ann } // === clamp(Vector parser.ValueTypeVector, min, max Scalar) (Vector, Annotations) === -func funcClamp(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcClamp(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { vec := vals[0].(Vector) minVal := vals[1].(Vector)[0].F maxVal := vals[2].(Vector)[0].F @@ -597,14 +598,14 @@ func funcClamp(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper } // === clamp_max(Vector parser.ValueTypeVector, max Scalar) (Vector, Annotations) === -func funcClampMax(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcClampMax(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { vec := vals[0].(Vector) maxVal := vals[1].(Vector)[0].F return clamp(vec, math.Inf(-1), maxVal, enh) } // === clamp_min(Vector parser.ValueTypeVector, min Scalar) (Vector, Annotations) === -func funcClampMin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcClampMin(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { vec := vals[0].(Vector) minVal := vals[1].(Vector)[0].F return clamp(vec, minVal, math.Inf(+1), enh) @@ -641,7 +642,7 @@ func funcRound(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper } // === Scalar(node parser.ValueTypeVector) Scalar === -func funcScalar(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcScalar(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { var ( v = vals[0].(Vector) value float64 @@ -766,14 +767,14 @@ func funcAvgOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNode } // === count_over_time(Matrix parser.ValueTypeMatrix) (Vector, Notes) === -func funcCountOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcCountOverTime(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return aggrOverTime(vals, enh, func(s Series) float64 { return float64(len(s.Floats) + len(s.Histograms)) }), nil } // === last_over_time(Matrix parser.ValueTypeMatrix) (Vector, Notes) === -func funcLastOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcLastOverTime(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { el := vals[0].(Matrix)[0] var f FPoint @@ -998,13 +999,13 @@ func funcAbsent(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelpe // This function will return 1 if the matrix has at least one element. // Due to engine optimization, this function is only called when this condition is true. // Then, the engine post-processes the results to get the expected output. -func funcAbsentOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAbsentOverTime(_ []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return append(enh.Out, Sample{F: 1}), nil } // === present_over_time(Vector parser.ValueTypeMatrix) (Vector, Annotations) === -func funcPresentOverTime(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { - return aggrOverTime(vals, enh, func(s Series) float64 { +func funcPresentOverTime(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { + return aggrOverTime(vals, enh, func(_ Series) float64 { return 1 }), nil } @@ -1026,126 +1027,126 @@ func simpleFunc(vals []parser.Value, enh *EvalNodeHelper, f func(float64) float6 } // === abs(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcAbs(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAbs(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Abs), nil } // === ceil(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcCeil(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcCeil(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Ceil), nil } // === floor(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcFloor(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcFloor(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Floor), nil } // === exp(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcExp(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcExp(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Exp), nil } // === sqrt(Vector VectorNode) (Vector, Annotations) === -func funcSqrt(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSqrt(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Sqrt), nil } // === ln(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcLn(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcLn(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Log), nil } // === log2(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcLog2(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcLog2(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Log2), nil } // === log10(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcLog10(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcLog10(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Log10), nil } // === sin(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcSin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSin(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Sin), nil } // === cos(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcCos(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcCos(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Cos), nil } // === tan(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcTan(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcTan(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Tan), nil } // === asin(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcAsin(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAsin(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Asin), nil } // === acos(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcAcos(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAcos(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Acos), nil } // === atan(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcAtan(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAtan(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Atan), nil } // === sinh(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcSinh(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSinh(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Sinh), nil } // === cosh(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcCosh(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcCosh(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Cosh), nil } // === tanh(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcTanh(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcTanh(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Tanh), nil } // === asinh(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcAsinh(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAsinh(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Asinh), nil } // === acosh(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcAcosh(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAcosh(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Acosh), nil } // === atanh(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcAtanh(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcAtanh(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, math.Atanh), nil } // === rad(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcRad(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcRad(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, func(v float64) float64 { return v * math.Pi / 180 }), nil } // === deg(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcDeg(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcDeg(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, func(v float64) float64 { return v * 180 / math.Pi }), nil } // === pi() Scalar === -func funcPi(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcPi(_ []parser.Value, _ parser.Expressions, _ *EvalNodeHelper) (Vector, annotations.Annotations) { return Vector{Sample{F: math.Pi}}, nil } // === sgn(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcSgn(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcSgn(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return simpleFunc(vals, enh, func(v float64) float64 { switch { case v < 0: @@ -1159,7 +1160,7 @@ func funcSgn(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) } // === timestamp(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcTimestamp(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcTimestamp(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { vec := vals[0].(Vector) for _, el := range vec { if !enh.enableDelayedNameRemoval { @@ -1284,7 +1285,7 @@ func funcPredictLinear(vals []parser.Value, args parser.Expressions, enh *EvalNo } // === histogram_count(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcHistogramCount(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcHistogramCount(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { inVec := vals[0].(Vector) for _, sample := range inVec { @@ -1305,7 +1306,7 @@ func funcHistogramCount(vals []parser.Value, args parser.Expressions, enh *EvalN } // === histogram_sum(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcHistogramSum(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcHistogramSum(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { inVec := vals[0].(Vector) for _, sample := range inVec { @@ -1326,7 +1327,7 @@ func funcHistogramSum(vals []parser.Value, args parser.Expressions, enh *EvalNod } // === histogram_avg(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcHistogramAvg(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcHistogramAvg(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { inVec := vals[0].(Vector) for _, sample := range inVec { @@ -1347,7 +1348,7 @@ func funcHistogramAvg(vals []parser.Value, args parser.Expressions, enh *EvalNod } // === histogram_stddev(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcHistogramStdDev(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcHistogramStdDev(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { inVec := vals[0].(Vector) for _, sample := range inVec { @@ -1390,7 +1391,7 @@ func funcHistogramStdDev(vals []parser.Value, args parser.Expressions, enh *Eval } // === histogram_stdvar(Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcHistogramStdVar(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcHistogramStdVar(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { inVec := vals[0].(Vector) for _, sample := range inVec { @@ -1433,7 +1434,7 @@ func funcHistogramStdVar(vals []parser.Value, args parser.Expressions, enh *Eval } // === histogram_fraction(lower, upper parser.ValueTypeScalar, Vector parser.ValueTypeVector) (Vector, Annotations) === -func funcHistogramFraction(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcHistogramFraction(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { lower := vals[0].(Vector)[0].F upper := vals[1].(Vector)[0].F inVec := vals[2].(Vector) @@ -1550,7 +1551,7 @@ func funcHistogramQuantile(vals []parser.Value, args parser.Expressions, enh *Ev } // === resets(Matrix parser.ValueTypeMatrix) (Vector, Annotations) === -func funcResets(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcResets(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { floats := vals[0].(Matrix)[0].Floats histograms := vals[0].(Matrix)[0].Histograms resets := 0 @@ -1595,7 +1596,7 @@ func funcResets(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelpe } // === changes(Matrix parser.ValueTypeMatrix) (Vector, Annotations) === -func funcChanges(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcChanges(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { floats := vals[0].(Matrix)[0].Floats histograms := vals[0].(Matrix)[0].Histograms changes := 0 @@ -1683,7 +1684,7 @@ func (ev *evaluator) evalLabelReplace(ctx context.Context, args parser.Expressio } // === Vector(s Scalar) (Vector, Annotations) === -func funcVector(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcVector(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return append(enh.Out, Sample{ Metric: labels.Labels{}, @@ -1765,56 +1766,56 @@ func dateWrapper(vals []parser.Value, enh *EvalNodeHelper, f func(time.Time) flo } // === days_in_month(v Vector) Scalar === -func funcDaysInMonth(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcDaysInMonth(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(32 - time.Date(t.Year(), t.Month(), 32, 0, 0, 0, 0, time.UTC).Day()) }), nil } // === day_of_month(v Vector) Scalar === -func funcDayOfMonth(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcDayOfMonth(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(t.Day()) }), nil } // === day_of_week(v Vector) Scalar === -func funcDayOfWeek(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcDayOfWeek(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(t.Weekday()) }), nil } // === day_of_year(v Vector) Scalar === -func funcDayOfYear(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcDayOfYear(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(t.YearDay()) }), nil } // === hour(v Vector) Scalar === -func funcHour(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcHour(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(t.Hour()) }), nil } // === minute(v Vector) Scalar === -func funcMinute(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcMinute(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(t.Minute()) }), nil } // === month(v Vector) Scalar === -func funcMonth(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcMonth(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(t.Month()) }), nil } // === year(v Vector) Scalar === -func funcYear(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { +func funcYear(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) { return dateWrapper(vals, enh, func(t time.Time) float64 { return float64(t.Year()) }), nil diff --git a/promql/histogram_stats_iterator_test.go b/promql/histogram_stats_iterator_test.go index ea0e8b469f..3b99f6ea6f 100644 --- a/promql/histogram_stats_iterator_test.go +++ b/promql/histogram_stats_iterator_test.go @@ -173,7 +173,7 @@ func (h *histogramIterator) Next() chunkenc.ValueType { return chunkenc.ValNone } -func (h *histogramIterator) Seek(t int64) chunkenc.ValueType { panic("not implemented") } +func (h *histogramIterator) Seek(_ int64) chunkenc.ValueType { panic("not implemented") } func (h *histogramIterator) At() (int64, float64) { panic("not implemented") } diff --git a/promql/info.go b/promql/info.go index 3fe9a2ce99..0197330822 100644 --- a/promql/info.go +++ b/promql/info.go @@ -83,7 +83,7 @@ loop: func (ev *evaluator) infoSelectHints(expr parser.Expr) storage.SelectHints { var nodeTimestamp *int64 var offset int64 - parser.Inspect(expr, func(node parser.Node, path []parser.Node) error { + parser.Inspect(expr, func(node parser.Node, _ []parser.Node) error { switch n := node.(type) { case *parser.VectorSelector: if n.Timestamp != nil { diff --git a/promql/parser/lex.go b/promql/parser/lex.go index 7210d51b7b..52658f318c 100644 --- a/promql/parser/lex.go +++ b/promql/parser/lex.go @@ -429,11 +429,10 @@ func lexStatements(l *Lexer) stateFn { l.emit(EQL) } case r == '!': - if t := l.next(); t == '=' { - l.emit(NEQ) - } else { + if t := l.next(); t != '=' { return l.errorf("unexpected character after '!': %q", t) } + l.emit(NEQ) case r == '<': if t := l.peek(); t == '=' { l.next() diff --git a/promql/parser/parse.go b/promql/parser/parse.go index 9d38fd2d6d..5db33269e8 100644 --- a/promql/parser/parse.go +++ b/promql/parser/parse.go @@ -72,7 +72,7 @@ func WithFunctions(functions map[string]*Function) Opt { } // NewParser returns a new parser. -func NewParser(input string, opts ...Opt) *parser { //nolint:revive // unexported-return. +func NewParser(input string, opts ...Opt) *parser { //nolint:revive // unexported-return p := parserPool.Get().(*parser) p.functions = Functions diff --git a/promql/parser/parse_test.go b/promql/parser/parse_test.go index 3445fce067..7a4f95d3ab 100644 --- a/promql/parser/parse_test.go +++ b/promql/parser/parse_test.go @@ -3970,7 +3970,6 @@ func TestParseExpressions(t *testing.T) { EnableExperimentalFunctions = false }) - model.NameValidationScheme = model.UTF8Validation for _, test := range testExpr { t.Run(readable(test.input), func(t *testing.T) { expr, err := ParseExpr(test.input) diff --git a/promql/parser/printer.go b/promql/parser/printer.go index afe755e7dd..6f234a0290 100644 --- a/promql/parser/printer.go +++ b/promql/parser/printer.go @@ -232,7 +232,7 @@ func (node *SubqueryExpr) getSubqueryTimeSuffix() string { } func (node *NumberLiteral) String() string { - return fmt.Sprint(node.Val) + return strconv.FormatFloat(node.Val, 'f', -1, 64) } func (node *ParenExpr) String() string { diff --git a/promql/parser/printer_test.go b/promql/parser/printer_test.go index 0a557ad597..44a9c62b7d 100644 --- a/promql/parser/printer_test.go +++ b/promql/parser/printer_test.go @@ -16,7 +16,6 @@ package parser import ( "testing" - "github.com/prometheus/common/model" "github.com/stretchr/testify/require" "github.com/prometheus/prometheus/model/labels" @@ -164,10 +163,12 @@ func TestExprString(t *testing.T) { in: "{``=\"0\"}", out: `{""="0"}`, }, + { + in: "1048576", + out: "1048576", + }, } - model.NameValidationScheme = model.UTF8Validation - for _, test := range inputs { expr, err := ParseExpr(test.in) require.NoError(t, err) diff --git a/promql/promqltest/test.go b/promql/promqltest/test.go index e84eeebe6a..4321bf6b39 100644 --- a/promql/promqltest/test.go +++ b/promql/promqltest/test.go @@ -57,10 +57,6 @@ const ( DefaultMaxSamplesPerQuery = 10000 ) -func init() { - model.NameValidationScheme = model.UTF8Validation -} - type TBRun interface { testing.TB Run(string, func(*testing.T)) bool diff --git a/promql/promqltest/testdata/functions.test b/promql/promqltest/testdata/functions.test index 49ab6c50ff..fafe2dda40 100644 --- a/promql/promqltest/testdata/functions.test +++ b/promql/promqltest/testdata/functions.test @@ -218,6 +218,7 @@ clear load 5m http_requests_total{path="/foo"} 0+10x10 http_requests_total{path="/bar"} 0+10x5 0+10x5 + http_requests_nan{} 1 NaN NaN 5 11 http_requests_histogram{path="/a"} {{sum:2 count:2}}+{{sum:3 count:3}}x5 http_requests_histogram{path="/b"} 0 0 {{sum:1 count:1}} {{sum:4 count:4}} http_requests_histogram{path="/c"} 0 0 {{sum:1 count:1}} {{sum:4 count:4 counter_reset_hint:gauge}} @@ -235,6 +236,9 @@ eval instant at 30m irate(http_requests_total[50m]) {path="/foo"} .03333333333333333333 {path="/bar"} 0 +eval range from 0 to 20m step 5m irate(http_requests_nan[15m1s]) + {} _ NaN NaN NaN 0.02 + eval instant at 20m irate(http_requests_histogram{path="/a"}[20m]) {path="/a"} {{sum:0.01 count:0.01 counter_reset_hint:gauge}} @@ -288,6 +292,7 @@ clear load 5m http_requests{path="/foo"} 0 50 100 150 http_requests{path="/bar"} 0 50 100 50 + http_requests_nan{} 1 NaN NaN 5 11 http_requests_histogram{path="/a"} {{sum:2 count:2 counter_reset_hint:gauge}}+{{sum:1 count:3 counter_reset_hint:gauge}}x5 http_requests_histogram{path="/b"} 0 0 {{sum:1 count:1 counter_reset_hint:gauge}} {{sum:2 count:2 counter_reset_hint:gauge}} http_requests_histogram{path="/c"} 0 0 {{sum:1 count:1}} {{sum:2 count:2 counter_reset_hint:gauge}} @@ -300,6 +305,9 @@ eval instant at 20m idelta(http_requests[20m]) {path="/foo"} 50 {path="/bar"} -50 +eval range from 0 to 20m step 5m idelta(http_requests_nan[15m1s]) + {} _ NaN NaN NaN 6 + eval instant at 20m idelta(http_requests_histogram{path="/a"}[20m]) {path="/a"} {{sum:1 count:3 counter_reset_hint:gauge}} @@ -1390,10 +1398,10 @@ clear eval instant at 50m absent(sum(nonexistent{job="testjob", instance="testinstance"})) {} 1 -eval instant at 50m absent(max(nonexistant)) +eval instant at 50m absent(max(nonexistent)) {} 1 -eval instant at 50m absent(nonexistant > 1) +eval instant at 50m absent(nonexistent > 1) {} 1 eval instant at 50m absent(a + b) @@ -1402,7 +1410,7 @@ eval instant at 50m absent(a + b) eval instant at 50m absent(a and b) {} 1 -eval instant at 50m absent(rate(nonexistant[5m])) +eval instant at 50m absent(rate(nonexistent[5m])) {} 1 clear @@ -1420,7 +1428,7 @@ eval instant at 1m absent_over_time(http_requests_total{handler!="/foo"}[5m]) eval instant at 1m absent_over_time(http_requests_total{handler="/foo", handler="/bar", handler="/foobar"}[5m]) {} 1 -eval instant at 1m absent_over_time(rate(nonexistant[5m])[5m:]) +eval instant at 1m absent_over_time(rate(nonexistent[5m])[5m:]) {} 1 eval instant at 1m absent_over_time(http_requests_total{handler="/foo", handler="/bar", instance="127.0.0.1"}[5m]) @@ -1497,7 +1505,7 @@ eval instant at 1m present_over_time(http_requests_total{handler!="/foo"}[5m]) eval instant at 1m present_over_time(http_requests_total{handler="/foo", handler="/bar", handler="/foobar"}[5m]) -eval instant at 1m present_over_time(rate(nonexistant[5m])[5m:]) +eval instant at 1m present_over_time(rate(nonexistent[5m])[5m:]) eval instant at 1m present_over_time(http_requests_total{handler="/foo", handler="/bar", instance="127.0.0.1"}[5m]) diff --git a/rules/alerting_test.go b/rules/alerting_test.go index f7bdf4a955..9d8e10711b 100644 --- a/rules/alerting_test.go +++ b/rules/alerting_test.go @@ -109,7 +109,7 @@ func TestAlertingRuleTemplateWithHistogram(t *testing.T) { NegativeBuckets: []float64{-2, 2, 2, 7, 5, 5, 2}, } - q := func(ctx context.Context, qs string, t time.Time) (promql.Vector, error) { + q := func(_ context.Context, _ string, _ time.Time) (promql.Vector, error) { return []promql.Sample{{H: &h}}, nil } @@ -678,7 +678,7 @@ func TestQueryForStateSeries(t *testing.T) { tests := []testInput{ // Test for empty series. { - selectMockFunction: func(sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet { + selectMockFunction: func(_ bool, _ *storage.SelectHints, _ ...*labels.Matcher) storage.SeriesSet { return storage.EmptySeriesSet() }, expectedSeries: nil, @@ -686,7 +686,7 @@ func TestQueryForStateSeries(t *testing.T) { }, // Test for error series. { - selectMockFunction: func(sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet { + selectMockFunction: func(_ bool, _ *storage.SelectHints, _ ...*labels.Matcher) storage.SeriesSet { return storage.ErrSeriesSet(testError) }, expectedSeries: nil, @@ -694,7 +694,7 @@ func TestQueryForStateSeries(t *testing.T) { }, // Test for mock series. { - selectMockFunction: func(sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet { + selectMockFunction: func(_ bool, _ *storage.SelectHints, _ ...*labels.Matcher) storage.SeriesSet { return storage.TestSeriesSet(storage.MockSeries( []int64{1, 2, 3}, []float64{1, 2, 3}, @@ -989,7 +989,7 @@ func TestAlertingEvalWithOrigin(t *testing.T) { true, promslog.NewNopLogger(), ) - _, err = rule.Eval(ctx, 0, now, func(ctx context.Context, qs string, _ time.Time) (promql.Vector, error) { + _, err = rule.Eval(ctx, 0, now, func(ctx context.Context, _ string, _ time.Time) (promql.Vector, error) { detail = FromOriginContext(ctx) return nil, nil }, nil, 0) diff --git a/rules/group.go b/rules/group.go index a23836a2d9..814dc7b4e9 100644 --- a/rules/group.go +++ b/rules/group.go @@ -1155,7 +1155,7 @@ func buildDependencyMap(rules []Rule) dependencyMap { break } - parser.Inspect(rule.Query(), func(node parser.Node, path []parser.Node) error { + parser.Inspect(rule.Query(), func(node parser.Node, _ []parser.Node) error { if n, ok := node.(*parser.VectorSelector); ok { // Find the name matcher for the rule. var nameMatcher *labels.Matcher diff --git a/rules/manager.go b/rules/manager.go index ee7841ba22..db357cbe48 100644 --- a/rules/manager.go +++ b/rules/manager.go @@ -454,7 +454,7 @@ type Sender interface { // SendAlerts implements the rules.NotifyFunc for a Notifier. func SendAlerts(s Sender, externalURL string) NotifyFunc { - return func(ctx context.Context, expr string, alerts ...*Alert) { + return func(_ context.Context, expr string, alerts ...*Alert) { var res []*notifier.Alert for _, alert := range alerts { @@ -533,7 +533,7 @@ func newRuleConcurrencyController(maxConcurrency int64) RuleConcurrencyControlle } } -func (c *concurrentRuleEvalController) Allow(_ context.Context, _ *Group, rule Rule) bool { +func (c *concurrentRuleEvalController) Allow(_ context.Context, _ *Group, _ Rule) bool { return c.sema.TryAcquire(1) } @@ -586,7 +586,7 @@ func (c sequentialRuleEvalController) Allow(_ context.Context, _ *Group, _ Rule) return false } -func (c sequentialRuleEvalController) SplitGroupIntoBatches(_ context.Context, g *Group) []ConcurrentRules { +func (c sequentialRuleEvalController) SplitGroupIntoBatches(_ context.Context, _ *Group) []ConcurrentRules { return nil } diff --git a/rules/manager_test.go b/rules/manager_test.go index 582d38ae2f..26cc0a2211 100644 --- a/rules/manager_test.go +++ b/rules/manager_test.go @@ -375,7 +375,7 @@ func TestForStateRestore(t *testing.T) { Queryable: storage, Context: context.Background(), Logger: promslog.NewNopLogger(), - NotifyFunc: func(ctx context.Context, expr string, alerts ...*Alert) {}, + NotifyFunc: func(_ context.Context, _ string, _ ...*Alert) {}, OutageTolerance: 30 * time.Minute, ForGracePeriod: 10 * time.Minute, } @@ -967,12 +967,12 @@ func TestGroupEvaluationContextFuncIsCalledWhenSupplied(t *testing.T) { oldContextTestValue := context.Background().Value(testContextKey) contextTestValueChannel := make(chan interface{}) - mockQueryFunc := func(ctx context.Context, qs string, t time.Time) (promql.Vector, error) { + mockQueryFunc := func(ctx context.Context, _ string, _ time.Time) (promql.Vector, error) { contextTestValueChannel <- ctx.Value(testContextKey) return promql.Vector{}, nil } - mockContextWrapFunc := func(ctx context.Context, g *Group) context.Context { + mockContextWrapFunc := func(ctx context.Context, _ *Group) context.Context { return context.WithValue(ctx, testContextKey, 42) } @@ -1091,7 +1091,7 @@ func TestNotify(t *testing.T) { } engine := promqltest.NewTestEngineWithOpts(t, engineOpts) var lastNotified []*Alert - notifyFunc := func(ctx context.Context, expr string, alerts ...*Alert) { + notifyFunc := func(_ context.Context, _ string, alerts ...*Alert) { lastNotified = alerts } opts := &ManagerOptions{ @@ -1530,7 +1530,7 @@ func TestRuleGroupEvalIterationFunc(t *testing.T) { testValue = 3 } - skipEvalIterationFunc := func(ctx context.Context, g *Group, evalTimestamp time.Time) { + skipEvalIterationFunc := func(_ context.Context, _ *Group, _ time.Time) { testValue = 4 } @@ -1569,7 +1569,7 @@ func TestRuleGroupEvalIterationFunc(t *testing.T) { Queryable: storage, Context: context.Background(), Logger: promslog.NewNopLogger(), - NotifyFunc: func(ctx context.Context, expr string, alerts ...*Alert) {}, + NotifyFunc: func(_ context.Context, _ string, _ ...*Alert) {}, OutageTolerance: 30 * time.Minute, ForGracePeriod: 10 * time.Minute, } @@ -1702,7 +1702,7 @@ func TestManager_LoadGroups_ShouldCheckWhetherEachRuleHasDependentsAndDependenci Context: context.Background(), Logger: promslog.NewNopLogger(), Appendable: storage, - QueryFunc: func(ctx context.Context, q string, ts time.Time) (promql.Vector, error) { return nil, nil }, + QueryFunc: func(_ context.Context, _ string, _ time.Time) (promql.Vector, error) { return nil, nil }, }) t.Run("load a mix of dependent and independent rules", func(t *testing.T) { @@ -2456,7 +2456,7 @@ func TestNewRuleGroupRestoration(t *testing.T) { interval = 60 * time.Second ) - waitForEvaluations := func(t *testing.T, ch <-chan int32, targetCount int32) { + waitForEvaluations := func(_ *testing.T, ch <-chan int32, targetCount int32) { for { select { case cnt := <-ch: @@ -2474,11 +2474,11 @@ func TestNewRuleGroupRestoration(t *testing.T) { option := optsFactory(store, &maxInflight, &inflightQueries, maxConcurrency) option.Queryable = store option.Appendable = store - option.NotifyFunc = func(ctx context.Context, expr string, alerts ...*Alert) {} + option.NotifyFunc = func(_ context.Context, _ string, _ ...*Alert) {} var evalCount atomic.Int32 ch := make(chan int32) - noopEvalIterFunc := func(ctx context.Context, g *Group, evalTimestamp time.Time) { + noopEvalIterFunc := func(_ context.Context, _ *Group, _ time.Time) { evalCount.Inc() ch <- evalCount.Load() } @@ -2519,7 +2519,7 @@ func TestNewRuleGroupRestorationWithRestoreNewGroupOption(t *testing.T) { interval = 60 * time.Second ) - waitForEvaluations := func(t *testing.T, ch <-chan int32, targetCount int32) { + waitForEvaluations := func(_ *testing.T, ch <-chan int32, targetCount int32) { for { select { case cnt := <-ch: @@ -2538,11 +2538,11 @@ func TestNewRuleGroupRestorationWithRestoreNewGroupOption(t *testing.T) { option.Queryable = store option.Appendable = store option.RestoreNewRuleGroups = true - option.NotifyFunc = func(ctx context.Context, expr string, alerts ...*Alert) {} + option.NotifyFunc = func(_ context.Context, _ string, _ ...*Alert) {} var evalCount atomic.Int32 ch := make(chan int32) - noopEvalIterFunc := func(ctx context.Context, g *Group, evalTimestamp time.Time) { + noopEvalIterFunc := func(_ context.Context, _ *Group, _ time.Time) { evalCount.Inc() ch <- evalCount.Load() } @@ -2684,7 +2684,7 @@ func optsFactory(storage storage.Storage, maxInflight, inflightQueries *atomic.I ConcurrentEvalsEnabled: concurrent, MaxConcurrentEvals: maxConcurrent, Appendable: storage, - QueryFunc: func(ctx context.Context, q string, ts time.Time) (promql.Vector, error) { + QueryFunc: func(_ context.Context, _ string, ts time.Time) (promql.Vector, error) { inflightMu.Lock() current := inflightQueries.Add(1) @@ -2833,7 +2833,7 @@ func TestRuleDependencyController_AnalyseRules(t *testing.T) { Context: context.Background(), Logger: promslog.NewNopLogger(), Appendable: storage, - QueryFunc: func(ctx context.Context, q string, ts time.Time) (promql.Vector, error) { return nil, nil }, + QueryFunc: func(_ context.Context, _ string, _ time.Time) (promql.Vector, error) { return nil, nil }, }) groups, errs := ruleManager.LoadGroups(time.Second, labels.EmptyLabels(), "", nil, false, tc.ruleFile) @@ -2862,7 +2862,7 @@ func BenchmarkRuleDependencyController_AnalyseRules(b *testing.B) { Context: context.Background(), Logger: promslog.NewNopLogger(), Appendable: storage, - QueryFunc: func(ctx context.Context, q string, ts time.Time) (promql.Vector, error) { return nil, nil }, + QueryFunc: func(_ context.Context, _ string, _ time.Time) (promql.Vector, error) { return nil, nil }, }) groups, errs := ruleManager.LoadGroups(time.Second, labels.EmptyLabels(), "", nil, false, "fixtures/rules_multiple.yaml") diff --git a/rules/recording_test.go b/rules/recording_test.go index 3fbf11c435..e7ec18d0d4 100644 --- a/rules/recording_test.go +++ b/rules/recording_test.go @@ -246,7 +246,7 @@ func TestRecordingEvalWithOrigin(t *testing.T) { require.NoError(t, err) rule := NewRecordingRule(name, expr, lbs) - _, err = rule.Eval(ctx, 0, now, func(ctx context.Context, qs string, _ time.Time) (promql.Vector, error) { + _, err = rule.Eval(ctx, 0, now, func(ctx context.Context, _ string, _ time.Time) (promql.Vector, error) { detail = FromOriginContext(ctx) return nil, nil }, nil, 0) diff --git a/scrape/helpers_test.go b/scrape/helpers_test.go index 2719a467bc..fcef695385 100644 --- a/scrape/helpers_test.go +++ b/scrape/helpers_test.go @@ -43,7 +43,7 @@ func (a nopAppendable) Appender(_ context.Context) storage.Appender { type nopAppender struct{} -func (a nopAppender) SetOptions(opts *storage.AppendOptions) {} +func (a nopAppender) SetOptions(_ *storage.AppendOptions) {} func (a nopAppender) Append(storage.SeriesRef, labels.Labels, int64, float64) (storage.SeriesRef, error) { return 1, nil @@ -57,7 +57,7 @@ func (a nopAppender) AppendHistogram(storage.SeriesRef, labels.Labels, int64, *h return 3, nil } -func (a nopAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, l labels.Labels, t, ct int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { +func (a nopAppender) AppendHistogramCTZeroSample(_ storage.SeriesRef, _ labels.Labels, _, _ int64, _ *histogram.Histogram, _ *histogram.FloatHistogram) (storage.SeriesRef, error) { return 0, nil } @@ -137,7 +137,7 @@ type collectResultAppender struct { pendingMetadata []metadataEntry } -func (a *collectResultAppender) SetOptions(opts *storage.AppendOptions) {} +func (a *collectResultAppender) SetOptions(_ *storage.AppendOptions) {} func (a *collectResultAppender) Append(ref storage.SeriesRef, lset labels.Labels, t int64, v float64) (storage.SeriesRef, error) { a.mtx.Lock() @@ -159,7 +159,7 @@ func (a *collectResultAppender) Append(ref storage.SeriesRef, lset labels.Labels if err != nil { return 0, err } - return ref, err + return ref, nil } func (a *collectResultAppender) AppendExemplar(ref storage.SeriesRef, l labels.Labels, e exemplar.Exemplar) (storage.SeriesRef, error) { @@ -184,7 +184,7 @@ func (a *collectResultAppender) AppendHistogram(ref storage.SeriesRef, l labels. return a.next.AppendHistogram(ref, l, t, h, fh) } -func (a *collectResultAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, l labels.Labels, t, ct int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { +func (a *collectResultAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, l labels.Labels, _, ct int64, h *histogram.Histogram, _ *histogram.FloatHistogram) (storage.SeriesRef, error) { if h != nil { return a.AppendHistogram(ref, l, ct, &histogram.Histogram{}, nil) } @@ -205,7 +205,7 @@ func (a *collectResultAppender) UpdateMetadata(ref storage.SeriesRef, l labels.L return a.next.UpdateMetadata(ref, l, m) } -func (a *collectResultAppender) AppendCTZeroSample(ref storage.SeriesRef, l labels.Labels, t, ct int64) (storage.SeriesRef, error) { +func (a *collectResultAppender) AppendCTZeroSample(ref storage.SeriesRef, l labels.Labels, _, ct int64) (storage.SeriesRef, error) { return a.Append(ref, l, ct, 0.0) } diff --git a/scrape/manager_test.go b/scrape/manager_test.go index 75ac9ea692..d15b3edcec 100644 --- a/scrape/manager_test.go +++ b/scrape/manager_test.go @@ -23,6 +23,7 @@ import ( "net/http/httptest" "net/url" "os" + "slices" "sort" "strconv" "sync" @@ -55,11 +56,6 @@ import ( "github.com/prometheus/prometheus/util/testutil" ) -func init() { - // This can be removed when the default validation scheme in common is updated. - model.NameValidationScheme = model.UTF8Validation -} - func TestPopulateLabels(t *testing.T) { cases := []struct { in model.LabelSet @@ -479,7 +475,7 @@ func loadConfiguration(t testing.TB, c string) *config.Config { func noopLoop() loop { return &testLoop{ - startFunc: func(interval, timeout time.Duration, errc chan<- error) {}, + startFunc: func(_, _ time.Duration, _ chan<- error) {}, stopFunc: func() {}, } } @@ -730,7 +726,7 @@ func setupTestServer(t *testing.T, typ string, toWrite []byte) *httptest.Server once := sync.Once{} server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { fail := true once.Do(func() { fail = false @@ -972,7 +968,7 @@ func TestManagerCTZeroIngestionHistogram(t *testing.T) { once := sync.Once{} // Start fake HTTP target to that allow one scrape only. server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { fail := true once.Do(func() { fail = false @@ -1156,12 +1152,7 @@ func requireTargets( } sort.Strings(expectedTargets) sort.Strings(sTargets) - for i, t := range sTargets { - if t != expectedTargets[i] { - return false - } - } - return true + return slices.Equal(sTargets, expectedTargets) }, 1*time.Second, 100*time.Millisecond) } diff --git a/scrape/scrape.go b/scrape/scrape.go index 020bddb757..14c442fc25 100644 --- a/scrape/scrape.go +++ b/scrape/scrape.go @@ -456,7 +456,7 @@ func (sp *scrapePool) Sync(tgs []*targetgroup.Group) { for _, t := range targets { // Replicate .Labels().IsEmpty() with a loop here to avoid generating garbage. nonEmpty := false - t.LabelsRange(func(l labels.Label) { nonEmpty = true }) + t.LabelsRange(func(_ labels.Label) { nonEmpty = true }) switch { case nonEmpty: all = append(all, t) @@ -820,7 +820,7 @@ func (s *targetScraper) scrape(ctx context.Context) (*http.Response, error) { return s.client.Do(s.req.WithContext(ctx)) } -func (s *targetScraper) readResponse(ctx context.Context, resp *http.Response, w io.Writer) (string, error) { +func (s *targetScraper) readResponse(_ context.Context, resp *http.Response, w io.Writer) (string, error) { defer func() { io.Copy(io.Discard, resp.Body) resp.Body.Close() @@ -1034,8 +1034,6 @@ func (c *scrapeCache) iterDone(flushCache bool) { } } c.metaMtx.Unlock() - - c.iter++ } // Swap current and previous series. @@ -1045,6 +1043,8 @@ func (c *scrapeCache) iterDone(flushCache bool) { for k := range c.seriesCur { delete(c.seriesCur, k) } + + c.iter++ } func (c *scrapeCache) get(met []byte) (*cacheEntry, bool, bool) { @@ -1700,7 +1700,7 @@ loop: t = *parsedTimestamp } - if sl.cache.getDropped(met) { + if sl.cache.getDropped(met) || isHistogram && !sl.enableNativeHistogramIngestion { continue } ce, seriesCached, seriesAlreadyScraped := sl.cache.get(met) @@ -1747,25 +1747,25 @@ loop: err = storage.ErrDuplicateSampleForTimestamp } else { if sl.enableCTZeroIngestion { - if ctMs := p.CreatedTimestamp(); ctMs != nil { - if isHistogram && sl.enableNativeHistogramIngestion { + if ctMs := p.CreatedTimestamp(); ctMs != 0 { + if isHistogram { if h != nil { - ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, *ctMs, h, nil) + ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, ctMs, h, nil) } else { - ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, *ctMs, nil, fh) + ref, err = app.AppendHistogramCTZeroSample(ref, lset, t, ctMs, nil, fh) } } else { - ref, err = app.AppendCTZeroSample(ref, lset, t, *ctMs) + ref, err = app.AppendCTZeroSample(ref, lset, t, ctMs) } if err != nil && !errors.Is(err, storage.ErrOutOfOrderCT) { // OOO is a common case, ignoring completely for now. // CT is an experimental feature. For now, we don't need to fail the // scrape on errors updating the created timestamp, log debug. - sl.l.Debug("Error when appending CT in scrape loop", "series", string(met), "ct", *ctMs, "t", t, "err", err) + sl.l.Debug("Error when appending CT in scrape loop", "series", string(met), "ct", ctMs, "t", t, "err", err) } } } - if isHistogram && sl.enableNativeHistogramIngestion { + if isHistogram { if h != nil { ref, err = app.AppendHistogram(ref, lset, t, h, nil) } else { diff --git a/scrape/scrape_test.go b/scrape/scrape_test.go index 5d79650828..692fd75bcf 100644 --- a/scrape/scrape_test.go +++ b/scrape/scrape_test.go @@ -120,7 +120,7 @@ func runScrapeLoopTest(t *testing.T, s *teststorage.TestStorage, expectOutOfOrde // Create an appender for adding samples to the storage. app := s.Appender(context.Background()) capp := &collectResultAppender{next: app} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return capp }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return capp }, 0) // Current time for generating timestamps. now := time.Now() @@ -215,7 +215,7 @@ test_metric2{foo="bar"} 22 // Create an appender for adding samples to the storage. capp := &collectResultAppender{next: nopAppender{}} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return capp }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return capp }, 0) now := time.Now() slApp := sl.appender(context.Background()) @@ -249,12 +249,12 @@ type nopScraper struct { scraper } -func (n nopScraper) Report(start time.Time, dur time.Duration, err error) {} +func (n nopScraper) Report(_ time.Time, _ time.Duration, _ error) {} func TestScrapeReportMetadataUpdate(t *testing.T) { // Create an appender for adding samples to the storage. capp := &collectResultAppender{next: nopAppender{}} - sl := newBasicScrapeLoop(t, context.Background(), nopScraper{}, func(ctx context.Context) storage.Appender { return capp }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nopScraper{}, func(_ context.Context) storage.Appender { return capp }, 0) now := time.Now() slApp := sl.appender(context.Background()) @@ -503,7 +503,7 @@ func TestScrapePoolReload(t *testing.T) { // equivalents have been stopped. newLoop := func(opts scrapeLoopOptions) loop { l := &testLoop{interval: time.Duration(reloadCfg.ScrapeInterval), timeout: time.Duration(reloadCfg.ScrapeTimeout)} - l.startFunc = func(interval, timeout time.Duration, errc chan<- error) { + l.startFunc = func(interval, timeout time.Duration, _ chan<- error) { require.Equal(t, 3*time.Second, interval, "Unexpected scrape interval") require.Equal(t, 2*time.Second, timeout, "Unexpected scrape timeout") @@ -593,7 +593,7 @@ func TestScrapePoolReloadPreserveRelabeledIntervalTimeout(t *testing.T) { } newLoop := func(opts scrapeLoopOptions) loop { l := &testLoop{interval: opts.interval, timeout: opts.timeout} - l.startFunc = func(interval, timeout time.Duration, errc chan<- error) { + l.startFunc = func(interval, timeout time.Duration, _ chan<- error) { require.Equal(t, 5*time.Second, interval, "Unexpected scrape interval") require.Equal(t, 3*time.Second, timeout, "Unexpected scrape timeout") } @@ -651,10 +651,10 @@ func TestScrapePoolTargetLimit(t *testing.T) { var wg sync.WaitGroup // On starting to run, new loops created on reload check whether their preceding // equivalents have been stopped. - newLoop := func(opts scrapeLoopOptions) loop { + newLoop := func(_ scrapeLoopOptions) loop { wg.Add(1) l := &testLoop{ - startFunc: func(interval, timeout time.Duration, errc chan<- error) { + startFunc: func(_, _ time.Duration, _ chan<- error) { wg.Done() }, stopFunc: func() {}, @@ -884,10 +884,10 @@ func TestScrapePoolRaces(t *testing.T) { func TestScrapePoolScrapeLoopsStarted(t *testing.T) { var wg sync.WaitGroup - newLoop := func(opts scrapeLoopOptions) loop { + newLoop := func(_ scrapeLoopOptions) loop { wg.Add(1) l := &testLoop{ - startFunc: func(interval, timeout time.Duration, errc chan<- error) { + startFunc: func(_, _ time.Duration, _ chan<- error) { wg.Done() }, stopFunc: func() {}, @@ -1022,7 +1022,7 @@ func TestScrapeLoopStop(t *testing.T) { signal = make(chan struct{}, 1) appender = &collectResultAppender{} scraper = &testScraper{} - app = func(ctx context.Context) storage.Appender { return appender } + app = func(_ context.Context) storage.Appender { return appender } ) // Since we're writing samples directly below we need to provide a protocol fallback. @@ -1078,7 +1078,7 @@ func TestScrapeLoopRun(t *testing.T) { errc = make(chan error) scraper = &testScraper{} - app = func(ctx context.Context) storage.Appender { return &nopAppender{} } + app = func(_ context.Context) storage.Appender { return &nopAppender{} } scrapeMetrics = newTestScrapeMetrics(t) ) @@ -1186,7 +1186,7 @@ func TestScrapeLoopForcedErr(t *testing.T) { errc = make(chan error) scraper = &testScraper{} - app = func(ctx context.Context) storage.Appender { return &nopAppender{} } + app = func(_ context.Context) storage.Appender { return &nopAppender{} } ) ctx, cancel := context.WithCancel(context.Background()) @@ -1235,7 +1235,7 @@ func TestScrapeLoopMetadata(t *testing.T) { nil, nil, nopMutator, nopMutator, - func(ctx context.Context) storage.Appender { return nopAppender{} }, + func(_ context.Context) storage.Appender { return nopAppender{} }, cache, labels.NewSymbolTable(), 0, @@ -1325,14 +1325,13 @@ func TestScrapeLoopSeriesAdded(t *testing.T) { } func TestScrapeLoopFailWithInvalidLabelsAfterRelabel(t *testing.T) { - model.NameValidationScheme = model.LegacyValidation s := teststorage.New(t) defer s.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() target := &Target{ - labels: labels.FromStrings("pod_label_invalid_012", "test"), + labels: labels.FromStrings("pod_label_invalid_012\xff", "test"), } relabelConfig := []*relabel.Config{{ Action: relabel.LabelMap, @@ -1357,10 +1356,6 @@ func TestScrapeLoopFailWithInvalidLabelsAfterRelabel(t *testing.T) { func TestScrapeLoopFailLegacyUnderUTF8(t *testing.T) { // Test that scrapes fail when default validation is utf8 but scrape config is // legacy. - model.NameValidationScheme = model.UTF8Validation - defer func() { - model.NameValidationScheme = model.LegacyValidation - }() s := teststorage.New(t) defer s.Close() ctx, cancel := context.WithCancel(context.Background()) @@ -1540,7 +1535,7 @@ func TestSetOptionsHandlingStaleness(t *testing.T) { ) sl := newBasicScrapeLoop(t, ctx, scraper, app, 10*time.Millisecond) numScrapes := 0 - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { numScrapes++ if numScrapes == cue { action(sl) @@ -1608,7 +1603,7 @@ func TestScrapeLoopRunCreatesStaleMarkersOnFailedScrape(t *testing.T) { var ( signal = make(chan struct{}, 1) scraper = &testScraper{} - app = func(ctx context.Context) storage.Appender { return appender } + app = func(_ context.Context) storage.Appender { return appender } ) ctx, cancel := context.WithCancel(context.Background()) @@ -1617,7 +1612,7 @@ func TestScrapeLoopRunCreatesStaleMarkersOnFailedScrape(t *testing.T) { // Succeed once, several failures, then stop. numScrapes := 0 - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { numScrapes++ switch numScrapes { @@ -1654,7 +1649,7 @@ func TestScrapeLoopRunCreatesStaleMarkersOnParseFailure(t *testing.T) { var ( signal = make(chan struct{}, 1) scraper = &testScraper{} - app = func(ctx context.Context) storage.Appender { return appender } + app = func(_ context.Context) storage.Appender { return appender } numScrapes = 0 ) @@ -1663,7 +1658,7 @@ func TestScrapeLoopRunCreatesStaleMarkersOnParseFailure(t *testing.T) { sl := newBasicScrapeLoopWithFallback(t, ctx, scraper, app, 10*time.Millisecond, "text/plain") // Succeed once, several failures, then stop. - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { numScrapes++ switch numScrapes { case 1: @@ -1716,7 +1711,7 @@ func TestScrapeLoopCache(t *testing.T) { numScrapes := 0 - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { switch numScrapes { case 1, 2: _, ok := sl.cache.series["metric_a"] @@ -1770,7 +1765,7 @@ func TestScrapeLoopCacheMemoryExhaustionProtection(t *testing.T) { var ( signal = make(chan struct{}, 1) scraper = &testScraper{} - app = func(ctx context.Context) storage.Appender { return appender } + app = func(_ context.Context) storage.Appender { return appender } ) ctx, cancel := context.WithCancel(context.Background()) @@ -1778,7 +1773,7 @@ func TestScrapeLoopCacheMemoryExhaustionProtection(t *testing.T) { numScrapes := 0 - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { numScrapes++ if numScrapes < 5 { s := "" @@ -1866,7 +1861,7 @@ func TestScrapeLoopAppend(t *testing.T) { labels: labels.FromStrings(test.discoveryLabels...), } - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.sampleMutator = func(l labels.Labels) labels.Labels { return mutateSampleLabels(l, discoveryLabels, test.honorLabels, nil) } @@ -1954,7 +1949,7 @@ func TestScrapeLoopAppendForConflictingPrefixedLabels(t *testing.T) { for name, tc := range testcases { t.Run(name, func(t *testing.T) { app := &collectResultAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.sampleMutator = func(l labels.Labels) labels.Labels { return mutateSampleLabels(l, &Target{labels: labels.FromStrings(tc.targetLabels...)}, false, nil) } @@ -1978,7 +1973,7 @@ func TestScrapeLoopAppendForConflictingPrefixedLabels(t *testing.T) { func TestScrapeLoopAppendCacheEntryButErrNotFound(t *testing.T) { // collectResultAppender's AddFast always returns ErrNotFound if we don't give it a next. app := &collectResultAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) fakeRef := storage.SeriesRef(1) expValue := float64(1) @@ -2016,7 +2011,7 @@ func TestScrapeLoopAppendSampleLimit(t *testing.T) { resApp := &collectResultAppender{} app := &limitAppender{Appender: resApp, limit: 1} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.sampleMutator = func(l labels.Labels) labels.Labels { if l.Has("deleteme") { return labels.EmptyLabels() @@ -2075,7 +2070,7 @@ func TestScrapeLoop_HistogramBucketLimit(t *testing.T) { resApp := &collectResultAppender{} app := &bucketLimitAppender{Appender: resApp, limit: 2} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.enableNativeHistogramIngestion = true sl.sampleMutator = func(l labels.Labels) labels.Labels { if l.Has("deleteme") { @@ -2187,7 +2182,7 @@ func TestScrapeLoop_ChangingMetricString(t *testing.T) { defer s.Close() capp := &collectResultAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return capp }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return capp }, 0) now := time.Now() slApp := sl.appender(context.Background()) @@ -2219,7 +2214,7 @@ func TestScrapeLoopAppendFailsWithNoContentType(t *testing.T) { app := &collectResultAppender{} // Explicitly setting the lack of fallback protocol here to make it obvious. - sl := newBasicScrapeLoopWithFallback(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0, "") + sl := newBasicScrapeLoopWithFallback(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0, "") now := time.Now() slApp := sl.appender(context.Background()) @@ -2233,7 +2228,7 @@ func TestScrapeLoopAppendEmptyWithNoContentType(t *testing.T) { app := &collectResultAppender{} // Explicitly setting the lack of fallback protocol here to make it obvious. - sl := newBasicScrapeLoopWithFallback(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0, "") + sl := newBasicScrapeLoopWithFallback(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0, "") now := time.Now() slApp := sl.appender(context.Background()) @@ -2245,7 +2240,7 @@ func TestScrapeLoopAppendEmptyWithNoContentType(t *testing.T) { func TestScrapeLoopAppendStaleness(t *testing.T) { app := &collectResultAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) now := time.Now() slApp := sl.appender(context.Background()) @@ -2275,7 +2270,7 @@ func TestScrapeLoopAppendStaleness(t *testing.T) { func TestScrapeLoopAppendNoStalenessIfTimestamp(t *testing.T) { app := &collectResultAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) now := time.Now() slApp := sl.appender(context.Background()) _, _, _, err := sl.append(slApp, []byte("metric_a 1 1000\n"), "text/plain", now) @@ -2299,7 +2294,7 @@ func TestScrapeLoopAppendNoStalenessIfTimestamp(t *testing.T) { func TestScrapeLoopAppendStalenessIfTrackTimestampStaleness(t *testing.T) { app := &collectResultAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.trackTimestampsStaleness = true now := time.Now() @@ -2395,7 +2390,7 @@ metric_total{n="2"} 2 # {t="2"} 2.0 20000 }, }, { - title: "Native histogram with three exemplars", + title: "Native histogram with three exemplars from classic buckets", enableNativeHistogramsIngestion: true, scrapeText: `name: "test_histogram" @@ -2644,6 +2639,180 @@ metric: < {Labels: labels.FromStrings("dummyID", "58215"), Value: -0.00019, Ts: 1625851055146, HasTs: true}, }, }, + { + title: "Native histogram with exemplars and no classic buckets", + contentType: "application/vnd.google.protobuf", + enableNativeHistogramsIngestion: true, + scrapeText: `name: "test_histogram" +help: "Test histogram." +type: HISTOGRAM +metric: < + histogram: < + sample_count: 175 + sample_sum: 0.0008280461746287094 + schema: 3 + zero_threshold: 2.938735877055719e-39 + zero_count: 2 + negative_span: < + offset: -162 + length: 1 + > + negative_span: < + offset: 23 + length: 4 + > + negative_delta: 1 + negative_delta: 3 + negative_delta: -2 + negative_delta: -1 + negative_delta: 1 + positive_span: < + offset: -161 + length: 1 + > + positive_span: < + offset: 8 + length: 3 + > + positive_delta: 1 + positive_delta: 2 + positive_delta: -1 + positive_delta: -1 + exemplars: < + label: < + name: "dummyID" + value: "59732" + > + value: -0.00039 + timestamp: < + seconds: 1625851155 + nanos: 146848499 + > + > + exemplars: < + label: < + name: "dummyID" + value: "58242" + > + value: -0.00019 + timestamp: < + seconds: 1625851055 + nanos: 146848599 + > + > + exemplars: < + label: < + name: "dummyID" + value: "5617" + > + value: -0.00029 + > + > + timestamp_ms: 1234568 +> + +`, + histograms: []histogramSample{{ + t: 1234568, + metric: labels.FromStrings("__name__", "test_histogram"), + h: &histogram.Histogram{ + Count: 175, + ZeroCount: 2, + Sum: 0.0008280461746287094, + ZeroThreshold: 2.938735877055719e-39, + Schema: 3, + PositiveSpans: []histogram.Span{ + {Offset: -161, Length: 1}, + {Offset: 8, Length: 3}, + }, + NegativeSpans: []histogram.Span{ + {Offset: -162, Length: 1}, + {Offset: 23, Length: 4}, + }, + PositiveBuckets: []int64{1, 2, -1, -1}, + NegativeBuckets: []int64{1, 3, -2, -1, 1}, + }, + }}, + exemplars: []exemplar.Exemplar{ + // Exemplars with missing timestamps are dropped for native histograms. + {Labels: labels.FromStrings("dummyID", "58242"), Value: -0.00019, Ts: 1625851055146, HasTs: true}, + {Labels: labels.FromStrings("dummyID", "59732"), Value: -0.00039, Ts: 1625851155146, HasTs: true}, + }, + }, + { + title: "Native histogram with exemplars but ingestion disabled", + contentType: "application/vnd.google.protobuf", + enableNativeHistogramsIngestion: false, + scrapeText: `name: "test_histogram" +help: "Test histogram." +type: HISTOGRAM +metric: < + histogram: < + sample_count: 175 + sample_sum: 0.0008280461746287094 + schema: 3 + zero_threshold: 2.938735877055719e-39 + zero_count: 2 + negative_span: < + offset: -162 + length: 1 + > + negative_span: < + offset: 23 + length: 4 + > + negative_delta: 1 + negative_delta: 3 + negative_delta: -2 + negative_delta: -1 + negative_delta: 1 + positive_span: < + offset: -161 + length: 1 + > + positive_span: < + offset: 8 + length: 3 + > + positive_delta: 1 + positive_delta: 2 + positive_delta: -1 + positive_delta: -1 + exemplars: < + label: < + name: "dummyID" + value: "59732" + > + value: -0.00039 + timestamp: < + seconds: 1625851155 + nanos: 146848499 + > + > + exemplars: < + label: < + name: "dummyID" + value: "58242" + > + value: -0.00019 + timestamp: < + seconds: 1625851055 + nanos: 146848599 + > + > + exemplars: < + label: < + name: "dummyID" + value: "5617" + > + value: -0.00029 + > + > + timestamp_ms: 1234568 +> + +`, + }, } for _, test := range tests { @@ -2654,7 +2823,7 @@ metric: < labels: labels.FromStrings(test.discoveryLabels...), } - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.enableNativeHistogramIngestion = test.enableNativeHistogramsIngestion sl.sampleMutator = func(l labels.Labels) labels.Labels { return mutateSampleLabels(l, discoveryLabels, false, nil) @@ -2738,7 +2907,7 @@ func TestScrapeLoopAppendExemplarSeries(t *testing.T) { app := &collectResultAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.sampleMutator = func(l labels.Labels) labels.Labels { return mutateSampleLabels(l, discoveryLabels, false, nil) } @@ -2775,13 +2944,13 @@ func TestScrapeLoopRunReportsTargetDownOnScrapeError(t *testing.T) { var ( scraper = &testScraper{} appender = &collectResultAppender{} - app = func(ctx context.Context) storage.Appender { return appender } + app = func(_ context.Context) storage.Appender { return appender } ) ctx, cancel := context.WithCancel(context.Background()) sl := newBasicScrapeLoop(t, ctx, scraper, app, 10*time.Millisecond) - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, _ io.Writer) error { cancel() return errors.New("scrape failed") } @@ -2794,13 +2963,13 @@ func TestScrapeLoopRunReportsTargetDownOnInvalidUTF8(t *testing.T) { var ( scraper = &testScraper{} appender = &collectResultAppender{} - app = func(ctx context.Context) storage.Appender { return appender } + app = func(_ context.Context) storage.Appender { return appender } ) ctx, cancel := context.WithCancel(context.Background()) sl := newBasicScrapeLoop(t, ctx, scraper, app, 10*time.Millisecond) - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { cancel() w.Write([]byte("a{l=\"\xff\"} 1\n")) return nil @@ -2829,7 +2998,7 @@ func (app *errorAppender) Append(ref storage.SeriesRef, lset labels.Labels, t in func TestScrapeLoopAppendGracefullyIfAmendOrOutOfOrderOrOutOfBounds(t *testing.T) { app := &errorAppender{} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) now := time.Unix(1, 0) slApp := sl.appender(context.Background()) @@ -2853,7 +3022,7 @@ func TestScrapeLoopAppendGracefullyIfAmendOrOutOfOrderOrOutOfBounds(t *testing.T func TestScrapeLoopOutOfBoundsTimeError(t *testing.T) { app := &collectResultAppender{} sl := newBasicScrapeLoop(t, context.Background(), nil, - func(ctx context.Context) storage.Appender { + func(_ context.Context) storage.Appender { return &timeLimitAppender{ Appender: app, maxTime: timestamp.FromTime(time.Now().Add(10 * time.Minute)), @@ -2996,7 +3165,7 @@ func TestTargetScrapeScrapeCancel(t *testing.T) { block := make(chan struct{}) server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { <-block }), ) @@ -3052,7 +3221,7 @@ func TestTargetScrapeScrapeCancel(t *testing.T) { func TestTargetScrapeScrapeNotFound(t *testing.T) { server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) }), ) @@ -3088,7 +3257,7 @@ func TestTargetScraperBodySizeLimit(t *testing.T) { ) var gzipResponse bool server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", `text/plain; version=0.0.4`) if gzipResponse { w.Header().Set("Content-Encoding", "gzip") @@ -3178,11 +3347,11 @@ func (ts *testScraper) Report(start time.Time, duration time.Duration, err error ts.lastError = err } -func (ts *testScraper) scrape(ctx context.Context) (*http.Response, error) { +func (ts *testScraper) scrape(_ context.Context) (*http.Response, error) { return nil, ts.scrapeErr } -func (ts *testScraper) readResponse(ctx context.Context, resp *http.Response, w io.Writer) (string, error) { +func (ts *testScraper) readResponse(ctx context.Context, _ *http.Response, w io.Writer) (string, error) { if ts.scrapeFunc != nil { return "", ts.scrapeFunc(ctx, w) } @@ -3195,7 +3364,7 @@ func TestScrapeLoop_RespectTimestamps(t *testing.T) { app := s.Appender(context.Background()) capp := &collectResultAppender{next: app} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return capp }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return capp }, 0) now := time.Now() slApp := sl.appender(context.Background()) @@ -3221,7 +3390,7 @@ func TestScrapeLoop_DiscardTimestamps(t *testing.T) { capp := &collectResultAppender{next: app} - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return capp }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return capp }, 0) sl.honorTimestamps = false now := time.Now() @@ -3284,7 +3453,7 @@ func TestScrapeLoopDiscardUnnamedMetrics(t *testing.T) { app := s.Appender(context.Background()) ctx, cancel := context.WithCancel(context.Background()) - sl := newBasicScrapeLoop(t, context.Background(), &testScraper{}, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), &testScraper{}, func(_ context.Context) storage.Appender { return app }, 0) sl.sampleMutator = func(l labels.Labels) labels.Labels { if l.Has("drop") { return labels.FromStrings("no", "name") // This label set will trigger an error. @@ -3613,7 +3782,7 @@ func TestScrapeReportSingleAppender(t *testing.T) { numScrapes := 0 - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { numScrapes++ if numScrapes%4 == 0 { return errors.New("scrape failed") @@ -3711,8 +3880,6 @@ func TestScrapeReportLimit(t *testing.T) { func TestScrapeUTF8(t *testing.T) { s := teststorage.New(t) defer s.Close() - model.NameValidationScheme = model.UTF8Validation - t.Cleanup(func() { model.NameValidationScheme = model.LegacyValidation }) cfg := &config.ScrapeConfig{ JobName: "test", @@ -3826,7 +3993,7 @@ func TestScrapeLoopLabelLimit(t *testing.T) { labels: labels.FromStrings(test.discoveryLabels...), } - sl := newBasicScrapeLoop(t, context.Background(), nil, func(ctx context.Context) storage.Appender { return app }, 0) + sl := newBasicScrapeLoop(t, context.Background(), nil, func(_ context.Context) storage.Appender { return app }, 0) sl.sampleMutator = func(l labels.Labels) labels.Labels { return mutateSampleLabels(l, discoveryLabels, false, nil) } @@ -4424,7 +4591,7 @@ metric: < scrapeCount := 0 scraped := make(chan bool) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { if metricsText.contentType != "" { w.Header().Set("Content-Type", `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`) for _, text := range metricsText.text { @@ -4524,7 +4691,7 @@ func TestScrapeLoopRunCreatesStaleMarkersOnFailedScrapeForTimestampedMetrics(t * var ( signal = make(chan struct{}, 1) scraper = &testScraper{} - app = func(ctx context.Context) storage.Appender { return appender } + app = func(_ context.Context) storage.Appender { return appender } ) ctx, cancel := context.WithCancel(context.Background()) @@ -4534,7 +4701,7 @@ func TestScrapeLoopRunCreatesStaleMarkersOnFailedScrapeForTimestampedMetrics(t * // Succeed once, several failures, then stop. numScrapes := 0 - scraper.scrapeFunc = func(ctx context.Context, w io.Writer) error { + scraper.scrapeFunc = func(_ context.Context, w io.Writer) error { numScrapes++ switch numScrapes { @@ -4861,7 +5028,7 @@ func testNativeHistogramMaxSchemaSet(t *testing.T, minBucketFactor string, expec buffer := protoMarshalDelimited(t, histogramMetricFamily) // Create a HTTP server to serve /metrics via ProtoBuf - metricsServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + metricsServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`) w.Write(buffer) })) @@ -5104,7 +5271,7 @@ func newScrapableServer(scrapeText string) (s *httptest.Server, scrapedTwice cha var scrapes int scrapedTwice = make(chan bool) - return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, scrapeText) scrapes++ if scrapes == 2 { @@ -5116,7 +5283,7 @@ func newScrapableServer(scrapeText string) (s *httptest.Server, scrapedTwice cha // Regression test for the panic fixed in https://github.com/prometheus/prometheus/pull/15523. func TestScrapePoolScrapeAfterReload(t *testing.T) { h := httptest.NewServer(http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte{0x42, 0x42}) }, )) @@ -5153,3 +5320,40 @@ func TestScrapePoolScrapeAfterReload(t *testing.T) { <-time.After(1 * time.Second) } + +// Regression test against https://github.com/prometheus/prometheus/issues/16160. +// The first scrape fails with a parsing error, but the second should +// succeed and cause `metric_1=11` to appear in the appender. +func TestScrapeAppendWithParseError(t *testing.T) { + const ( + scrape1 = `metric_a 1 +` + scrape2 = `metric_a 11 +# EOF` + ) + + sl := newBasicScrapeLoop(t, context.Background(), nil, nil, 0) + sl.cache = newScrapeCache(sl.metrics) + + now := time.Now() + capp := &collectResultAppender{next: nopAppender{}} + _, _, _, err := sl.append(capp, []byte(scrape1), "application/openmetrics-text", now) + require.Error(t, err) + _, _, _, err = sl.append(capp, nil, "application/openmetrics-text", now) + require.NoError(t, err) + require.Empty(t, capp.resultFloats) + + capp = &collectResultAppender{next: nopAppender{}} + _, _, _, err = sl.append(capp, []byte(scrape2), "application/openmetrics-text", now.Add(15*time.Second)) + require.NoError(t, err) + require.NoError(t, capp.Commit()) + + want := []floatSample{ + { + metric: labels.FromStrings(model.MetricNameLabel, "metric_a"), + t: timestamp.FromTime(now.Add(15 * time.Second)), + f: 11, + }, + } + requireEqual(t, want, capp.resultFloats, "Appended samples not as expected:\n%s", capp) +} diff --git a/scrape/target_test.go b/scrape/target_test.go index 9dad18f01c..85f2280c41 100644 --- a/scrape/target_test.go +++ b/scrape/target_test.go @@ -147,7 +147,7 @@ func newTestTarget(targetURL string, _ time.Duration, lbls labels.Labels) *Targe func TestNewHTTPBearerToken(t *testing.T) { server := httptest.NewServer( http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(_ http.ResponseWriter, r *http.Request) { expected := "Bearer 1234" received := r.Header.Get("Authorization") require.Equal(t, expected, received, "Authorization header was not set correctly.") @@ -168,7 +168,7 @@ func TestNewHTTPBearerToken(t *testing.T) { func TestNewHTTPBearerTokenFile(t *testing.T) { server := httptest.NewServer( http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(_ http.ResponseWriter, r *http.Request) { expected := "Bearer 12345" received := r.Header.Get("Authorization") require.Equal(t, expected, received, "Authorization header was not set correctly.") @@ -189,7 +189,7 @@ func TestNewHTTPBearerTokenFile(t *testing.T) { func TestNewHTTPBasicAuth(t *testing.T) { server := httptest.NewServer( http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(_ http.ResponseWriter, r *http.Request) { username, password, ok := r.BasicAuth() require.True(t, ok, "Basic authorization header was not set correctly.") require.Equal(t, "user", username) @@ -214,7 +214,7 @@ func TestNewHTTPBasicAuth(t *testing.T) { func TestNewHTTPCACert(t *testing.T) { server := httptest.NewUnstartedServer( http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", `text/plain; version=0.0.4`) w.Write([]byte{}) }, @@ -238,7 +238,7 @@ func TestNewHTTPCACert(t *testing.T) { func TestNewHTTPClientCert(t *testing.T) { server := httptest.NewUnstartedServer( http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", `text/plain; version=0.0.4`) w.Write([]byte{}) }, @@ -267,7 +267,7 @@ func TestNewHTTPClientCert(t *testing.T) { func TestNewHTTPWithServerName(t *testing.T) { server := httptest.NewUnstartedServer( http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", `text/plain; version=0.0.4`) w.Write([]byte{}) }, @@ -292,7 +292,7 @@ func TestNewHTTPWithServerName(t *testing.T) { func TestNewHTTPWithBadServerName(t *testing.T) { server := httptest.NewUnstartedServer( http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { + func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", `text/plain; version=0.0.4`) w.Write([]byte{}) }, diff --git a/scripts/compress_assets.sh b/scripts/compress_assets.sh index 19e1e22486..91b1c7b31a 100755 --- a/scripts/compress_assets.sh +++ b/scripts/compress_assets.sh @@ -13,9 +13,9 @@ fi cd web/ui cp embed.go.tmpl embed.go -GZIP_OPTS="-fk" +GZIP_OPTS="-fkn" # gzip option '-k' may not always exist in the latest gzip available on different distros. -if ! gzip -k -h &>/dev/null; then GZIP_OPTS="-f"; fi +if ! gzip -k -h &>/dev/null; then GZIP_OPTS="-fn"; fi mkdir -p static find static -type f -name '*.gz' -delete diff --git a/scripts/golangci-lint.yml b/scripts/golangci-lint.yml index def9007ac6..e36a9f1a47 100644 --- a/scripts/golangci-lint.yml +++ b/scripts/golangci-lint.yml @@ -28,12 +28,12 @@ jobs: - name: Install Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: - go-version: 1.23.x + go-version: 1.24.x - name: Install snmp_exporter/generator dependencies run: sudo apt-get update && sudo apt-get -y install libsnmp-dev if: github.repository == 'prometheus/snmp_exporter' - name: Lint - uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 + uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0 with: args: --verbose - version: v1.63.4 + version: v1.64.6 diff --git a/storage/interface.go b/storage/interface.go index 40ea8abebe..e6fc03d523 100644 --- a/storage/interface.go +++ b/storage/interface.go @@ -43,7 +43,6 @@ var ( ErrExemplarLabelLength = fmt.Errorf("label length for exemplar exceeds maximum of %d UTF-8 characters", exemplar.ExemplarMaxLabelSetLength) ErrExemplarsDisabled = errors.New("exemplar storage is disabled or max exemplars is less than or equal to 0") ErrNativeHistogramsDisabled = errors.New("native histograms are disabled") - ErrOOONativeHistogramsDisabled = errors.New("out-of-order native histogram ingestion is disabled") // ErrOutOfOrderCT indicates failed append of CT to the storage // due to CT being older the then newer sample. diff --git a/storage/merge.go b/storage/merge.go index 2f7f661adb..fded50564c 100644 --- a/storage/merge.go +++ b/storage/merge.go @@ -133,7 +133,7 @@ func filterChunkQueriers(qs []ChunkQuerier) []ChunkQuerier { } // Select returns a set of series that matches the given label matchers. -func (q *mergeGenericQuerier) Select(ctx context.Context, sortSeries bool, hints *SelectHints, matchers ...*labels.Matcher) genericSeriesSet { +func (q *mergeGenericQuerier) Select(ctx context.Context, _ bool, hints *SelectHints, matchers ...*labels.Matcher) genericSeriesSet { seriesSets := make([]genericSeriesSet, 0, len(q.queriers)) var limit int if hints != nil { diff --git a/storage/merge_test.go b/storage/merge_test.go index eaf0610646..b182d417a6 100644 --- a/storage/merge_test.go +++ b/storage/merge_test.go @@ -974,7 +974,7 @@ func (m *mockQuerier) Select(_ context.Context, sortSeries bool, _ *SelectHints, return &mockSeriesSet{idx: -1, series: ret, warnings: m.warnings, err: m.err} } -func (m *mockQuerier) LabelValues(_ context.Context, name string, hints *LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (m *mockQuerier) LabelValues(_ context.Context, name string, _ *LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { m.mtx.Lock() m.labelNamesRequested = append(m.labelNamesRequested, labelNameRequest{ name: name, @@ -1424,7 +1424,7 @@ func BenchmarkMergeLabelValuesWithLimit(b *testing.B) { }, } - b.Run("benchmark", func(b *testing.B) { + b.Run("benchmark", func(_ *testing.B) { ctx := context.Background() hints := &LabelHints{ Limit: 1000, @@ -1711,7 +1711,7 @@ func (e errIterator) Next() chunkenc.ValueType { return chunkenc.ValNone } -func (e errIterator) Seek(t int64) chunkenc.ValueType { +func (e errIterator) Seek(_ int64) chunkenc.ValueType { return chunkenc.ValNone } diff --git a/storage/remote/client.go b/storage/remote/client.go index aadf15307c..714ee872e9 100644 --- a/storage/remote/client.go +++ b/storage/remote/client.go @@ -42,6 +42,7 @@ import ( "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/storage/remote/azuread" "github.com/prometheus/prometheus/storage/remote/googleiam" + "github.com/prometheus/prometheus/util/compression" ) const ( @@ -53,17 +54,6 @@ const ( appProtoContentType = "application/x-protobuf" ) -// Compression represents the encoding. Currently remote storage supports only -// one, but we experiment with more, thus leaving the compression scaffolding -// for now. -// NOTE(bwplotka): Keeping it public, as a non-stable help for importers to use. -type Compression string - -const ( - // SnappyBlockCompression represents https://github.com/google/snappy/blob/2c94e11145f0b7b184b831577c93e5a41c4c0346/format_description.txt - SnappyBlockCompression Compression = "snappy" -) - var ( // UserAgent represents Prometheus version to use for user agent header. UserAgent = version.PrometheusUserAgent() @@ -130,7 +120,7 @@ type Client struct { readQueriesDuration prometheus.ObserverVec writeProtoMsg config.RemoteWriteProtoMsg - writeCompression Compression // Not exposed by ClientConfig for now. + writeCompression compression.Type // Not exposed by ClientConfig for now. } // ClientConfig configures a client. @@ -232,7 +222,7 @@ func NewWriteClient(name string, conf *ClientConfig) (WriteClient, error) { retryOnRateLimit: conf.RetryOnRateLimit, timeout: time.Duration(conf.Timeout), writeProtoMsg: writeProtoMsg, - writeCompression: SnappyBlockCompression, + writeCompression: compression.Snappy, }, nil } @@ -269,7 +259,7 @@ func (c *Client) Store(ctx context.Context, req []byte, attempt int) (WriteRespo return WriteResponseStats{}, err } - httpReq.Header.Add("Content-Encoding", string(c.writeCompression)) + httpReq.Header.Add("Content-Encoding", c.writeCompression) httpReq.Header.Set("Content-Type", remoteWriteContentTypeHeaders[c.writeProtoMsg]) httpReq.Header.Set("User-Agent", UserAgent) if c.writeProtoMsg == config.RemoteWriteProtoMsgV1 { @@ -375,7 +365,8 @@ func (c *Client) Read(ctx context.Context, query *prompb.Query, sortSeries bool) httpReq.Header.Set("User-Agent", UserAgent) httpReq.Header.Set("X-Prometheus-Remote-Read-Version", "0.1.0") - ctx, cancel := context.WithTimeout(ctx, c.timeout) + errTimeout := fmt.Errorf("%w: request timed out after %s", context.DeadlineExceeded, c.timeout) + ctx, cancel := context.WithTimeoutCause(ctx, c.timeout, errTimeout) ctx, span := otel.Tracer("").Start(ctx, "Remote Read", trace.WithSpanKind(trace.SpanKindClient)) defer span.End() diff --git a/storage/remote/client_test.go b/storage/remote/client_test.go index c8b3d487e7..112e96d2b6 100644 --- a/storage/remote/client_test.go +++ b/storage/remote/client_test.go @@ -61,7 +61,7 @@ func TestStoreHTTPErrorHandling(t *testing.T) { for _, test := range tests { server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { http.Error(w, longErrMessage, test.code) }), ) @@ -93,7 +93,7 @@ func TestStoreHTTPErrorHandling(t *testing.T) { func TestClientRetryAfter(t *testing.T) { setupServer := func(statusCode int) *httptest.Server { return httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Retry-After", "5") http.Error(w, longErrMessage, statusCode) }), @@ -180,7 +180,7 @@ func TestClientCustomHeaders(t *testing.T) { var called bool server := httptest.NewServer( - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { called = true receivedHeaders := r.Header for name, value := range headersToSend { @@ -220,6 +220,7 @@ func TestReadClient(t *testing.T) { name string query *prompb.Query httpHandler http.HandlerFunc + timeout time.Duration expectedLabels []map[string]string expectedSamples [][]model.SamplePair expectedErrorContains string @@ -271,7 +272,7 @@ func TestReadClient(t *testing.T) { StartTimestampMs: 4000, EndTimestampMs: 12000, }, - httpHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + httpHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/x-streamed-protobuf; proto=prometheus.ChunkedReadResponse") flusher, ok := w.(http.Flusher) @@ -324,11 +325,17 @@ func TestReadClient(t *testing.T) { }, { name: "unsupported content type", - httpHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + httpHandler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "foobar") }), expectedErrorContains: "unsupported content type", }, + { + name: "timeout", + httpHandler: delayedResponseHTTPHandler(t, 15*time.Millisecond), + timeout: 5 * time.Millisecond, + expectedErrorContains: "context deadline exceeded: request timed out after 5ms", + }, } for _, test := range tests { @@ -339,9 +346,13 @@ func TestReadClient(t *testing.T) { u, err := url.Parse(server.URL) require.NoError(t, err) + if test.timeout == 0 { + test.timeout = 5 * time.Second + } + conf := &ClientConfig{ URL: &config_util.URL{URL: u}, - Timeout: model.Duration(5 * time.Second), + Timeout: model.Duration(test.timeout), ChunkedReadLimit: config.DefaultChunkedReadLimit, } c, err := NewReadClient("test", conf) @@ -399,7 +410,7 @@ func TestReadClient(t *testing.T) { } func sampledResponseHTTPHandler(t *testing.T) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/x-protobuf") resp := prompb.ReadResponse{ @@ -437,3 +448,16 @@ func sampledResponseHTTPHandler(t *testing.T) http.HandlerFunc { require.NoError(t, err) } } + +func delayedResponseHTTPHandler(t *testing.T, delay time.Duration) http.HandlerFunc { + return func(w http.ResponseWriter, _ *http.Request) { + time.Sleep(delay) + + w.Header().Set("Content-Type", "application/x-protobuf") + b, err := proto.Marshal(&prompb.ReadResponse{}) + require.NoError(t, err) + + _, err = w.Write(snappy.Encode(nil, b)) + require.NoError(t, err) + } +} diff --git a/storage/remote/codec_test.go b/storage/remote/codec_test.go index 3557a87eb5..51cdd1e39a 100644 --- a/storage/remote/codec_test.go +++ b/storage/remote/codec_test.go @@ -165,11 +165,6 @@ func TestWriteV2RequestFixture(t *testing.T) { } func TestValidateLabelsAndMetricName(t *testing.T) { - oldScheme := model.NameValidationScheme - model.NameValidationScheme = model.LegacyValidation - defer func() { - model.NameValidationScheme = oldScheme - }() tests := []struct { input []prompb.Label expectedErr string @@ -194,18 +189,10 @@ func TestValidateLabelsAndMetricName(t *testing.T) { { input: []prompb.Label{ {Name: "__name__", Value: "name"}, - {Name: "@labelName", Value: "labelValue"}, + {Name: "@labelName\xff", Value: "labelValue"}, }, - expectedErr: "invalid label name: @labelName", - description: "label name with @", - }, - { - input: []prompb.Label{ - {Name: "__name__", Value: "name"}, - {Name: "123labelName", Value: "labelValue"}, - }, - expectedErr: "invalid label name: 123labelName", - description: "label name starts with numbers", + expectedErr: "invalid label name: @labelName\xff", + description: "label name with \xff", }, { input: []prompb.Label{ @@ -225,10 +212,10 @@ func TestValidateLabelsAndMetricName(t *testing.T) { }, { input: []prompb.Label{ - {Name: "__name__", Value: "@invalid_name"}, + {Name: "__name__", Value: "invalid_name\xff"}, }, - expectedErr: "invalid metric name: @invalid_name", - description: "metric name starts with @", + expectedErr: "invalid metric name: invalid_name\xff", + description: "metric name has invalid utf8", }, { input: []prompb.Label{ diff --git a/storage/remote/queue_manager.go b/storage/remote/queue_manager.go index b274707bff..67071f1f8d 100644 --- a/storage/remote/queue_manager.go +++ b/storage/remote/queue_manager.go @@ -24,7 +24,6 @@ import ( "time" "github.com/gogo/protobuf/proto" - "github.com/golang/snappy" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/prometheus/common/promslog" @@ -45,6 +44,7 @@ import ( "github.com/prometheus/prometheus/tsdb/chunks" "github.com/prometheus/prometheus/tsdb/record" "github.com/prometheus/prometheus/tsdb/wlog" + "github.com/prometheus/prometheus/util/compression" ) const ( @@ -421,7 +421,7 @@ type QueueManager struct { clientMtx sync.RWMutex storeClient WriteClient protoMsg config.RemoteWriteProtoMsg - enc Compression + compr compression.Type seriesMtx sync.Mutex // Covers seriesLabels, seriesMetadata, droppedSeries and builder. seriesLabels map[chunks.HeadSeriesRef]labels.Labels @@ -512,7 +512,7 @@ func NewQueueManager( highestRecvTimestamp: highestRecvTimestamp, protoMsg: protoMsg, - enc: SnappyBlockCompression, // Hardcoded for now, but scaffolding exists for likely future use. + compr: compression.Snappy, // Hardcoded for now, but scaffolding exists for likely future use. } walMetadata := false @@ -574,7 +574,7 @@ func (t *QueueManager) AppendWatcherMetadata(ctx context.Context, metadata []scr func (t *QueueManager) sendMetadataWithBackoff(ctx context.Context, metadata []prompb.MetricMetadata, pBuf *proto.Buffer) error { // Build the WriteRequest with no samples (v1 flow). - req, _, _, err := buildWriteRequest(t.logger, nil, metadata, pBuf, nil, nil, t.enc) + req, _, _, err := buildWriteRequest(t.logger, nil, metadata, pBuf, nil, nil, t.compr) if err != nil { return err } @@ -1502,7 +1502,7 @@ func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) { pBuf = proto.NewBuffer(nil) pBufRaw []byte - buf []byte + encBuf = compression.NewSyncEncodeBuffer() ) // TODO(@tpaschalis) Should we also raise the max if we have WAL metadata? if s.qm.sendExemplars { @@ -1534,7 +1534,7 @@ func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) { } defer stop() - sendBatch := func(batch []timeSeries, protoMsg config.RemoteWriteProtoMsg, enc Compression, timer bool) { + sendBatch := func(batch []timeSeries, protoMsg config.RemoteWriteProtoMsg, compr compression.Type, timer bool) { switch protoMsg { case config.RemoteWriteProtoMsgV1: nPendingSamples, nPendingExemplars, nPendingHistograms := populateTimeSeries(batch, pendingData, s.qm.sendExemplars, s.qm.sendNativeHistograms) @@ -1543,11 +1543,11 @@ func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) { s.qm.logger.Debug("runShard timer ticked, sending buffered data", "samples", nPendingSamples, "exemplars", nPendingExemplars, "shard", shardNum, "histograms", nPendingHistograms) } - _ = s.sendSamples(ctx, pendingData[:n], nPendingSamples, nPendingExemplars, nPendingHistograms, pBuf, &buf, enc) + _ = s.sendSamples(ctx, pendingData[:n], nPendingSamples, nPendingExemplars, nPendingHistograms, pBuf, encBuf, compr) case config.RemoteWriteProtoMsgV2: nPendingSamples, nPendingExemplars, nPendingHistograms, nPendingMetadata := populateV2TimeSeries(&symbolTable, batch, pendingDataV2, s.qm.sendExemplars, s.qm.sendNativeHistograms) n := nPendingSamples + nPendingExemplars + nPendingHistograms - _ = s.sendV2Samples(ctx, pendingDataV2[:n], symbolTable.Symbols(), nPendingSamples, nPendingExemplars, nPendingHistograms, nPendingMetadata, &pBufRaw, &buf, enc) + _ = s.sendV2Samples(ctx, pendingDataV2[:n], symbolTable.Symbols(), nPendingSamples, nPendingExemplars, nPendingHistograms, nPendingMetadata, &pBufRaw, encBuf, compr) symbolTable.Reset() } } @@ -1576,7 +1576,7 @@ func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) { return } - sendBatch(batch, s.qm.protoMsg, s.qm.enc, false) + sendBatch(batch, s.qm.protoMsg, s.qm.compr, false) // TODO(bwplotka): Previously the return was between popular and send. // Consider this when DRY-ing https://github.com/prometheus/prometheus/issues/14409 queue.ReturnForReuse(batch) @@ -1587,7 +1587,7 @@ func (s *shards) runShard(ctx context.Context, shardID int, queue *queue) { case <-timer.C: batch := queue.Batch() if len(batch) > 0 { - sendBatch(batch, s.qm.protoMsg, s.qm.enc, true) + sendBatch(batch, s.qm.protoMsg, s.qm.compr, true) } queue.ReturnForReuse(batch) timer.Reset(time.Duration(s.qm.cfg.BatchSendDeadline)) @@ -1636,18 +1636,18 @@ func populateTimeSeries(batch []timeSeries, pendingData []prompb.TimeSeries, sen return nPendingSamples, nPendingExemplars, nPendingHistograms } -func (s *shards) sendSamples(ctx context.Context, samples []prompb.TimeSeries, sampleCount, exemplarCount, histogramCount int, pBuf *proto.Buffer, buf *[]byte, enc Compression) error { +func (s *shards) sendSamples(ctx context.Context, samples []prompb.TimeSeries, sampleCount, exemplarCount, histogramCount int, pBuf *proto.Buffer, buf compression.EncodeBuffer, compr compression.Type) error { begin := time.Now() - rs, err := s.sendSamplesWithBackoff(ctx, samples, sampleCount, exemplarCount, histogramCount, 0, pBuf, buf, enc) + rs, err := s.sendSamplesWithBackoff(ctx, samples, sampleCount, exemplarCount, histogramCount, 0, pBuf, buf, compr) s.updateMetrics(ctx, err, sampleCount, exemplarCount, histogramCount, 0, rs, time.Since(begin)) return err } // TODO(bwplotka): DRY this (have one logic for both v1 and v2). // See https://github.com/prometheus/prometheus/issues/14409 -func (s *shards) sendV2Samples(ctx context.Context, samples []writev2.TimeSeries, labels []string, sampleCount, exemplarCount, histogramCount, metadataCount int, pBuf, buf *[]byte, enc Compression) error { +func (s *shards) sendV2Samples(ctx context.Context, samples []writev2.TimeSeries, labels []string, sampleCount, exemplarCount, histogramCount, metadataCount int, pBuf *[]byte, buf compression.EncodeBuffer, compr compression.Type) error { begin := time.Now() - rs, err := s.sendV2SamplesWithBackoff(ctx, samples, labels, sampleCount, exemplarCount, histogramCount, metadataCount, pBuf, buf, enc) + rs, err := s.sendV2SamplesWithBackoff(ctx, samples, labels, sampleCount, exemplarCount, histogramCount, metadataCount, pBuf, buf, compr) s.updateMetrics(ctx, err, sampleCount, exemplarCount, histogramCount, metadataCount, rs, time.Since(begin)) return err } @@ -1689,9 +1689,9 @@ func (s *shards) updateMetrics(_ context.Context, err error, sampleCount, exempl } // sendSamplesWithBackoff to the remote storage with backoff for recoverable errors. -func (s *shards) sendSamplesWithBackoff(ctx context.Context, samples []prompb.TimeSeries, sampleCount, exemplarCount, histogramCount, metadataCount int, pBuf *proto.Buffer, buf *[]byte, enc Compression) (WriteResponseStats, error) { +func (s *shards) sendSamplesWithBackoff(ctx context.Context, samples []prompb.TimeSeries, sampleCount, exemplarCount, histogramCount, metadataCount int, pBuf *proto.Buffer, buf compression.EncodeBuffer, compr compression.Type) (WriteResponseStats, error) { // Build the WriteRequest with no metadata. - req, highest, lowest, err := buildWriteRequest(s.qm.logger, samples, nil, pBuf, buf, nil, enc) + req, highest, lowest, err := buildWriteRequest(s.qm.logger, samples, nil, pBuf, nil, buf, compr) s.qm.buildRequestLimitTimestamp.Store(lowest) if err != nil { // Failing to build the write request is non-recoverable, since it will @@ -1700,7 +1700,6 @@ func (s *shards) sendSamplesWithBackoff(ctx context.Context, samples []prompb.Ti } reqSize := len(req) - *buf = req // Since we retry writes via attemptStore and sendWriteRequestWithBackoff we need // to track the total amount of accepted data across the various attempts. @@ -1720,20 +1719,20 @@ func (s *shards) sendSamplesWithBackoff(ctx context.Context, samples []prompb.Ti lowest := s.qm.buildRequestLimitTimestamp.Load() if isSampleOld(currentTime, time.Duration(s.qm.cfg.SampleAgeLimit), lowest) { // This will filter out old samples during retries. - req, _, lowest, err := buildWriteRequest( + req2, _, lowest, err := buildWriteRequest( s.qm.logger, samples, nil, pBuf, - buf, isTimeSeriesOldFilter(s.qm.metrics, currentTime, time.Duration(s.qm.cfg.SampleAgeLimit)), - enc, + buf, + compr, ) s.qm.buildRequestLimitTimestamp.Store(lowest) if err != nil { return err } - *buf = req + req = req2 } ctx, span := otel.Tracer("").Start(ctx, "Remote Send Batch") @@ -1761,7 +1760,7 @@ func (s *shards) sendSamplesWithBackoff(ctx context.Context, samples []prompb.Ti s.qm.metrics.metadataTotal.Add(float64(metadataCount)) // Technically for v1, we will likely have empty response stats, but for // newer Receivers this might be not, so used it in a best effort. - rs, err := s.qm.client().Store(ctx, *buf, try) + rs, err := s.qm.client().Store(ctx, req, try) s.qm.metrics.sentBatchDuration.Observe(time.Since(begin).Seconds()) // TODO(bwplotka): Revisit this once we have Receivers doing retriable partial error // so far we don't have those, so it's ok to potentially skew statistics. @@ -1803,9 +1802,9 @@ func (s *shards) sendSamplesWithBackoff(ctx context.Context, samples []prompb.Ti } // sendV2SamplesWithBackoff to the remote storage with backoff for recoverable errors. -func (s *shards) sendV2SamplesWithBackoff(ctx context.Context, samples []writev2.TimeSeries, labels []string, sampleCount, exemplarCount, histogramCount, metadataCount int, pBuf, buf *[]byte, enc Compression) (WriteResponseStats, error) { +func (s *shards) sendV2SamplesWithBackoff(ctx context.Context, samples []writev2.TimeSeries, labels []string, sampleCount, exemplarCount, histogramCount, metadataCount int, pBuf *[]byte, buf compression.EncodeBuffer, compr compression.Type) (WriteResponseStats, error) { // Build the WriteRequest with no metadata. - req, highest, lowest, err := buildV2WriteRequest(s.qm.logger, samples, labels, pBuf, buf, nil, enc) + req, highest, lowest, err := buildV2WriteRequest(s.qm.logger, samples, labels, pBuf, nil, buf, compr) s.qm.buildRequestLimitTimestamp.Store(lowest) if err != nil { // Failing to build the write request is non-recoverable, since it will @@ -1814,7 +1813,6 @@ func (s *shards) sendV2SamplesWithBackoff(ctx context.Context, samples []writev2 } reqSize := len(req) - *buf = req // Since we retry writes via attemptStore and sendWriteRequestWithBackoff we need // to track the total amount of accepted data across the various attempts. @@ -1834,20 +1832,20 @@ func (s *shards) sendV2SamplesWithBackoff(ctx context.Context, samples []writev2 lowest := s.qm.buildRequestLimitTimestamp.Load() if isSampleOld(currentTime, time.Duration(s.qm.cfg.SampleAgeLimit), lowest) { // This will filter out old samples during retries. - req, _, lowest, err := buildV2WriteRequest( + req2, _, lowest, err := buildV2WriteRequest( s.qm.logger, samples, labels, pBuf, - buf, isV2TimeSeriesOldFilter(s.qm.metrics, currentTime, time.Duration(s.qm.cfg.SampleAgeLimit)), - enc, + buf, + compr, ) s.qm.buildRequestLimitTimestamp.Store(lowest) if err != nil { return err } - *buf = req + req = req2 } ctx, span := otel.Tracer("").Start(ctx, "Remote Send Batch") @@ -1873,7 +1871,7 @@ func (s *shards) sendV2SamplesWithBackoff(ctx context.Context, samples []writev2 s.qm.metrics.exemplarsTotal.Add(float64(exemplarCount)) s.qm.metrics.histogramsTotal.Add(float64(histogramCount)) s.qm.metrics.metadataTotal.Add(float64(metadataCount)) - rs, err := s.qm.client().Store(ctx, *buf, try) + rs, err := s.qm.client().Store(ctx, req, try) s.qm.metrics.sentBatchDuration.Observe(time.Since(begin).Seconds()) // TODO(bwplotka): Revisit this once we have Receivers doing retriable partial error // so far we don't have those, so it's ok to potentially skew statistics. @@ -2114,21 +2112,7 @@ func buildTimeSeries(timeSeries []prompb.TimeSeries, filter func(prompb.TimeSeri return highest, lowest, timeSeries, droppedSamples, droppedExemplars, droppedHistograms } -func compressPayload(tmpbuf *[]byte, inp []byte, enc Compression) (compressed []byte, _ error) { - switch enc { - case SnappyBlockCompression: - compressed = snappy.Encode(*tmpbuf, inp) - if n := snappy.MaxEncodedLen(len(inp)); n > len(*tmpbuf) { - // grow the buffer for the next time - *tmpbuf = make([]byte, n) - } - return compressed, nil - default: - return compressed, fmt.Errorf("unknown compression scheme [%v]", enc) - } -} - -func buildWriteRequest(logger *slog.Logger, timeSeries []prompb.TimeSeries, metadata []prompb.MetricMetadata, pBuf *proto.Buffer, buf *[]byte, filter func(prompb.TimeSeries) bool, enc Compression) (compressed []byte, highest, lowest int64, _ error) { +func buildWriteRequest(logger *slog.Logger, timeSeries []prompb.TimeSeries, metadata []prompb.MetricMetadata, pBuf *proto.Buffer, filter func(prompb.TimeSeries) bool, buf compression.EncodeBuffer, compr compression.Type) (_ []byte, highest, lowest int64, _ error) { highest, lowest, timeSeries, droppedSamples, droppedExemplars, droppedHistograms := buildTimeSeries(timeSeries, filter) @@ -2146,27 +2130,18 @@ func buildWriteRequest(logger *slog.Logger, timeSeries []prompb.TimeSeries, meta } else { pBuf.Reset() } - err := pBuf.Marshal(req) - if err != nil { + if err := pBuf.Marshal(req); err != nil { return nil, highest, lowest, err } - // snappy uses len() to see if it needs to allocate a new slice. Make the - // buffer as long as possible. - if buf != nil { - *buf = (*buf)[0:cap(*buf)] - } else { - buf = &[]byte{} - } - - compressed, err = compressPayload(buf, pBuf.Bytes(), enc) + compressed, err := compression.Encode(compr, pBuf.Bytes(), buf) if err != nil { return nil, highest, lowest, err } return compressed, highest, lowest, nil } -func buildV2WriteRequest(logger *slog.Logger, samples []writev2.TimeSeries, labels []string, pBuf, buf *[]byte, filter func(writev2.TimeSeries) bool, enc Compression) (compressed []byte, highest, lowest int64, _ error) { +func buildV2WriteRequest(logger *slog.Logger, samples []writev2.TimeSeries, labels []string, pBuf *[]byte, filter func(writev2.TimeSeries) bool, buf compression.EncodeBuffer, compr compression.Type) (compressed []byte, highest, lowest int64, _ error) { highest, lowest, timeSeries, droppedSamples, droppedExemplars, droppedHistograms := buildV2TimeSeries(samples, filter) if droppedSamples > 0 || droppedExemplars > 0 || droppedHistograms > 0 { @@ -2188,15 +2163,7 @@ func buildV2WriteRequest(logger *slog.Logger, samples []writev2.TimeSeries, labe } *pBuf = data - // snappy uses len() to see if it needs to allocate a new slice. Make the - // buffer as long as possible. - if buf != nil { - *buf = (*buf)[0:cap(*buf)] - } else { - buf = &[]byte{} - } - - compressed, err = compressPayload(buf, data, enc) + compressed, err = compression.Encode(compr, *pBuf, buf) if err != nil { return nil, highest, lowest, err } diff --git a/storage/remote/queue_manager_test.go b/storage/remote/queue_manager_test.go index 27d5aa47b6..785700f091 100644 --- a/storage/remote/queue_manager_test.go +++ b/storage/remote/queue_manager_test.go @@ -30,7 +30,6 @@ import ( "time" "github.com/gogo/protobuf/proto" - "github.com/golang/snappy" "github.com/google/go-cmp/cmp" "github.com/prometheus/client_golang/prometheus" client_testutil "github.com/prometheus/client_golang/prometheus/testutil" @@ -39,6 +38,8 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/atomic" + "github.com/prometheus/prometheus/util/compression" + "github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/labels" @@ -761,7 +762,7 @@ func TestDisableReshardOnRetry(t *testing.T) { metrics = newQueueManagerMetrics(nil, "", "") client = &MockWriteClient{ - StoreFunc: func(ctx context.Context, b []byte, i int) (WriteResponseStats, error) { + StoreFunc: func(_ context.Context, _ []byte, _ int) (WriteResponseStats, error) { onStoreCalled() return WriteResponseStats{}, RecoverableError{ @@ -839,7 +840,7 @@ func createTimeseries(numSamples, numSeries int, extraLabels ...labels.Label) ([ return samples, series } -func createProtoTimeseriesWithOld(numSamples, baseTs int64, extraLabels ...labels.Label) []prompb.TimeSeries { +func createProtoTimeseriesWithOld(numSamples, baseTs int64, _ ...labels.Label) []prompb.TimeSeries { samples := make([]prompb.TimeSeries, numSamples) // use a fixed rand source so tests are consistent r := rand.New(rand.NewSource(99)) @@ -963,7 +964,6 @@ type TestWriteClient struct { receivedMetadata map[string][]prompb.MetricMetadata writesReceived int mtx sync.Mutex - buf []byte protoMsg config.RemoteWriteProtoMsg injectedErrs []error currErr int @@ -1119,13 +1119,8 @@ func (c *TestWriteClient) Store(_ context.Context, req []byte, _ int) (WriteResp if c.returnError != nil { return WriteResponseStats{}, c.returnError } - // nil buffers are ok for snappy, ignore cast error. - if c.buf != nil { - c.buf = c.buf[:cap(c.buf)] - } - reqBuf, err := snappy.Decode(c.buf, req) - c.buf = reqBuf + reqBuf, err := compression.Decode(compression.Snappy, req, nil) if err != nil { return WriteResponseStats{}, err } @@ -1858,7 +1853,7 @@ func createDummyTimeSeries(instances int) []timeSeries { func BenchmarkBuildWriteRequest(b *testing.B) { noopLogger := promslog.NewNopLogger() bench := func(b *testing.B, batch []timeSeries) { - buff := make([]byte, 0) + cEnc := compression.NewSyncEncodeBuffer() seriesBuff := make([]prompb.TimeSeries, len(batch)) for i := range seriesBuff { seriesBuff[i].Samples = []prompb.Sample{{}} @@ -1869,7 +1864,7 @@ func BenchmarkBuildWriteRequest(b *testing.B) { totalSize := 0 for i := 0; i < b.N; i++ { populateTimeSeries(batch, seriesBuff, true, true) - req, _, _, err := buildWriteRequest(noopLogger, seriesBuff, nil, pBuf, &buff, nil, "snappy") + req, _, _, err := buildWriteRequest(noopLogger, seriesBuff, nil, pBuf, nil, cEnc, compression.Snappy) if err != nil { b.Fatal(err) } @@ -1899,7 +1894,7 @@ func BenchmarkBuildV2WriteRequest(b *testing.B) { noopLogger := promslog.NewNopLogger() bench := func(b *testing.B, batch []timeSeries) { symbolTable := writev2.NewSymbolTable() - buff := make([]byte, 0) + cEnc := compression.NewSyncEncodeBuffer() seriesBuff := make([]writev2.TimeSeries, len(batch)) for i := range seriesBuff { seriesBuff[i].Samples = []writev2.Sample{{}} @@ -1910,7 +1905,7 @@ func BenchmarkBuildV2WriteRequest(b *testing.B) { totalSize := 0 for i := 0; i < b.N; i++ { populateV2TimeSeries(&symbolTable, batch, seriesBuff, true, true) - req, _, _, err := buildV2WriteRequest(noopLogger, seriesBuff, symbolTable.Symbols(), &pBuf, &buff, nil, "snappy") + req, _, _, err := buildV2WriteRequest(noopLogger, seriesBuff, symbolTable.Symbols(), &pBuf, nil, cEnc, "snappy") if err != nil { b.Fatal(err) } diff --git a/storage/remote/write_handler.go b/storage/remote/write_handler.go index b71450444b..7b1dc26b98 100644 --- a/storage/remote/write_handler.go +++ b/storage/remote/write_handler.go @@ -24,11 +24,12 @@ import ( "time" "github.com/gogo/protobuf/proto" - "github.com/golang/snappy" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/util/compression" + "github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/histogram" @@ -150,8 +151,8 @@ func (h *writeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Don't break yolo 1.0 clients if not needed. This is similar to what we did // before 2.0: https://github.com/prometheus/prometheus/blob/d78253319daa62c8f28ed47e40bafcad2dd8b586/storage/remote/write_handler.go#L62 // We could give http.StatusUnsupportedMediaType, but let's assume snappy by default. - } else if enc != string(SnappyBlockCompression) { - err := fmt.Errorf("%v encoding (compression) is not accepted by this server; only %v is acceptable", enc, SnappyBlockCompression) + } else if strings.ToLower(enc) != compression.Snappy { + err := fmt.Errorf("%v encoding (compression) is not accepted by this server; only %v is acceptable", enc, compression.Snappy) h.logger.Error("Error decoding remote write request", "err", err) http.Error(w, err.Error(), http.StatusUnsupportedMediaType) } @@ -164,7 +165,7 @@ func (h *writeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - decompressed, err := snappy.Decode(nil, body) + decompressed, err := compression.Decode(compression.Snappy, body, nil) if err != nil { // TODO(bwplotka): Add more context to responded error? h.logger.Error("Error decompressing remote write request", "err", err.Error()) @@ -250,7 +251,7 @@ func (h *writeHandler) write(ctx context.Context, req *prompb.WriteRequest) (err // TODO(bwplotka): Even as per 1.0 spec, this should be a 400 error, while other samples are // potentially written. Perhaps unify with fixed writeV2 implementation a bit. - if !ls.Has(labels.MetricName) || !ls.IsValid(model.NameValidationScheme) { + if !ls.Has(labels.MetricName) || !ls.IsValid(model.UTF8Validation) { h.logger.Warn("Invalid metric names or labels", "got", ls.String()) samplesWithInvalidLabels++ continue @@ -391,7 +392,7 @@ func (h *writeHandler) appendV2(app storage.Appender, req *writev2.Request, rs * // Validate series labels early. // NOTE(bwplotka): While spec allows UTF-8, Prometheus Receiver may impose // specific limits and follow https://prometheus.io/docs/specs/remote_write_spec_2_0/#invalid-samples case. - if !ls.Has(labels.MetricName) || !ls.IsValid(model.NameValidationScheme) { + if !ls.Has(labels.MetricName) || !ls.IsValid(model.UTF8Validation) { badRequestErrs = append(badRequestErrs, fmt.Errorf("invalid metric name or labels, got %v", ls.String())) samplesWithInvalidLabels += len(ts.Samples) + len(ts.Histograms) continue @@ -513,7 +514,7 @@ func (h *writeHandler) appendV2(app storage.Appender, req *writev2.Request, rs * } // handleHistogramZeroSample appends CT as a zero-value sample with CT value as the sample timestamp. -// It doens't return errors in case of out of order CT. +// It doesn't return errors in case of out of order CT. func (h *writeHandler) handleHistogramZeroSample(app storage.Appender, ref storage.SeriesRef, l labels.Labels, hist writev2.Histogram, ct int64) (storage.SeriesRef, error) { var err error if hist.IsFloatHistogram() { @@ -531,7 +532,7 @@ type OTLPOptions struct { // NewOTLPWriteHandler creates a http.Handler that accepts OTLP write requests and // writes them to the provided appendable. -func NewOTLPWriteHandler(logger *slog.Logger, reg prometheus.Registerer, appendable storage.Appendable, configFunc func() config.Config, enableCTZeroIngestion bool, validIntervalCTZeroIngestion time.Duration, opts OTLPOptions) http.Handler { +func NewOTLPWriteHandler(logger *slog.Logger, _ prometheus.Registerer, appendable storage.Appendable, configFunc func() config.Config, enableCTZeroIngestion bool, validIntervalCTZeroIngestion time.Duration, opts OTLPOptions) http.Handler { ex := &rwExporter{ writeHandler: &writeHandler{ logger: logger, @@ -550,7 +551,10 @@ func NewOTLPWriteHandler(logger *slog.Logger, reg prometheus.Registerer, appenda if opts.ConvertDelta { fac := deltatocumulative.NewFactory() - set := processor.Settings{TelemetrySettings: component.TelemetrySettings{MeterProvider: noop.NewMeterProvider()}} + set := processor.Settings{ + ID: component.NewID(fac.Type()), + TelemetrySettings: component.TelemetrySettings{MeterProvider: noop.NewMeterProvider()}, + } d2c, err := fac.CreateMetrics(context.Background(), set, fac.CreateDefaultConfig(), wh.cumul) if err != nil { // fac.CreateMetrics directly calls [deltatocumulativeprocessor.createMetricsProcessor], @@ -561,7 +565,7 @@ func NewOTLPWriteHandler(logger *slog.Logger, reg prometheus.Registerer, appenda // both cannot be the case, as we pass a valid *Config and valid TelemetrySettings. // as such, we assume this error to never occur. // if it is, our assumptions are broken in which case a panic seems acceptable. - panic(err) + panic(fmt.Errorf("failed to create metrics processor: %w", err)) } if err := d2c.Start(context.Background(), nil); err != nil { // deltatocumulative does not error on start. see above for panic reasoning diff --git a/storage/remote/write_handler_test.go b/storage/remote/write_handler_test.go index b37b3632b9..492a1c82a0 100644 --- a/storage/remote/write_handler_test.go +++ b/storage/remote/write_handler_test.go @@ -31,6 +31,8 @@ import ( "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" + "github.com/prometheus/prometheus/util/compression" + "github.com/prometheus/common/promslog" "github.com/prometheus/prometheus/config" @@ -60,7 +62,7 @@ func TestRemoteWriteHandlerHeadersHandling_V1Message(t *testing.T) { name: "correct PRW 1.0 headers", reqHeaders: map[string]string{ "Content-Type": remoteWriteContentTypeHeaders[config.RemoteWriteProtoMsgV1], - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, expectedCode: http.StatusNoContent, @@ -69,7 +71,7 @@ func TestRemoteWriteHandlerHeadersHandling_V1Message(t *testing.T) { name: "missing remote write version", reqHeaders: map[string]string{ "Content-Type": remoteWriteContentTypeHeaders[config.RemoteWriteProtoMsgV1], - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, }, expectedCode: http.StatusNoContent, }, @@ -81,7 +83,7 @@ func TestRemoteWriteHandlerHeadersHandling_V1Message(t *testing.T) { { name: "missing content-type", reqHeaders: map[string]string{ - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, expectedCode: http.StatusNoContent, @@ -98,7 +100,7 @@ func TestRemoteWriteHandlerHeadersHandling_V1Message(t *testing.T) { name: "wrong content-type", reqHeaders: map[string]string{ "Content-Type": "yolo", - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, expectedCode: http.StatusUnsupportedMediaType, @@ -107,7 +109,7 @@ func TestRemoteWriteHandlerHeadersHandling_V1Message(t *testing.T) { name: "wrong content-type2", reqHeaders: map[string]string{ "Content-Type": appProtoContentType + ";proto=yolo", - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, expectedCode: http.StatusUnsupportedMediaType, @@ -157,7 +159,7 @@ func TestRemoteWriteHandlerHeadersHandling_V2Message(t *testing.T) { name: "correct PRW 2.0 headers", reqHeaders: map[string]string{ "Content-Type": remoteWriteContentTypeHeaders[config.RemoteWriteProtoMsgV2], - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, expectedCode: http.StatusNoContent, @@ -166,7 +168,7 @@ func TestRemoteWriteHandlerHeadersHandling_V2Message(t *testing.T) { name: "missing remote write version", reqHeaders: map[string]string{ "Content-Type": remoteWriteContentTypeHeaders[config.RemoteWriteProtoMsgV2], - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, }, expectedCode: http.StatusNoContent, // We don't check for now. }, @@ -178,7 +180,7 @@ func TestRemoteWriteHandlerHeadersHandling_V2Message(t *testing.T) { { name: "missing content-type", reqHeaders: map[string]string{ - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, // This only gives 415, because we explicitly only support 2.0. If we supported both @@ -199,7 +201,7 @@ func TestRemoteWriteHandlerHeadersHandling_V2Message(t *testing.T) { name: "wrong content-type", reqHeaders: map[string]string{ "Content-Type": "yolo", - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, expectedCode: http.StatusUnsupportedMediaType, @@ -208,7 +210,7 @@ func TestRemoteWriteHandlerHeadersHandling_V2Message(t *testing.T) { name: "wrong content-type2", reqHeaders: map[string]string{ "Content-Type": appProtoContentType + ";proto=yolo", - "Content-Encoding": string(SnappyBlockCompression), + "Content-Encoding": compression.Snappy, RemoteWriteVersionHeader: RemoteWriteVersion20HeaderValue, }, expectedCode: http.StatusUnsupportedMediaType, @@ -445,7 +447,7 @@ func TestRemoteWriteHandler_V2Message(t *testing.T) { require.NoError(t, err) req.Header.Set("Content-Type", remoteWriteContentTypeHeaders[config.RemoteWriteProtoMsgV2]) - req.Header.Set("Content-Encoding", string(SnappyBlockCompression)) + req.Header.Set("Content-Encoding", compression.Snappy) req.Header.Set(RemoteWriteVersionHeader, RemoteWriteVersion20HeaderValue) appendable := &mockAppendable{ @@ -715,7 +717,7 @@ func TestCommitErr_V2Message(t *testing.T) { require.NoError(t, err) req.Header.Set("Content-Type", remoteWriteContentTypeHeaders[config.RemoteWriteProtoMsgV2]) - req.Header.Set("Content-Encoding", string(SnappyBlockCompression)) + req.Header.Set("Content-Encoding", compression.Snappy) req.Header.Set(RemoteWriteVersionHeader, RemoteWriteVersion20HeaderValue) appendable := &mockAppendable{commitErr: errors.New("commit error")} @@ -860,7 +862,7 @@ func (m *mockAppendable) Appender(_ context.Context) storage.Appender { return m } -func (m *mockAppendable) SetOptions(opts *storage.AppendOptions) { +func (m *mockAppendable) SetOptions(_ *storage.AppendOptions) { panic("unimplemented") } @@ -956,7 +958,7 @@ func (m *mockAppendable) AppendHistogram(_ storage.SeriesRef, l labels.Labels, t return 0, nil } -func (m *mockAppendable) AppendHistogramCTZeroSample(ref storage.SeriesRef, l labels.Labels, t, ct int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { +func (m *mockAppendable) AppendHistogramCTZeroSample(_ storage.SeriesRef, l labels.Labels, t, ct int64, h *histogram.Histogram, _ *histogram.FloatHistogram) (storage.SeriesRef, error) { if m.appendCTZeroSampleErr != nil { return 0, m.appendCTZeroSampleErr } @@ -1006,7 +1008,7 @@ func (m *mockAppendable) UpdateMetadata(_ storage.SeriesRef, l labels.Labels, mp return 0, nil } -func (m *mockAppendable) AppendCTZeroSample(ref storage.SeriesRef, l labels.Labels, t, ct int64) (storage.SeriesRef, error) { +func (m *mockAppendable) AppendCTZeroSample(_ storage.SeriesRef, l labels.Labels, t, ct int64) (storage.SeriesRef, error) { if m.appendCTZeroSampleErr != nil { return 0, m.appendCTZeroSampleErr } diff --git a/storage/series.go b/storage/series.go index 4a6aad77f7..1fd63b759d 100644 --- a/storage/series.go +++ b/storage/series.go @@ -67,7 +67,7 @@ func NewListChunkSeriesFromSamples(lset labels.Labels, samples ...[]chunks.Sampl if err != nil { return &ChunkSeriesEntry{ Lset: lset, - ChunkIteratorFn: func(it chunks.Iterator) chunks.Iterator { + ChunkIteratorFn: func(_ chunks.Iterator) chunks.Iterator { return errChunksIterator{err: err} }, } diff --git a/tsdb/agent/db.go b/tsdb/agent/db.go index 38e6927ffb..99126d16f1 100644 --- a/tsdb/agent/db.go +++ b/tsdb/agent/db.go @@ -41,6 +41,7 @@ import ( "github.com/prometheus/prometheus/tsdb/record" "github.com/prometheus/prometheus/tsdb/tsdbutil" "github.com/prometheus/prometheus/tsdb/wlog" + "github.com/prometheus/prometheus/util/compression" "github.com/prometheus/prometheus/util/zeropool" ) @@ -66,7 +67,7 @@ type Options struct { WALSegmentSize int // WALCompression configures the compression type to use on records in the WAL. - WALCompression wlog.CompressionType + WALCompression compression.Type // StripeSize is the size (power of 2) in entries of the series hash map. Reducing the size will save memory but impact performance. StripeSize int @@ -90,7 +91,7 @@ type Options struct { func DefaultOptions() *Options { return &Options{ WALSegmentSize: wlog.DefaultSegmentSize, - WALCompression: wlog.CompressionNone, + WALCompression: compression.None, StripeSize: tsdb.DefaultStripeSize, TruncateFrequency: DefaultTruncateFrequency, MinWALTime: DefaultMinWALTime, @@ -337,7 +338,7 @@ func validateOptions(opts *Options) *Options { } if opts.WALCompression == "" { - opts.WALCompression = wlog.CompressionNone + opts.WALCompression = compression.None } // Revert StripeSize to DefaultStripeSize if StripeSize is either 0 or not a power of 2. diff --git a/tsdb/block.go b/tsdb/block.go index 0d06971c1e..912f15fb7c 100644 --- a/tsdb/block.go +++ b/tsdb/block.go @@ -27,7 +27,7 @@ import ( "sync" "time" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/common/promslog" @@ -695,7 +695,7 @@ Outer: func (pb *Block) CleanTombstones(dest string, c Compactor) ([]ulid.ULID, bool, error) { numStones := 0 - if err := pb.tombstones.Iter(func(id storage.SeriesRef, ivs tombstones.Intervals) error { + if err := pb.tombstones.Iter(func(_ storage.SeriesRef, ivs tombstones.Intervals) error { numStones += len(ivs) return nil }); err != nil { diff --git a/tsdb/block_test.go b/tsdb/block_test.go index 00b75fbf09..56f07819f0 100644 --- a/tsdb/block_test.go +++ b/tsdb/block_test.go @@ -618,7 +618,7 @@ func testPostingsForLabelMatching(t *testing.T, offset storage.SeriesRef, setUp { name: "missing label", labelName: "missing", - match: func(val string) bool { + match: func(_ string) bool { return true }, exp: nil, diff --git a/tsdb/blockwriter.go b/tsdb/blockwriter.go index 63f82e28df..5eb8a649a9 100644 --- a/tsdb/blockwriter.go +++ b/tsdb/blockwriter.go @@ -21,7 +21,7 @@ import ( "math" "os" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/prometheus/model/timestamp" "github.com/prometheus/prometheus/storage" diff --git a/tsdb/chunkenc/histogram.go b/tsdb/chunkenc/histogram.go index d2eec6b75a..7f528df8d5 100644 --- a/tsdb/chunkenc/histogram.go +++ b/tsdb/chunkenc/histogram.go @@ -262,17 +262,23 @@ func (a *HistogramAppender) Append(int64, float64) { // The method returns an additional boolean set to true if it is not appendable // because of a counter reset. If the given sample is stale, it is always ok to // append. If counterReset is true, okToAppend is always false. +// +// The method returns an additional CounterResetHeader value that indicates the +// status of the counter reset detection. But it returns UnknownCounterReset +// when schema or zero threshold changed, because we don't do a full counter +// reset detection. func (a *HistogramAppender) appendable(h *histogram.Histogram) ( positiveInserts, negativeInserts []Insert, backwardPositiveInserts, backwardNegativeInserts []Insert, - okToAppend, counterReset bool, + okToAppend bool, counterResetHint CounterResetHeader, ) { + counterResetHint = NotCounterReset if a.NumSamples() > 0 && a.GetCounterResetHeader() == GaugeType { return } if h.CounterResetHint == histogram.CounterReset { // Always honor the explicit counter reset hint. - counterReset = true + counterResetHint = CounterReset return } if value.IsStaleNaN(h.Sum) { @@ -283,39 +289,45 @@ func (a *HistogramAppender) appendable(h *histogram.Histogram) ( if value.IsStaleNaN(a.sum) { // If the last sample was stale, then we can only accept stale // samples in this chunk. + counterResetHint = UnknownCounterReset return } if h.Count < a.cnt { // There has been a counter reset. - counterReset = true + counterResetHint = CounterReset return } if h.Schema != a.schema || h.ZeroThreshold != a.zThreshold { + // This case might or might not go along with a counter reset and + // we do not want to invest the work of a full counter reset detection + // as long as https://github.com/prometheus/prometheus/issues/15346 is still open. + // TODO: consider adding the counter reset detection here once #15346 is fixed. + counterResetHint = UnknownCounterReset return } if histogram.IsCustomBucketsSchema(h.Schema) && !histogram.FloatBucketsMatch(h.CustomValues, a.customValues) { - counterReset = true + counterResetHint = CounterReset return } if h.ZeroCount < a.zCnt { // There has been a counter reset since ZeroThreshold didn't change. - counterReset = true + counterResetHint = CounterReset return } var ok bool positiveInserts, backwardPositiveInserts, ok = expandIntSpansAndBuckets(a.pSpans, h.PositiveSpans, a.pBuckets, h.PositiveBuckets) if !ok { - counterReset = true + counterResetHint = CounterReset return } negativeInserts, backwardNegativeInserts, ok = expandIntSpansAndBuckets(a.nSpans, h.NegativeSpans, a.nBuckets, h.NegativeBuckets) if !ok { - counterReset = true + counterResetHint = CounterReset return } @@ -781,21 +793,17 @@ func (a *HistogramAppender) AppendHistogram(prev *HistogramAppender, t int64, h case prev != nil: // This is a new chunk, but continued from a previous one. We need to calculate the reset header unless already set. _, _, _, _, _, counterReset := prev.appendable(h) - if counterReset { - a.setCounterResetHeader(CounterReset) - } else { - a.setCounterResetHeader(NotCounterReset) - } + a.setCounterResetHeader(counterReset) } return nil, false, a, nil } // Adding counter-like histogram. if h.CounterResetHint != histogram.GaugeType { - pForwardInserts, nForwardInserts, pBackwardInserts, nBackwardInserts, okToAppend, counterReset := a.appendable(h) - if !okToAppend || counterReset { + pForwardInserts, nForwardInserts, pBackwardInserts, nBackwardInserts, okToAppend, counterResetHint := a.appendable(h) + if !okToAppend || counterResetHint != NotCounterReset { if appendOnly { - if counterReset { + if counterResetHint == CounterReset { return nil, false, a, errors.New("histogram counter reset") } return nil, false, a, errors.New("histogram schema change") @@ -806,9 +814,7 @@ func (a *HistogramAppender) AppendHistogram(prev *HistogramAppender, t int64, h panic(err) // This should never happen for an empty histogram chunk. } happ := app.(*HistogramAppender) - if counterReset { - happ.setCounterResetHeader(CounterReset) - } + happ.setCounterResetHeader(counterResetHint) happ.appendHistogram(t, h) return newChunk, false, app, nil } diff --git a/tsdb/chunkenc/histogram_test.go b/tsdb/chunkenc/histogram_test.go index 7e8807963b..fb36b232c4 100644 --- a/tsdb/chunkenc/histogram_test.go +++ b/tsdb/chunkenc/histogram_test.go @@ -268,7 +268,7 @@ func TestHistogramChunkBucketChanges(t *testing.T) { require.Empty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.True(t, ok) // Only new buckets came in. - require.False(t, cr) + require.Equal(t, NotCounterReset, cr) c, app = hApp.recode(posInterjections, negInterjections, h2.PositiveSpans, h2.NegativeSpans) chk, _, _, err = app.AppendHistogram(nil, ts2, h2, false) require.NoError(t, err) @@ -394,7 +394,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.Empty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.True(t, ok) // Only new buckets came in. - require.False(t, cr) + require.Equal(t, NotCounterReset, cr) assertRecodedHistogramChunkOnAppend(t, c, hApp, ts+1, h2, UnknownCounterReset) } @@ -417,7 +417,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.Empty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.False(t, ok) // Need to cut a new chunk. - require.True(t, cr) + require.Equal(t, CounterReset, cr) assertNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, CounterReset, histogram.UnknownCounterReset) } @@ -443,7 +443,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.NotEmpty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.True(t, ok) - require.False(t, cr) + require.Equal(t, NotCounterReset, cr) assertNoNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, UnknownCounterReset) @@ -474,7 +474,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.NotEmpty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.True(t, ok) - require.False(t, cr) + require.Equal(t, NotCounterReset, cr) assertRecodedHistogramChunkOnAppend(t, c, hApp, ts+1, h2, UnknownCounterReset) @@ -502,7 +502,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.Empty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.False(t, ok) // Need to cut a new chunk. - require.True(t, cr) + require.Equal(t, CounterReset, cr) assertNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, CounterReset, histogram.UnknownCounterReset) } @@ -528,7 +528,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.Empty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.False(t, ok) // Need to cut a new chunk. - require.True(t, cr) + require.Equal(t, CounterReset, cr) assertNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, CounterReset, histogram.UnknownCounterReset) } @@ -560,7 +560,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.Empty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.False(t, ok) // Need to cut a new chunk. - require.True(t, cr) + require.Equal(t, CounterReset, cr) assertNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, CounterReset, histogram.UnknownCounterReset) } @@ -667,7 +667,7 @@ func TestHistogramChunkAppendable(t *testing.T) { require.NotEmpty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.True(t, ok) - require.False(t, cr) + require.Equal(t, NotCounterReset, cr) assertNoNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, UnknownCounterReset) } @@ -735,10 +735,42 @@ func TestHistogramChunkAppendable(t *testing.T) { require.Empty(t, backwardPositiveInserts) require.Empty(t, backwardNegativeInserts) require.True(t, ok) // Only new buckets came in. - require.False(t, cr) + require.Equal(t, NotCounterReset, cr) assertRecodedHistogramChunkOnAppend(t, c, hApp, ts+1, h2, UnknownCounterReset) } + + { // New histogram with a different schema. + c, hApp, ts, h1 := setup(eh) + h2 := h1.Copy() + h2.Schema = 2 + + posInterjections, negInterjections, backwardPositiveInserts, backwardNegativeInserts, ok, cr := hApp.appendable(h2) + require.Empty(t, posInterjections) + require.Empty(t, negInterjections) + require.Empty(t, backwardPositiveInserts) + require.Empty(t, backwardNegativeInserts) + require.False(t, ok) // Need to cut a new chunk. + require.Equal(t, UnknownCounterReset, cr) + + assertNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, UnknownCounterReset, histogram.UnknownCounterReset) + } + + { // New histogram with a different schema. + c, hApp, ts, h1 := setup(eh) + h2 := h1.Copy() + h2.ZeroThreshold = 1e-120 + + posInterjections, negInterjections, backwardPositiveInserts, backwardNegativeInserts, ok, cr := hApp.appendable(h2) + require.Empty(t, posInterjections) + require.Empty(t, negInterjections) + require.Empty(t, backwardPositiveInserts) + require.Empty(t, backwardNegativeInserts) + require.False(t, ok) // Need to cut a new chunk. + require.Equal(t, UnknownCounterReset, cr) + + assertNewHistogramChunkOnAppend(t, c, hApp, ts+1, h2, UnknownCounterReset, histogram.UnknownCounterReset) + } } func assertNewHistogramChunkOnAppend(t *testing.T, oldChunk Chunk, hApp *HistogramAppender, ts int64, h *histogram.Histogram, expectHeader CounterResetHeader, expectHint histogram.CounterResetHint) { @@ -1007,7 +1039,7 @@ func TestHistogramChunkAppendableWithEmptySpan(t *testing.T) { require.Empty(t, bpI) require.Empty(t, bnI) require.True(t, okToAppend) - require.False(t, counterReset) + require.Equal(t, NotCounterReset, counterReset) }) } } diff --git a/tsdb/chunks/chunk_write_queue_test.go b/tsdb/chunks/chunk_write_queue_test.go index 1a5482aed5..72b305c2a5 100644 --- a/tsdb/chunks/chunk_write_queue_test.go +++ b/tsdb/chunks/chunk_write_queue_test.go @@ -63,7 +63,7 @@ func TestChunkWriteQueue_WritingThroughQueue(t *testing.T) { gotCutFile bool ) - blockingChunkWriter := func(seriesRef HeadSeriesRef, mint, maxt int64, chunk chunkenc.Chunk, ref ChunkDiskMapperRef, isOOO, cutFile bool) error { + blockingChunkWriter := func(seriesRef HeadSeriesRef, mint, maxt int64, chunk chunkenc.Chunk, ref ChunkDiskMapperRef, _, cutFile bool) error { gotSeriesRef = seriesRef gotMint = mint gotMaxt = maxt @@ -82,7 +82,7 @@ func TestChunkWriteQueue_WritingThroughQueue(t *testing.T) { ref := newChunkDiskMapperRef(321, 123) cutFile := true awaitCb := make(chan struct{}) - require.NoError(t, q.addJob(chunkWriteJob{seriesRef: seriesRef, mint: mint, maxt: maxt, chk: chunk, ref: ref, cutFile: cutFile, callback: func(err error) { + require.NoError(t, q.addJob(chunkWriteJob{seriesRef: seriesRef, mint: mint, maxt: maxt, chk: chunk, ref: ref, cutFile: cutFile, callback: func(_ error) { close(awaitCb) }})) <-awaitCb @@ -101,7 +101,7 @@ func TestChunkWriteQueue_WrappingAroundSizeLimit(t *testing.T) { unblockChunkWriterCh := make(chan struct{}, sizeLimit) // blockingChunkWriter blocks until the unblockChunkWriterCh channel returns a value. - blockingChunkWriter := func(seriesRef HeadSeriesRef, mint, maxt int64, chunk chunkenc.Chunk, ref ChunkDiskMapperRef, isOOO, cutFile bool) error { + blockingChunkWriter := func(_ HeadSeriesRef, _, _ int64, _ chunkenc.Chunk, _ ChunkDiskMapperRef, _, _ bool) error { <-unblockChunkWriterCh return nil } @@ -117,7 +117,7 @@ func TestChunkWriteQueue_WrappingAroundSizeLimit(t *testing.T) { callbackWg.Add(1) require.NoError(t, q.addJob(chunkWriteJob{ ref: chunkRef, - callback: func(err error) { + callback: func(_ error) { callbackWg.Done() }, })) @@ -211,7 +211,7 @@ func BenchmarkChunkWriteQueue_addJob(b *testing.B) { for _, concurrentWrites := range []int{1, 10, 100, 1000} { b.Run(fmt.Sprintf("%d concurrent writes", concurrentWrites), func(b *testing.B) { issueReadSignal := make(chan struct{}) - q := newChunkWriteQueue(nil, 1000, func(ref HeadSeriesRef, i, i2 int64, chunk chunkenc.Chunk, ref2 ChunkDiskMapperRef, ooo, b bool) error { + q := newChunkWriteQueue(nil, 1000, func(_ HeadSeriesRef, _, _ int64, _ chunkenc.Chunk, _ ChunkDiskMapperRef, _, _ bool) error { if withReads { select { case issueReadSignal <- struct{}{}: diff --git a/tsdb/chunks/head_chunks_test.go b/tsdb/chunks/head_chunks_test.go index b530350b70..8e8f68d7f5 100644 --- a/tsdb/chunks/head_chunks_test.go +++ b/tsdb/chunks/head_chunks_test.go @@ -155,7 +155,7 @@ func TestChunkDiskMapper_WriteChunk_Chunk_IterateChunks(t *testing.T) { hrw = createChunkDiskMapper(t, dir) idx := 0 - require.NoError(t, hrw.IterateAllChunks(func(seriesRef HeadSeriesRef, chunkRef ChunkDiskMapperRef, mint, maxt int64, numSamples uint16, encoding chunkenc.Encoding, isOOO bool) error { + require.NoError(t, hrw.IterateAllChunks(func(seriesRef HeadSeriesRef, chunkRef ChunkDiskMapperRef, mint, maxt int64, numSamples uint16, _ chunkenc.Encoding, isOOO bool) error { t.Helper() expData := expectedData[idx] @@ -193,7 +193,7 @@ func TestChunkDiskMapper_WriteUnsupportedChunk_Chunk_IterateChunks(t *testing.T) require.NoError(t, hrw.Close()) hrw = createChunkDiskMapper(t, dir) - require.NoError(t, hrw.IterateAllChunks(func(seriesRef HeadSeriesRef, chunkRef ChunkDiskMapperRef, mint, maxt int64, numSamples uint16, encoding chunkenc.Encoding, isOOO bool) error { + require.NoError(t, hrw.IterateAllChunks(func(seriesRef HeadSeriesRef, chunkRef ChunkDiskMapperRef, mint, maxt int64, _ uint16, encoding chunkenc.Encoding, _ bool) error { t.Helper() require.Equal(t, ucSeriesRef, seriesRef) @@ -623,7 +623,7 @@ func createChunk(t *testing.T, idx int, hrw *ChunkDiskMapper) (seriesRef HeadSer if rand.Intn(2) == 0 { isOOO = true } - chunkRef = hrw.WriteChunk(seriesRef, mint, maxt, chunk, isOOO, func(cbErr error) { + chunkRef = hrw.WriteChunk(seriesRef, mint, maxt, chunk, isOOO, func(_ error) { require.NoError(t, err) close(awaitCb) }) @@ -638,7 +638,7 @@ func writeUnsupportedChunk(t *testing.T, idx int, hrw *ChunkDiskMapper) (seriesR maxt = int64((idx + 1) * 1000) chunk = randomUnsupportedChunk(t) awaitCb := make(chan struct{}) - chunkRef = hrw.WriteChunk(seriesRef, mint, maxt, chunk, false, func(cbErr error) { + chunkRef = hrw.WriteChunk(seriesRef, mint, maxt, chunk, false, func(_ error) { require.NoError(t, err) close(awaitCb) }) diff --git a/tsdb/compact.go b/tsdb/compact.go index 651736ba00..949895dcd7 100644 --- a/tsdb/compact.go +++ b/tsdb/compact.go @@ -26,7 +26,7 @@ import ( "sync" "time" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/promslog" "go.uber.org/atomic" diff --git a/tsdb/compact_test.go b/tsdb/compact_test.go index 8f0c2c7baa..03737ea4bd 100644 --- a/tsdb/compact_test.go +++ b/tsdb/compact_test.go @@ -29,7 +29,7 @@ import ( "testing" "time" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" "github.com/prometheus/common/promslog" "github.com/stretchr/testify/require" @@ -44,7 +44,7 @@ import ( "github.com/prometheus/prometheus/tsdb/index" "github.com/prometheus/prometheus/tsdb/tombstones" "github.com/prometheus/prometheus/tsdb/tsdbutil" - "github.com/prometheus/prometheus/tsdb/wlog" + "github.com/prometheus/prometheus/util/compression" ) func TestSplitByRange(t *testing.T) { @@ -1764,7 +1764,7 @@ func checkBlocks(t *testing.T, blocks []*Block, dirs ...string) { func TestHeadCompactionWithHistograms(t *testing.T) { for _, floatTest := range []bool{true, false} { t.Run(fmt.Sprintf("float=%t", floatTest), func(t *testing.T) { - head, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + head, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) require.NoError(t, head.Init(0)) t.Cleanup(func() { require.NoError(t, head.Close()) @@ -1944,11 +1944,11 @@ func TestSparseHistogramSpaceSavings(t *testing.T) { c.numBuckets, ), func(t *testing.T) { - oldHead, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + oldHead, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) t.Cleanup(func() { require.NoError(t, oldHead.Close()) }) - sparseHead, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + sparseHead, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) t.Cleanup(func() { require.NoError(t, sparseHead.Close()) }) diff --git a/tsdb/db.go b/tsdb/db.go index d8844bbef7..bdbdabef64 100644 --- a/tsdb/db.go +++ b/tsdb/db.go @@ -30,7 +30,7 @@ import ( "sync" "time" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/promslog" "go.uber.org/atomic" @@ -48,6 +48,7 @@ import ( "github.com/prometheus/prometheus/tsdb/index" "github.com/prometheus/prometheus/tsdb/tsdbutil" "github.com/prometheus/prometheus/tsdb/wlog" + "github.com/prometheus/prometheus/util/compression" ) const ( @@ -82,7 +83,7 @@ func DefaultOptions() *Options { MaxBlockDuration: DefaultBlockDuration, NoLockfile: false, SamplesPerChunk: DefaultSamplesPerChunk, - WALCompression: wlog.CompressionNone, + WALCompression: compression.None, StripeSize: DefaultStripeSize, HeadChunksWriteBufferSize: chunks.DefaultWriteBufferSize, IsolationDisabled: defaultIsolationDisabled, @@ -138,7 +139,7 @@ type Options struct { NoLockfile bool // WALCompression configures the compression type to use on records in the WAL. - WALCompression wlog.CompressionType + WALCompression compression.Type // Maximum number of CPUs that can simultaneously processes WAL replay. // If it is <=0, then GOMAXPROCS is used. @@ -200,12 +201,6 @@ type Options struct { // EnableNativeHistograms enables the ingestion of native histograms. EnableNativeHistograms bool - // EnableOOONativeHistograms enables the ingestion of OOO native histograms. - // It will only take effect if EnableNativeHistograms is set to true and the - // OutOfOrderTimeWindow is > 0. This flag will be removed after testing of - // OOO Native Histogram ingestion is complete. - EnableOOONativeHistograms bool - // EnableBiggerOOOBlockForOldSamples enables building 24h blocks for the OOO samples // that belong to the previous day. This is in-line with Mimir maintaining 24h blocks // for the previous days. @@ -1042,7 +1037,6 @@ func open(dir string, l *slog.Logger, r prometheus.Registerer, opts *Options, rn headOpts.MaxExemplars.Store(opts.MaxExemplars) headOpts.EnableMemorySnapshotOnShutdown = opts.EnableMemorySnapshotOnShutdown headOpts.EnableNativeHistograms.Store(opts.EnableNativeHistograms) - headOpts.EnableOOONativeHistograms.Store(opts.EnableOOONativeHistograms) headOpts.OutOfOrderTimeWindow.Store(opts.OutOfOrderTimeWindow) headOpts.OutOfOrderCapMax.Store(opts.OutOfOrderCapMax) headOpts.EnableSharding = opts.EnableSharding @@ -1279,16 +1273,6 @@ func (db *DB) DisableNativeHistograms() { db.head.DisableNativeHistograms() } -// EnableOOONativeHistograms enables the ingestion of out-of-order native histograms. -func (db *DB) EnableOOONativeHistograms() { - db.head.EnableOOONativeHistograms() -} - -// DisableOOONativeHistograms disables the ingestion of out-of-order native histograms. -func (db *DB) DisableOOONativeHistograms() { - db.head.DisableOOONativeHistograms() -} - // dbAppender wraps the DB's head appender and triggers compactions on commit // if necessary. type dbAppender struct { diff --git a/tsdb/db_test.go b/tsdb/db_test.go index 3f3fd0ed91..8c80711123 100644 --- a/tsdb/db_test.go +++ b/tsdb/db_test.go @@ -37,7 +37,9 @@ import ( "testing" "time" - "github.com/oklog/ulid" + "github.com/gogo/protobuf/proto" + "github.com/golang/snappy" + "github.com/oklog/ulid/v2" "github.com/prometheus/client_golang/prometheus" prom_testutil "github.com/prometheus/client_golang/prometheus/testutil" "github.com/prometheus/common/promslog" @@ -45,17 +47,13 @@ import ( "go.uber.org/atomic" "go.uber.org/goleak" - "github.com/prometheus/prometheus/prompb" - "github.com/prometheus/prometheus/storage/remote" - - "github.com/gogo/protobuf/proto" - "github.com/golang/snappy" - "github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/metadata" + "github.com/prometheus/prometheus/prompb" "github.com/prometheus/prometheus/storage" + "github.com/prometheus/prometheus/storage/remote" "github.com/prometheus/prometheus/tsdb/chunkenc" "github.com/prometheus/prometheus/tsdb/chunks" "github.com/prometheus/prometheus/tsdb/fileutil" @@ -65,6 +63,7 @@ import ( "github.com/prometheus/prometheus/tsdb/tsdbutil" "github.com/prometheus/prometheus/tsdb/wlog" "github.com/prometheus/prometheus/util/annotations" + "github.com/prometheus/prometheus/util/compression" "github.com/prometheus/prometheus/util/testutil" ) @@ -1025,7 +1024,7 @@ func TestWALFlushedOnDBClose(t *testing.T) { func TestWALSegmentSizeOptions(t *testing.T) { tests := map[int]func(dbdir string, segmentSize int){ // Default Wal Size. - 0: func(dbDir string, segmentSize int) { + 0: func(dbDir string, _ int) { filesAndDir, err := os.ReadDir(filepath.Join(dbDir, "wal")) require.NoError(t, err) files := []os.FileInfo{} @@ -1064,7 +1063,7 @@ func TestWALSegmentSizeOptions(t *testing.T) { require.Greater(t, int64(segmentSize), lastFile.Size(), "last WAL file size is not smaller than the WALSegmentSize option, filename: %v", lastFile.Name()) }, // Wal disabled. - -1: func(dbDir string, segmentSize int) { + -1: func(dbDir string, _ int) { // Check that WAL dir is not there. _, err := os.Stat(filepath.Join(dbDir, "wal")) require.Error(t, err) @@ -1975,7 +1974,7 @@ func TestInitializeHeadTimestamp(t *testing.T) { dir := t.TempDir() require.NoError(t, os.MkdirAll(path.Join(dir, "wal"), 0o777)) - w, err := wlog.New(nil, nil, path.Join(dir, "wal"), wlog.CompressionNone) + w, err := wlog.New(nil, nil, path.Join(dir, "wal"), compression.None) require.NoError(t, err) var enc record.Encoder @@ -2019,7 +2018,7 @@ func TestInitializeHeadTimestamp(t *testing.T) { createBlock(t, dir, genSeries(1, 1, 1000, 6000)) require.NoError(t, os.MkdirAll(path.Join(dir, "wal"), 0o777)) - w, err := wlog.New(nil, nil, path.Join(dir, "wal"), wlog.CompressionNone) + w, err := wlog.New(nil, nil, path.Join(dir, "wal"), compression.None) require.NoError(t, err) var enc record.Encoder @@ -2420,7 +2419,7 @@ func TestDBReadOnly(t *testing.T) { } // Add head to test DBReadOnly WAL reading capabilities. - w, err := wlog.New(logger, nil, filepath.Join(dbDir, "wal"), wlog.CompressionSnappy) + w, err := wlog.New(logger, nil, filepath.Join(dbDir, "wal"), compression.Snappy) require.NoError(t, err) h := createHead(t, w, genSeries(1, 1, 16, 18), dbDir) require.NoError(t, h.Close()) @@ -3071,7 +3070,7 @@ func TestCompactHead(t *testing.T) { NoLockfile: true, MinBlockDuration: int64(time.Hour * 2 / time.Millisecond), MaxBlockDuration: int64(time.Hour * 2 / time.Millisecond), - WALCompression: wlog.CompressionSnappy, + WALCompression: compression.Snappy, HeadPostingsForMatchersCacheMetrics: NewPostingsForMatchersCacheMetrics(nil), BlockPostingsForMatchersCacheMetrics: NewPostingsForMatchersCacheMetrics(nil), } @@ -4449,7 +4448,6 @@ func testOOOWALWrite(t *testing.T, db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) @@ -4677,7 +4675,7 @@ func TestMetadataCheckpointingOnlyKeepsLatestEntry(t *testing.T) { ctx := context.Background() numSamples := 10000 - hb, w := newTestHead(t, int64(numSamples)*10, wlog.CompressionNone, false) + hb, w := newTestHead(t, int64(numSamples)*10, compression.None, false) // Add some series so we can append metadata to them. app := hb.Appender(ctx) @@ -4870,7 +4868,6 @@ func TestMultipleEncodingsCommitOrder(t *testing.T) { db := openTestDB(t, opts, nil) db.DisableCompactions() db.EnableNativeHistograms() - db.EnableOOONativeHistograms() defer func() { require.NoError(t, db.Close()) }() @@ -5031,7 +5028,6 @@ func testOOOCompaction(t *testing.T, scenario sampleTypeScenario, addExtraSample opts.OutOfOrderCapMax = 30 opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -5238,7 +5234,6 @@ func testOOOCompactionWithNormalCompaction(t *testing.T, scenario sampleTypeScen require.NoError(t, err) db.DisableCompactions() // We want to manually call it. db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) }) @@ -5345,13 +5340,11 @@ func testOOOCompactionWithDisabledWriteLog(t *testing.T, scenario sampleTypeScen opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.WALSegmentSize = -1 // disabled WAL and WBL opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) db.DisableCompactions() // We want to manually call it. db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) }) @@ -5458,7 +5451,6 @@ func testOOOQueryAfterRestartWithSnapshotAndRemovedWBL(t *testing.T, scenario sa opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.EnableMemorySnapshotOnShutdown = true opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -5564,7 +5556,7 @@ func TestQuerierOOOQuery(t *testing.T) { sampleFunc func(ts int64) chunks.Sample }{ "float": { - appendFunc: func(app storage.Appender, ts int64, counterReset bool) (storage.SeriesRef, error) { + appendFunc: func(app storage.Appender, ts int64, _ bool) (storage.SeriesRef, error) { return app.Append(0, labels.FromStrings("foo", "bar1"), ts, float64(ts)) }, sampleFunc: func(ts int64) chunks.Sample { @@ -5597,7 +5589,7 @@ func TestQuerierOOOQuery(t *testing.T) { }, "integer histogram counter resets": { // Adding counter reset to all histograms means each histogram will have its own chunk. - appendFunc: func(app storage.Appender, ts int64, counterReset bool) (storage.SeriesRef, error) { + appendFunc: func(app storage.Appender, ts int64, _ bool) (storage.SeriesRef, error) { h := tsdbutil.GenerateTestHistogram(ts) h.CounterResetHint = histogram.CounterReset // For this scenario, ignore the counterReset argument. return app.AppendHistogram(0, labels.FromStrings("foo", "bar1"), ts, h, nil) @@ -5625,7 +5617,7 @@ func testQuerierOOOQuery(t *testing.T, series1 := labels.FromStrings("foo", "bar1") type filterFunc func(t int64) bool - defaultFilterFunc := func(t int64) bool { return true } + defaultFilterFunc := func(_ int64) bool { return true } minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() } addSample := func(db *DB, fromMins, toMins, queryMinT, queryMaxT int64, expSamples []chunks.Sample, filter filterFunc, counterReset bool) ([]chunks.Sample, int) { @@ -5824,7 +5816,6 @@ func testQuerierOOOQuery(t *testing.T, db := openTestDB(t, opts, nil) db.DisableCompactions() db.EnableNativeHistograms() - db.EnableOOONativeHistograms() defer func() { require.NoError(t, db.Close()) }() @@ -5880,7 +5871,7 @@ func TestChunkQuerierOOOQuery(t *testing.T) { checkInUseBucket bool }{ "float": { - appendFunc: func(app storage.Appender, ts int64, counterReset bool) (storage.SeriesRef, error) { + appendFunc: func(app storage.Appender, ts int64, _ bool) (storage.SeriesRef, error) { return app.Append(0, labels.FromStrings("foo", "bar1"), ts, float64(ts)) }, sampleFunc: func(ts int64) chunks.Sample { @@ -5913,7 +5904,7 @@ func TestChunkQuerierOOOQuery(t *testing.T) { }, "integer histogram counter resets": { // Adding counter reset to all histograms means each histogram will have its own chunk. - appendFunc: func(app storage.Appender, ts int64, counterReset bool) (storage.SeriesRef, error) { + appendFunc: func(app storage.Appender, ts int64, _ bool) (storage.SeriesRef, error) { h := tsdbutil.GenerateTestHistogram(ts) h.CounterResetHint = histogram.CounterReset // For this scenario, ignore the counterReset argument. return app.AppendHistogram(0, labels.FromStrings("foo", "bar1"), ts, h, nil) @@ -5924,7 +5915,7 @@ func TestChunkQuerierOOOQuery(t *testing.T) { }, "integer histogram with recode": { // Histograms have increasing number of buckets so their chunks are recoded. - appendFunc: func(app storage.Appender, ts int64, counterReset bool) (storage.SeriesRef, error) { + appendFunc: func(app storage.Appender, ts int64, _ bool) (storage.SeriesRef, error) { n := ts / time.Minute.Milliseconds() return app.AppendHistogram(0, labels.FromStrings("foo", "bar1"), ts, nBucketHistogram(n), nil) }, @@ -5956,7 +5947,7 @@ func testChunkQuerierOOOQuery(t *testing.T, series1 := labels.FromStrings("foo", "bar1") type filterFunc func(t int64) bool - defaultFilterFunc := func(t int64) bool { return true } + defaultFilterFunc := func(_ int64) bool { return true } minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() } addSample := func(db *DB, fromMins, toMins, queryMinT, queryMaxT int64, expSamples []chunks.Sample, filter filterFunc, counterReset bool) ([]chunks.Sample, int) { @@ -6155,7 +6146,6 @@ func testChunkQuerierOOOQuery(t *testing.T, db := openTestDB(t, opts, nil) db.DisableCompactions() db.EnableNativeHistograms() - db.EnableOOONativeHistograms() defer func() { require.NoError(t, db.Close()) }() @@ -6236,7 +6226,7 @@ func testOOONativeHistogramsWithCounterResets(t *testing.T, scenario sampleTypeS opts.OutOfOrderTimeWindow = 24 * time.Hour.Milliseconds() type resetFunc func(v int64) bool - defaultResetFunc := func(v int64) bool { return false } + defaultResetFunc := func(_ int64) bool { return false } lbls := labels.FromStrings("foo", "bar1") minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() } @@ -6336,7 +6326,6 @@ func testOOONativeHistogramsWithCounterResets(t *testing.T, scenario sampleTypeS t.Run(fmt.Sprintf("name=%s", tc.name), func(t *testing.T) { db := openTestDB(t, opts, nil) db.DisableCompactions() - db.EnableOOONativeHistograms() defer func() { require.NoError(t, db.Close()) }() @@ -6574,7 +6563,6 @@ func testOOOInterleavedImplicitCounterResets(t *testing.T, name string, scenario db := openTestDB(t, opts, nil) db.DisableCompactions() - db.EnableOOONativeHistograms() defer func() { require.NoError(t, db.Close()) }() @@ -6677,7 +6665,6 @@ func testOOOAppendAndQuery(t *testing.T, scenario sampleTypeScenario) { db := openTestDB(t, opts, nil) db.DisableCompactions() db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) }) @@ -6810,7 +6797,6 @@ func testOOODisabled(t *testing.T, scenario sampleTypeScenario) { db := openTestDB(t, opts, nil) db.DisableCompactions() db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) }) @@ -6884,7 +6870,6 @@ func testWBLAndMmapReplay(t *testing.T, scenario sampleTypeScenario) { opts.OutOfOrderCapMax = 30 opts.OutOfOrderTimeWindow = 4 * time.Hour.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db := openTestDB(t, opts, nil) db.DisableCompactions() @@ -7034,7 +7019,7 @@ func testWBLAndMmapReplay(t *testing.T, scenario sampleTypeScenario) { resetMmapToOriginal() // We neet to reset because new duplicate chunks can be written above. // Removing m-map markers in WBL by rewriting it. - newWbl, err := wlog.New(promslog.NewNopLogger(), nil, filepath.Join(t.TempDir(), "new_wbl"), wlog.CompressionNone) + newWbl, err := wlog.New(promslog.NewNopLogger(), nil, filepath.Join(t.TempDir(), "new_wbl"), compression.None) require.NoError(t, err) sr, err := wlog.NewSegmentsReader(originalWblDir) require.NoError(t, err) @@ -7078,7 +7063,6 @@ func TestOOOHistogramCompactionWithCounterResets(t *testing.T) { require.NoError(t, err) db.DisableCompactions() // We want to manually call it. db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) }) @@ -7440,7 +7424,6 @@ func TestInterleavedInOrderAndOOOHistogramCompactionWithCounterResets(t *testing require.NoError(t, err) db.DisableCompactions() // We want to manually call it. db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) }) @@ -7556,7 +7539,6 @@ func testOOOCompactionFailure(t *testing.T, scenario sampleTypeScenario) { require.NoError(t, err) db.DisableCompactions() // We want to manually call it. db.EnableNativeHistograms() - db.EnableOOONativeHistograms() t.Cleanup(func() { require.NoError(t, db.Close()) }) @@ -7845,7 +7827,6 @@ func testOOOMmapCorruption(t *testing.T, scenario sampleTypeScenario) { opts.OutOfOrderCapMax = 10 opts.OutOfOrderTimeWindow = 300 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -7980,7 +7961,6 @@ func testOutOfOrderRuntimeConfig(t *testing.T, scenario sampleTypeScenario) { opts := DefaultOptions() opts.OutOfOrderTimeWindow = oooTimeWindow opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -8275,7 +8255,6 @@ func testNoGapAfterRestartWithOOO(t *testing.T, scenario sampleTypeScenario) { opts := DefaultOptions() opts.OutOfOrderTimeWindow = 30 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -8335,7 +8314,6 @@ func testWblReplayAfterOOODisableAndRestart(t *testing.T, scenario sampleTypeSce opts := DefaultOptions() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -8404,7 +8382,6 @@ func testPanicOnApplyConfig(t *testing.T, scenario sampleTypeScenario) { opts := DefaultOptions() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -8463,7 +8440,6 @@ func testDiskFillingUpAfterDisablingOOO(t *testing.T, scenario sampleTypeScenari opts := DefaultOptions() opts.OutOfOrderTimeWindow = 60 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) @@ -9005,7 +8981,7 @@ func TestNativeHistogramFlag(t *testing.T) { }, act) } -func TestOOONativeHistogramFlag(t *testing.T) { +func TestOOONativeHistogramsSettings(t *testing.T) { h := &histogram.Histogram{ Count: 9, ZeroCount: 4, @@ -9021,7 +8997,7 @@ func TestOOONativeHistogramFlag(t *testing.T) { l := labels.FromStrings("foo", "bar") - t.Run("Test OOO native histograms if OOO is disabled", func(t *testing.T) { + t.Run("Test OOO native histograms if OOO is disabled and Native Histograms is enabled", func(t *testing.T) { opts := DefaultOptions() opts.OutOfOrderTimeWindow = 0 db := openTestDB(t, opts, []int64{100}) @@ -9029,9 +9005,7 @@ func TestOOONativeHistogramFlag(t *testing.T) { require.NoError(t, db.Close()) }() - // Enable Native Histograms and OOO Native Histogram ingestion db.EnableNativeHistograms() - db.EnableOOONativeHistograms() app := db.Appender(context.Background()) _, err := app.AppendHistogram(0, l, 100, h, nil) @@ -9049,7 +9023,7 @@ func TestOOONativeHistogramFlag(t *testing.T) { l.String(): {sample{t: 100, h: h}}, }, act) }) - t.Run("Test OOO Native Histograms if Native Histograms are disabled", func(t *testing.T) { + t.Run("Test OOO Native Histograms if OOO is enabled and Native Histograms are disabled", func(t *testing.T) { opts := DefaultOptions() opts.OutOfOrderTimeWindow = 100 db := openTestDB(t, opts, []int64{100}) @@ -9057,9 +9031,7 @@ func TestOOONativeHistogramFlag(t *testing.T) { require.NoError(t, db.Close()) }() - // Disable Native Histograms and enable OOO Native Histogram ingestion db.DisableNativeHistograms() - db.EnableOOONativeHistograms() // Attempt to add an in-order sample app := db.Appender(context.Background()) @@ -9077,7 +9049,7 @@ func TestOOONativeHistogramFlag(t *testing.T) { act := query(t, q, labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")) require.Equal(t, map[string][]chunks.Sample{}, act) }) - t.Run("Test OOO native histograms when flag is enabled", func(t *testing.T) { + t.Run("Test OOO native histograms when both OOO and Native Histograms are enabled", func(t *testing.T) { opts := DefaultOptions() opts.OutOfOrderTimeWindow = 100 db := openTestDB(t, opts, []int64{100}) @@ -9085,9 +9057,7 @@ func TestOOONativeHistogramFlag(t *testing.T) { require.NoError(t, db.Close()) }() - // Enable Native Histograms and OOO Native Histogram ingestion db.EnableNativeHistograms() - db.EnableOOONativeHistograms() // Add in-order samples app := db.Appender(context.Background()) @@ -9312,7 +9282,7 @@ func TestNewCompactorFunc(t *testing.T) { opts := DefaultOptions() block1 := ulid.MustNew(1, nil) block2 := ulid.MustNew(2, nil) - opts.NewCompactorFunc = func(ctx context.Context, r prometheus.Registerer, l *slog.Logger, ranges []int64, pool chunkenc.Pool, opts *Options) (Compactor, error) { + opts.NewCompactorFunc = func(_ context.Context, _ prometheus.Registerer, _ *slog.Logger, _ []int64, _ chunkenc.Pool, _ *Options) (Compactor, error) { return &mockCompactorFn{ planFn: func() ([]string, error) { return []string{block1.String(), block2.String()}, nil diff --git a/tsdb/errors/errors.go b/tsdb/errors/errors.go index ff230c44b1..a86ce59bd8 100644 --- a/tsdb/errors/errors.go +++ b/tsdb/errors/errors.go @@ -25,7 +25,7 @@ import ( type multiError []error // NewMulti returns multiError with provided errors added if not nil. -func NewMulti(errs ...error) multiError { //nolint:revive // unexported-return. +func NewMulti(errs ...error) multiError { //nolint:revive // unexported-return m := multiError{} m.Add(errs...) return m diff --git a/tsdb/fileutil/dir.go b/tsdb/fileutil/dir.go index e6ac4ec989..1672a92d4c 100644 --- a/tsdb/fileutil/dir.go +++ b/tsdb/fileutil/dir.go @@ -20,7 +20,7 @@ import ( func DirSize(dir string) (int64, error) { var size int64 - err := filepath.Walk(dir, func(filePath string, info os.FileInfo, err error) error { + err := filepath.Walk(dir, func(_ string, info os.FileInfo, err error) error { if err != nil { return err } diff --git a/tsdb/fileutil/fileutil.go b/tsdb/fileutil/fileutil.go index 5e479f48b9..523f99292c 100644 --- a/tsdb/fileutil/fileutil.go +++ b/tsdb/fileutil/fileutil.go @@ -76,7 +76,7 @@ func copyFile(src, dest string) error { func readDirs(src string) ([]string, error) { var files []string - err := filepath.Walk(src, func(path string, f os.FileInfo, err error) error { + err := filepath.Walk(src, func(path string, _ os.FileInfo, _ error) error { relativePath := strings.TrimPrefix(path, src) if len(relativePath) > 0 { files = append(files, relativePath) diff --git a/tsdb/head.go b/tsdb/head.go index 6b10dcf8e8..bb0d2611b8 100644 --- a/tsdb/head.go +++ b/tsdb/head.go @@ -26,7 +26,7 @@ import ( "sync" "time" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/promslog" "go.uber.org/atomic" @@ -162,11 +162,6 @@ type HeadOptions struct { // EnableNativeHistograms enables the ingestion of native histograms. EnableNativeHistograms atomic.Bool - // EnableOOONativeHistograms enables the ingestion of OOO native histograms. - // It will only take effect if EnableNativeHistograms is set to true and the - // OutOfOrderTimeWindow is > 0 - EnableOOONativeHistograms atomic.Bool - ChunkRange int64 // ChunkDirRoot is the parent directory of the chunks directory. ChunkDirRoot string @@ -1074,16 +1069,6 @@ func (h *Head) DisableNativeHistograms() { h.opts.EnableNativeHistograms.Store(false) } -// EnableOOONativeHistograms enables the ingestion of out-of-order native histograms. -func (h *Head) EnableOOONativeHistograms() { - h.opts.EnableOOONativeHistograms.Store(true) -} - -// DisableOOONativeHistograms disables the ingestion of out-of-order native histograms. -func (h *Head) DisableOOONativeHistograms() { - h.opts.EnableOOONativeHistograms.Store(false) -} - // PostingsCardinalityStats returns highest cardinality stats by label and value names. func (h *Head) PostingsCardinalityStats(statsByLabelName string, limit int) *index.PostingsStats { cacheKey := statsByLabelName + ";" + strconv.Itoa(limit) @@ -2356,6 +2341,10 @@ type memChunk struct { // len returns the length of memChunk list, including the element it was called on. func (mc *memChunk) len() (count int) { + if mc.prev == nil { + return 1 + } + elem := mc for elem != nil { count++ @@ -2367,6 +2356,9 @@ func (mc *memChunk) len() (count int) { // oldest returns the oldest element on the list. // For single element list this will be the same memChunk oldest() was called on. func (mc *memChunk) oldest() (elem *memChunk) { + if mc.prev == nil { + return mc + } elem = mc for elem.prev != nil { elem = elem.prev @@ -2379,6 +2371,9 @@ func (mc *memChunk) atOffset(offset int) (elem *memChunk) { if offset == 0 { return mc } + if offset == 1 { + return mc.prev + } if offset < 0 { return nil } @@ -2392,7 +2387,6 @@ func (mc *memChunk) atOffset(offset int) (elem *memChunk) { break } } - return elem } diff --git a/tsdb/head_append.go b/tsdb/head_append.go index eb6a2592bf..eb3fc6e2c3 100644 --- a/tsdb/head_append.go +++ b/tsdb/head_append.go @@ -527,7 +527,7 @@ func (s *memSeries) appendable(t int64, v float64, headMaxt, minValidTime, oooTi // appendableHistogram checks whether the given histogram sample is valid for appending to the series. (if we return false and no error) // The sample belongs to the out of order chunk if we return true and no error. // An error signifies the sample cannot be handled. -func (s *memSeries) appendableHistogram(t int64, h *histogram.Histogram, headMaxt, minValidTime, oooTimeWindow int64, oooHistogramsEnabled bool) (isOOO bool, oooDelta int64, err error) { +func (s *memSeries) appendableHistogram(t int64, h *histogram.Histogram, headMaxt, minValidTime, oooTimeWindow int64) (isOOO bool, oooDelta int64, err error) { // Check if we can append in the in-order chunk. if t >= minValidTime { if s.headChunks == nil { @@ -553,9 +553,6 @@ func (s *memSeries) appendableHistogram(t int64, h *histogram.Histogram, headMax // The sample cannot go in the in-order chunk. Check if it can go in the out-of-order chunk. if oooTimeWindow > 0 && t >= headMaxt-oooTimeWindow { - if !oooHistogramsEnabled { - return true, headMaxt - t, storage.ErrOOONativeHistogramsDisabled - } return true, headMaxt - t, nil } @@ -572,7 +569,7 @@ func (s *memSeries) appendableHistogram(t int64, h *histogram.Histogram, headMax // appendableFloatHistogram checks whether the given float histogram sample is valid for appending to the series. (if we return false and no error) // The sample belongs to the out of order chunk if we return true and no error. // An error signifies the sample cannot be handled. -func (s *memSeries) appendableFloatHistogram(t int64, fh *histogram.FloatHistogram, headMaxt, minValidTime, oooTimeWindow int64, oooHistogramsEnabled bool) (isOOO bool, oooDelta int64, err error) { +func (s *memSeries) appendableFloatHistogram(t int64, fh *histogram.FloatHistogram, headMaxt, minValidTime, oooTimeWindow int64) (isOOO bool, oooDelta int64, err error) { // Check if we can append in the in-order chunk. if t >= minValidTime { if s.headChunks == nil { @@ -598,9 +595,6 @@ func (s *memSeries) appendableFloatHistogram(t int64, fh *histogram.FloatHistogr // The sample cannot go in the in-order chunk. Check if it can go in the out-of-order chunk. if oooTimeWindow > 0 && t >= headMaxt-oooTimeWindow { - if !oooHistogramsEnabled { - return true, headMaxt - t, storage.ErrOOONativeHistogramsDisabled - } return true, headMaxt - t, nil } @@ -658,7 +652,7 @@ func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels // Fail fast if OOO is disabled and the sample is out of bounds. // Otherwise a full check will be done later to decide if the sample is in-order or out-of-order. - if (a.oooTimeWindow == 0 || !a.head.opts.EnableOOONativeHistograms.Load()) && t < a.minValidTime { + if a.oooTimeWindow == 0 && t < a.minValidTime { a.head.metrics.outOfBoundSamples.WithLabelValues(sampleMetricTypeHistogram).Inc() return 0, storage.ErrOutOfBounds } @@ -698,7 +692,7 @@ func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels // TODO(codesome): If we definitely know at this point that the sample is ooo, then optimise // to skip that sample from the WAL and write only in the WBL. - _, delta, err := s.appendableHistogram(t, h, a.headMaxt, a.minValidTime, a.oooTimeWindow, a.head.opts.EnableOOONativeHistograms.Load()) + _, delta, err := s.appendableHistogram(t, h, a.headMaxt, a.minValidTime, a.oooTimeWindow) if err != nil { s.pendingCommit = true } @@ -709,8 +703,6 @@ func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels if err != nil { switch { case errors.Is(err, storage.ErrOutOfOrderSample): - fallthrough - case errors.Is(err, storage.ErrOOONativeHistogramsDisabled): a.head.metrics.outOfOrderSamples.WithLabelValues(sampleMetricTypeHistogram).Inc() case errors.Is(err, storage.ErrTooOldSample): a.head.metrics.tooOldSamples.WithLabelValues(sampleMetricTypeHistogram).Inc() @@ -735,7 +727,7 @@ func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels // TODO(codesome): If we definitely know at this point that the sample is ooo, then optimise // to skip that sample from the WAL and write only in the WBL. - _, delta, err := s.appendableFloatHistogram(t, fh, a.headMaxt, a.minValidTime, a.oooTimeWindow, a.head.opts.EnableOOONativeHistograms.Load()) + _, delta, err := s.appendableFloatHistogram(t, fh, a.headMaxt, a.minValidTime, a.oooTimeWindow) if err == nil { s.pendingCommit = true } @@ -746,8 +738,6 @@ func (a *headAppender) AppendHistogram(ref storage.SeriesRef, lset labels.Labels if err != nil { switch { case errors.Is(err, storage.ErrOutOfOrderSample): - fallthrough - case errors.Is(err, storage.ErrOOONativeHistogramsDisabled): a.head.metrics.outOfOrderSamples.WithLabelValues(sampleMetricTypeHistogram).Inc() case errors.Is(err, storage.ErrTooOldSample): a.head.metrics.tooOldSamples.WithLabelValues(sampleMetricTypeHistogram).Inc() @@ -803,9 +793,9 @@ func (a *headAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, lset l s.lastHistogramValue = zeroHistogram } - // Although we call `appendableHistogram` with oooHistogramsEnabled=true, for CTZeroSamples OOO is not allowed. + // For CTZeroSamples OOO is not allowed. // We set it to true to make this implementation as close as possible to the float implementation. - isOOO, _, err := s.appendableHistogram(ct, zeroHistogram, a.headMaxt, a.minValidTime, a.oooTimeWindow, true) + isOOO, _, err := s.appendableHistogram(ct, zeroHistogram, a.headMaxt, a.minValidTime, a.oooTimeWindow) if err != nil { s.Unlock() if errors.Is(err, storage.ErrOutOfOrderSample) { @@ -837,9 +827,8 @@ func (a *headAppender) AppendHistogramCTZeroSample(ref storage.SeriesRef, lset l s.lastFloatHistogramValue = zeroFloatHistogram } - // Although we call `appendableFloatHistogram` with oooHistogramsEnabled=true, for CTZeroSamples OOO is not allowed. // We set it to true to make this implementation as close as possible to the float implementation. - isOOO, _, err := s.appendableFloatHistogram(ct, zeroFloatHistogram, a.headMaxt, a.minValidTime, a.oooTimeWindow, true) // OOO is not allowed for CTZeroSamples. + isOOO, _, err := s.appendableFloatHistogram(ct, zeroFloatHistogram, a.headMaxt, a.minValidTime, a.oooTimeWindow) // OOO is not allowed for CTZeroSamples. if err != nil { s.Unlock() if errors.Is(err, storage.ErrOutOfOrderSample) { @@ -1265,7 +1254,7 @@ func (a *headAppender) commitHistograms(acc *appenderCommitContext) { series = a.histogramSeries[i] series.Lock() - oooSample, _, err := series.appendableHistogram(s.T, s.H, a.headMaxt, a.minValidTime, a.oooTimeWindow, a.head.opts.EnableOOONativeHistograms.Load()) + oooSample, _, err := series.appendableHistogram(s.T, s.H, a.headMaxt, a.minValidTime, a.oooTimeWindow) if err != nil { handleAppendableError(err, &acc.histogramsAppended, &acc.histoOOORejected, &acc.histoOOBRejected, &acc.histoTooOldRejected) } @@ -1353,7 +1342,7 @@ func (a *headAppender) commitFloatHistograms(acc *appenderCommitContext) { series = a.floatHistogramSeries[i] series.Lock() - oooSample, _, err := series.appendableFloatHistogram(s.T, s.FH, a.headMaxt, a.minValidTime, a.oooTimeWindow, a.head.opts.EnableOOONativeHistograms.Load()) + oooSample, _, err := series.appendableFloatHistogram(s.T, s.FH, a.headMaxt, a.minValidTime, a.oooTimeWindow) if err != nil { handleAppendableError(err, &acc.histogramsAppended, &acc.histoOOORejected, &acc.histoOOBRejected, &acc.histoTooOldRejected) } diff --git a/tsdb/head_bench_test.go b/tsdb/head_bench_test.go index dc682602b1..0ffc75abaf 100644 --- a/tsdb/head_bench_test.go +++ b/tsdb/head_bench_test.go @@ -29,7 +29,7 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/tsdb/chunks" - "github.com/prometheus/prometheus/tsdb/wlog" + "github.com/prometheus/prometheus/util/compression" ) func BenchmarkHeadStripeSeriesCreate(b *testing.B) { @@ -132,7 +132,7 @@ func BenchmarkHead_WalCommit(b *testing.B) { for i := 0; i < b.N; i++ { b.StopTimer() - h, w := newTestHead(b, 10000, wlog.CompressionNone, false) + h, w := newTestHead(b, 10000, compression.None, false) b.Cleanup(func() { if h != nil { h.Close() diff --git a/tsdb/head_other.go b/tsdb/head_other.go index c73872c12e..45bb2285f0 100644 --- a/tsdb/head_other.go +++ b/tsdb/head_other.go @@ -27,6 +27,6 @@ func (s *memSeries) labels() labels.Labels { } // RebuildSymbolTable is a no-op when not using dedupelabels. -func (h *Head) RebuildSymbolTable(logger *slog.Logger) *labels.SymbolTable { +func (h *Head) RebuildSymbolTable(_ *slog.Logger) *labels.SymbolTable { return nil } diff --git a/tsdb/head_read.go b/tsdb/head_read.go index 5a49138648..d7cedeaf9b 100644 --- a/tsdb/head_read.go +++ b/tsdb/head_read.go @@ -504,7 +504,7 @@ func (s *memSeries) chunk(id chunks.HeadChunkID, chunkDiskMapper *chunks.ChunkDi // oooChunk returns the chunk for the HeadChunkID by m-mapping it from the disk. // It never returns the head OOO chunk. -func (s *memSeries) oooChunk(id chunks.HeadChunkID, chunkDiskMapper *chunks.ChunkDiskMapper, memChunkPool *sync.Pool) (chunk chunkenc.Chunk, maxTime int64, err error) { +func (s *memSeries) oooChunk(id chunks.HeadChunkID, chunkDiskMapper *chunks.ChunkDiskMapper, _ *sync.Pool) (chunk chunkenc.Chunk, maxTime int64, err error) { // ix represents the index of chunk in the s.ooo.oooMmappedChunks slice. The chunk id's are // incremented by 1 when new chunk is created, hence (id - firstOOOChunkID) gives the slice index. ix := int(id) - int(s.ooo.firstOOOChunkID) diff --git a/tsdb/head_test.go b/tsdb/head_test.go index bca7223ac0..866b2b9381 100644 --- a/tsdb/head_test.go +++ b/tsdb/head_test.go @@ -38,6 +38,8 @@ import ( "go.uber.org/atomic" "golang.org/x/sync/errgroup" + "github.com/prometheus/prometheus/util/compression" + "github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/model/exemplar" "github.com/prometheus/prometheus/model/histogram" @@ -68,11 +70,11 @@ func newTestHeadDefaultOptions(chunkRange int64, oooEnabled bool) *HeadOptions { return opts } -func newTestHead(t testing.TB, chunkRange int64, compressWAL wlog.CompressionType, oooEnabled bool) (*Head, *wlog.WL) { +func newTestHead(t testing.TB, chunkRange int64, compressWAL compression.Type, oooEnabled bool) (*Head, *wlog.WL) { return newTestHeadWithOptions(t, compressWAL, newTestHeadDefaultOptions(chunkRange, oooEnabled)) } -func newTestHeadWithOptions(t testing.TB, compressWAL wlog.CompressionType, opts *HeadOptions) (*Head, *wlog.WL) { +func newTestHeadWithOptions(t testing.TB, compressWAL compression.Type, opts *HeadOptions) (*Head, *wlog.WL) { dir := t.TempDir() wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compressWAL) require.NoError(t, err) @@ -92,7 +94,7 @@ func newTestHeadWithOptions(t testing.TB, compressWAL wlog.CompressionType, opts func BenchmarkCreateSeries(b *testing.B) { series := genSeries(b.N, 10, 0, 0) - h, _ := newTestHead(b, 10000, wlog.CompressionNone, false) + h, _ := newTestHead(b, 10000, compression.None, false) b.Cleanup(func() { require.NoError(b, h.Close()) }) @@ -113,7 +115,7 @@ func BenchmarkHeadAppender_Append_Commit_ExistingSeries(b *testing.B) { b.Run(fmt.Sprintf("%d series", seriesCount), func(b *testing.B) { for _, samplesPerAppend := range []int64{1, 2, 5, 100} { b.Run(fmt.Sprintf("%d samples per append", samplesPerAppend), func(b *testing.B) { - h, _ := newTestHead(b, 10000, wlog.CompressionNone, false) + h, _ := newTestHead(b, 10000, compression.None, false) b.Cleanup(func() { require.NoError(b, h.Close()) }) ts := int64(1000) @@ -298,11 +300,11 @@ func BenchmarkLoadWLs(b *testing.B) { func(b *testing.B) { dir := b.TempDir() - wal, err := wlog.New(nil, nil, dir, wlog.CompressionNone) + wal, err := wlog.New(nil, nil, dir, compression.None) require.NoError(b, err) var wbl *wlog.WL if c.oooSeriesPct != 0 { - wbl, err = wlog.New(nil, nil, dir, wlog.CompressionNone) + wbl, err = wlog.New(nil, nil, dir, compression.None) require.NoError(b, err) } @@ -478,11 +480,11 @@ func BenchmarkLoadRealWLs(b *testing.B) { dir := b.TempDir() require.NoError(b, fileutil.CopyDirs(srcDir, dir)) - wal, err := wlog.New(nil, nil, filepath.Join(dir, "wal"), wlog.CompressionNone) + wal, err := wlog.New(nil, nil, filepath.Join(dir, "wal"), compression.None) require.NoError(b, err) b.Cleanup(func() { wal.Close() }) - wbl, err := wlog.New(nil, nil, filepath.Join(dir, "wbl"), wlog.CompressionNone) + wbl, err := wlog.New(nil, nil, filepath.Join(dir, "wbl"), compression.None) require.NoError(b, err) b.Cleanup(func() { wbl.Close() }) b.StartTimer() @@ -503,7 +505,7 @@ func BenchmarkLoadRealWLs(b *testing.B) { // While appending the samples to the head it concurrently queries them from multiple go routines and verifies that the // returned results are correct. func TestHead_HighConcurrencyReadAndWrite(t *testing.T) { - head, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + head, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) defer func() { require.NoError(t, head.Close()) }() @@ -684,7 +686,7 @@ func TestHead_HighConcurrencyReadAndWrite(t *testing.T) { } func TestHead_ReadWAL(t *testing.T) { - for _, compress := range []wlog.CompressionType{wlog.CompressionNone, wlog.CompressionSnappy, wlog.CompressionZstd} { + for _, compress := range []compression.Type{compression.None, compression.Snappy, compression.Zstd} { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { entries := []interface{}{ []record.RefSeries{ @@ -811,7 +813,7 @@ func TestHead_ReadWAL(t *testing.T) { } func TestHead_WALMultiRef(t *testing.T) { - head, w := newTestHead(t, 1000, wlog.CompressionNone, false) + head, w := newTestHead(t, 1000, compression.None, false) require.NoError(t, head.Init(0)) @@ -846,7 +848,7 @@ func TestHead_WALMultiRef(t *testing.T) { require.NotEqual(t, ref1, ref2, "Refs are the same") require.NoError(t, head.Close()) - w, err = wlog.New(nil, nil, w.Dir(), wlog.CompressionNone) + w, err = wlog.New(nil, nil, w.Dir(), compression.None) require.NoError(t, err) opts := DefaultHeadOptions() @@ -913,7 +915,7 @@ func TestHead_KeepSeriesInWALCheckpoint(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) t.Cleanup(func() { require.NoError(t, h.Close()) }) @@ -929,7 +931,7 @@ func TestHead_KeepSeriesInWALCheckpoint(t *testing.T) { } func TestHead_ActiveAppenders(t *testing.T) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) defer head.Close() require.NoError(t, head.Init(0)) @@ -962,7 +964,7 @@ func TestHead_ActiveAppenders(t *testing.T) { } func TestHead_UnknownWALRecord(t *testing.T) { - head, w := newTestHead(t, 1000, wlog.CompressionNone, false) + head, w := newTestHead(t, 1000, compression.None, false) w.Log([]byte{255, 42}) require.NoError(t, head.Init(0)) require.NoError(t, head.Close()) @@ -974,7 +976,7 @@ func BenchmarkHead_Truncate(b *testing.B) { const total = 1e6 prepare := func(b *testing.B, churn int) *Head { - h, _ := newTestHead(b, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(b, 1000, compression.None, false) b.Cleanup(func() { require.NoError(b, h.Close()) }) @@ -1043,7 +1045,7 @@ func BenchmarkHead_Truncate(b *testing.B) { } func TestHead_Truncate(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -1353,7 +1355,7 @@ func TestMemSeries_truncateChunks_scenarios(t *testing.T) { } func TestHeadDeleteSeriesWithoutSamples(t *testing.T) { - for _, compress := range []wlog.CompressionType{wlog.CompressionNone, wlog.CompressionSnappy, wlog.CompressionZstd} { + for _, compress := range []compression.Type{compression.None, compression.Snappy, compression.Zstd} { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { entries := []interface{}{ []record.RefSeries{ @@ -1433,7 +1435,7 @@ func TestHeadDeleteSimple(t *testing.T) { }, } - for _, compress := range []wlog.CompressionType{wlog.CompressionNone, wlog.CompressionSnappy, wlog.CompressionZstd} { + for _, compress := range []compression.Type{compression.None, compression.Snappy, compression.Zstd} { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { for _, c := range cases { head, w := newTestHead(t, 1000, compress, false) @@ -1515,7 +1517,7 @@ func TestHeadDeleteSimple(t *testing.T) { } func TestDeleteUntilCurMax(t *testing.T) { - hb, _ := newTestHead(t, 1000000, wlog.CompressionNone, false) + hb, _ := newTestHead(t, 1000000, compression.None, false) defer func() { require.NoError(t, hb.Close()) }() @@ -1568,7 +1570,7 @@ func TestDeletedSamplesAndSeriesStillInWALAfterCheckpoint(t *testing.T) { numSamples := 10000 // Enough samples to cause a checkpoint. - hb, w := newTestHead(t, int64(numSamples)*10, wlog.CompressionNone, false) + hb, w := newTestHead(t, int64(numSamples)*10, compression.None, false) for i := 0; i < numSamples; i++ { app := hb.Appender(context.Background()) @@ -1660,7 +1662,7 @@ func TestDelete_e2e(t *testing.T) { seriesMap[labels.New(l...).String()] = []chunks.Sample{} } - hb, _ := newTestHead(t, 100000, wlog.CompressionNone, false) + hb, _ := newTestHead(t, 100000, compression.None, false) defer func() { require.NoError(t, hb.Close()) }() @@ -2028,7 +2030,7 @@ func TestMemSeries_append_atVariableRate(t *testing.T) { func TestGCChunkAccess(t *testing.T) { // Put a chunk, select it. GC it and then access it. const chunkRange = 1000 - h, _ := newTestHead(t, chunkRange, wlog.CompressionNone, false) + h, _ := newTestHead(t, chunkRange, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2087,7 +2089,7 @@ func TestGCChunkAccess(t *testing.T) { func TestGCSeriesAccess(t *testing.T) { // Put a series, select it. GC it and then access it. const chunkRange = 1000 - h, _ := newTestHead(t, chunkRange, wlog.CompressionNone, false) + h, _ := newTestHead(t, chunkRange, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2146,7 +2148,7 @@ func TestGCSeriesAccess(t *testing.T) { } func TestUncommittedSamplesNotLostOnTruncate(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2176,7 +2178,7 @@ func TestUncommittedSamplesNotLostOnTruncate(t *testing.T) { } func TestRemoveSeriesAfterRollbackAndTruncate(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2207,7 +2209,7 @@ func TestRemoveSeriesAfterRollbackAndTruncate(t *testing.T) { } func TestHead_LogRollback(t *testing.T) { - for _, compress := range []wlog.CompressionType{wlog.CompressionNone, wlog.CompressionSnappy, wlog.CompressionZstd} { + for _, compress := range []compression.Type{compression.None, compression.Snappy, compression.Zstd} { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { h, w := newTestHead(t, 1000, compress, false) defer func() { @@ -2231,7 +2233,7 @@ func TestHead_LogRollback(t *testing.T) { } func TestHead_ReturnsSortedLabelValues(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2295,7 +2297,7 @@ func TestWalRepair_DecodingError(t *testing.T) { 5, }, } { - for _, compress := range []wlog.CompressionType{wlog.CompressionNone, wlog.CompressionSnappy, wlog.CompressionZstd} { + for _, compress := range []compression.Type{compression.None, compression.Snappy, compression.Zstd} { t.Run(fmt.Sprintf("%s,compress=%s", name, compress), func(t *testing.T) { dir := t.TempDir() @@ -2369,9 +2371,9 @@ func TestWblRepair_DecodingError(t *testing.T) { // Fill the wbl and corrupt it. { - wal, err := wlog.New(nil, nil, filepath.Join(dir, "wal"), wlog.CompressionNone) + wal, err := wlog.New(nil, nil, filepath.Join(dir, "wal"), compression.None) require.NoError(t, err) - wbl, err := wlog.New(nil, nil, filepath.Join(dir, "wbl"), wlog.CompressionNone) + wbl, err := wlog.New(nil, nil, filepath.Join(dir, "wbl"), compression.None) require.NoError(t, err) for i := 1; i <= totalRecs; i++ { @@ -2435,7 +2437,7 @@ func TestHeadReadWriterRepair(t *testing.T) { walDir := filepath.Join(dir, "wal") // Fill the chunk segments and corrupt it. { - w, err := wlog.New(nil, nil, walDir, wlog.CompressionNone) + w, err := wlog.New(nil, nil, walDir, compression.None) require.NoError(t, err) opts := DefaultHeadOptions() @@ -2504,7 +2506,7 @@ func TestHeadReadWriterRepair(t *testing.T) { } func TestNewWalSegmentOnTruncate(t *testing.T) { - h, wal := newTestHead(t, 1000, wlog.CompressionNone, false) + h, wal := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2534,7 +2536,7 @@ func TestNewWalSegmentOnTruncate(t *testing.T) { } func TestAddDuplicateLabelName(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2613,11 +2615,11 @@ func TestMemSeriesIsolation(t *testing.T) { return i } - testIsolation := func(h *Head, i int) { + testIsolation := func(_ *Head, _ int) { } // Test isolation without restart of Head. - hb, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + hb, _ := newTestHead(t, 1000, compression.None, false) i := addSamples(hb) testIsolation(hb, i) @@ -2679,11 +2681,11 @@ func TestMemSeriesIsolation(t *testing.T) { require.NoError(t, hb.Close()) // Test isolation with restart of Head. This is to verify the num samples of chunks after m-map chunk replay. - hb, w := newTestHead(t, 1000, wlog.CompressionNone, false) + hb, w := newTestHead(t, 1000, compression.None, false) i = addSamples(hb) require.NoError(t, hb.Close()) - wal, err := wlog.NewSize(nil, nil, w.Dir(), 32768, wlog.CompressionNone) + wal, err := wlog.NewSize(nil, nil, w.Dir(), 32768, compression.None) require.NoError(t, err) opts := DefaultHeadOptions() opts.ChunkRange = 1000 @@ -2732,7 +2734,7 @@ func TestIsolationRollback(t *testing.T) { } // Rollback after a failed append and test if the low watermark has progressed anyway. - hb, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + hb, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, hb.Close()) }() @@ -2763,7 +2765,7 @@ func TestIsolationLowWatermarkMonotonous(t *testing.T) { t.Skip("skipping test since tsdb isolation is disabled") } - hb, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + hb, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, hb.Close()) }() @@ -2800,7 +2802,7 @@ func TestIsolationAppendIDZeroIsNoop(t *testing.T) { t.Skip("skipping test since tsdb isolation is disabled") } - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2831,7 +2833,7 @@ func TestIsolationWithoutAdd(t *testing.T) { t.Skip("skipping test since tsdb isolation is disabled") } - hb, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + hb, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, hb.Close()) }() @@ -2852,7 +2854,6 @@ func TestOutOfOrderSamplesMetric(t *testing.T) { t.Run(name, func(t *testing.T) { options := DefaultOptions() options.EnableNativeHistograms = true - options.EnableOOONativeHistograms = true testOutOfOrderSamplesMetric(t, scenario, options, storage.ErrOutOfOrderSample) }) } @@ -2865,10 +2866,9 @@ func TestOutOfOrderSamplesMetricNativeHistogramOOODisabled(t *testing.T) { } t.Run(name, func(t *testing.T) { options := DefaultOptions() - options.OutOfOrderTimeWindow = (1000 * time.Minute).Milliseconds() + options.OutOfOrderTimeWindow = 0 options.EnableNativeHistograms = true - options.EnableOOONativeHistograms = false - testOutOfOrderSamplesMetric(t, scenario, options, storage.ErrOOONativeHistogramsDisabled) + testOutOfOrderSamplesMetric(t, scenario, options, storage.ErrOutOfOrderSample) }) } } @@ -2956,7 +2956,7 @@ func testOutOfOrderSamplesMetric(t *testing.T, scenario sampleTypeScenario, opti } func testHeadSeriesChunkRace(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -2991,7 +2991,7 @@ func testHeadSeriesChunkRace(t *testing.T) { } func TestHeadLabelNamesValuesWithMinMaxRange(t *testing.T) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, head.Close()) }() @@ -3052,7 +3052,7 @@ func TestHeadLabelNamesValuesWithMinMaxRange(t *testing.T) { } func TestHeadLabelValuesWithMatchers(t *testing.T) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) ctx := context.Background() @@ -3128,7 +3128,7 @@ func TestHeadLabelValuesWithMatchers(t *testing.T) { } func TestHeadLabelNamesWithMatchers(t *testing.T) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, head.Close()) }() @@ -3198,7 +3198,7 @@ func TestHeadLabelNamesWithMatchers(t *testing.T) { func TestHeadShardedPostings(t *testing.T) { headOpts := newTestHeadDefaultOptions(1000, false) headOpts.EnableSharding = true - head, _ := newTestHeadWithOptions(t, wlog.CompressionNone, headOpts) + head, _ := newTestHeadWithOptions(t, compression.None, headOpts) defer func() { require.NoError(t, head.Close()) }() @@ -3301,7 +3301,7 @@ func TestHeadCompactable(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { headOpts.TimelyCompaction = tc.timelyCompaction - head, _ := newTestHeadWithOptions(t, wlog.CompressionNone, headOpts) + head, _ := newTestHeadWithOptions(t, compression.None, headOpts) defer func() { require.NoError(t, head.Close()) }() @@ -3316,7 +3316,7 @@ func TestHeadCompactable(t *testing.T) { } func TestErrReuseAppender(t *testing.T) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, head.Close()) }() @@ -3352,7 +3352,7 @@ func TestErrReuseAppender(t *testing.T) { func TestHeadMintAfterTruncation(t *testing.T) { chunkRange := int64(2000) - head, _ := newTestHead(t, chunkRange, wlog.CompressionNone, false) + head, _ := newTestHead(t, chunkRange, compression.None, false) app := head.Appender(context.Background()) _, err := app.Append(0, labels.FromStrings("a", "b"), 100, 100) @@ -3386,7 +3386,7 @@ func TestHeadMintAfterTruncation(t *testing.T) { func TestHeadExemplars(t *testing.T) { chunkRange := int64(2000) - head, _ := newTestHead(t, chunkRange, wlog.CompressionNone, false) + head, _ := newTestHead(t, chunkRange, compression.None, false) app := head.Appender(context.Background()) l := labels.FromStrings("trace_id", "123") @@ -3407,7 +3407,7 @@ func TestHeadExemplars(t *testing.T) { } func TestHeadMinMaxTimeNotSet(t *testing.T) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, head.Close()) }() @@ -3424,7 +3424,7 @@ func TestHeadMinMaxTimeNotSet(t *testing.T) { func BenchmarkHeadLabelValuesWithMatchers(b *testing.B) { chunkRange := int64(2000) - head, _ := newTestHead(b, chunkRange, wlog.CompressionNone, false) + head, _ := newTestHead(b, chunkRange, compression.None, false) b.Cleanup(func() { require.NoError(b, head.Close()) }) ctx := context.Background() @@ -3869,7 +3869,7 @@ func TestAppendHistogram(t *testing.T) { l := labels.FromStrings("a", "b") for _, numHistograms := range []int{1, 10, 150, 200, 250, 300} { t.Run(strconv.Itoa(numHistograms), func(t *testing.T) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) @@ -3973,7 +3973,7 @@ func TestAppendHistogram(t *testing.T) { } func TestHistogramInWALAndMmapChunk(t *testing.T) { - head, _ := newTestHead(t, 3000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 3000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) @@ -4124,7 +4124,7 @@ func TestHistogramInWALAndMmapChunk(t *testing.T) { // Restart head. require.NoError(t, head.Close()) startHead := func() { - w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) require.NoError(t, err) head, err = NewHead(nil, nil, w, nil, head.opts, nil) require.NoError(t, err) @@ -4153,7 +4153,7 @@ func TestHistogramInWALAndMmapChunk(t *testing.T) { } func TestChunkSnapshot(t *testing.T) { - head, _ := newTestHead(t, 120*4, wlog.CompressionNone, false) + head, _ := newTestHead(t, 120*4, compression.None, false) defer func() { head.opts.EnableMemorySnapshotOnShutdown = false require.NoError(t, head.Close()) @@ -4246,7 +4246,7 @@ func TestChunkSnapshot(t *testing.T) { } openHeadAndCheckReplay := func() { - w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) require.NoError(t, err) head, err = NewHead(nil, nil, w, nil, head.opts, nil) require.NoError(t, err) @@ -4440,7 +4440,7 @@ func TestChunkSnapshot(t *testing.T) { } func TestSnapshotError(t *testing.T) { - head, _ := newTestHead(t, 120*4, wlog.CompressionNone, false) + head, _ := newTestHead(t, 120*4, compression.None, false) defer func() { head.opts.EnableMemorySnapshotOnShutdown = false require.NoError(t, head.Close()) @@ -4500,7 +4500,7 @@ func TestSnapshotError(t *testing.T) { require.NoError(t, f.Close()) // Create new Head which should replay this snapshot. - w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) require.NoError(t, err) // Testing https://github.com/prometheus/prometheus/issues/9437 with the registry. head, err = NewHead(prometheus.NewRegistry(), nil, w, nil, head.opts, nil) @@ -4529,7 +4529,7 @@ func TestSnapshotError(t *testing.T) { opts := head.opts opts.SeriesCallback = c - w, err = wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, err = wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) require.NoError(t, err) head, err = NewHead(prometheus.NewRegistry(), nil, w, nil, head.opts, nil) require.NoError(t, err) @@ -4551,7 +4551,7 @@ func TestSnapshotError(t *testing.T) { func TestHistogramMetrics(t *testing.T) { numHistograms := 10 - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) @@ -4581,7 +4581,7 @@ func TestHistogramMetrics(t *testing.T) { require.Equal(t, float64(expHSamples), prom_testutil.ToFloat64(head.metrics.samplesAppended.WithLabelValues(sampleMetricTypeHistogram))) require.NoError(t, head.Close()) - w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) require.NoError(t, err) head, err = NewHead(nil, nil, w, nil, head.opts, nil) require.NoError(t, err) @@ -4603,7 +4603,7 @@ func testHistogramStaleSampleHelper(t *testing.T, floatHistogram bool) { t.Helper() l := labels.FromStrings("a", "b") numHistograms := 20 - head, _ := newTestHead(t, 100000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 100000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) @@ -4755,7 +4755,7 @@ func TestHistogramCounterResetHeader(t *testing.T) { for _, floatHisto := range []bool{true} { // FIXME t.Run(fmt.Sprintf("floatHistogram=%t", floatHisto), func(t *testing.T) { l := labels.FromStrings("a", "b") - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) @@ -4876,9 +4876,8 @@ func TestOOOHistogramCounterResetHeaders(t *testing.T) { for _, floatHisto := range []bool{true, false} { t.Run(fmt.Sprintf("floatHistogram=%t", floatHisto), func(t *testing.T) { l := labels.FromStrings("a", "b") - head, _ := newTestHead(t, 1000, wlog.CompressionNone, true) + head, _ := newTestHead(t, 1000, compression.None, true) head.opts.OutOfOrderCapMax.Store(5) - head.opts.EnableOOONativeHistograms.Store(true) t.Cleanup(func() { require.NoError(t, head.Close()) @@ -5037,7 +5036,6 @@ func TestAppendingDifferentEncodingToSameSeries(t *testing.T) { dir := t.TempDir() opts := DefaultOptions() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true db, err := Open(dir, nil, nil, opts, nil) require.NoError(t, err) t.Cleanup(func() { @@ -5187,7 +5185,7 @@ func TestAppendingDifferentEncodingToSameSeries(t *testing.T) { // Tests https://github.com/prometheus/prometheus/issues/9725. func TestChunkSnapshotReplayBug(t *testing.T) { dir := t.TempDir() - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) // Write few series records and samples such that the series references are not in order in the WAL @@ -5254,7 +5252,7 @@ func TestChunkSnapshotReplayBug(t *testing.T) { func TestChunkSnapshotTakenAfterIncompleteSnapshot(t *testing.T) { dir := t.TempDir() - wlTemp, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wlTemp, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) // Write a snapshot with .tmp suffix. This used to fail taking any further snapshots or replay of snapshots. @@ -5299,9 +5297,9 @@ func TestWBLReplay(t *testing.T) { func testWBLReplay(t *testing.T, scenario sampleTypeScenario) { dir := t.TempDir() - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) - oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, wlog.CompressionSnappy) + oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, compression.Snappy) require.NoError(t, err) opts := DefaultHeadOptions() @@ -5309,7 +5307,6 @@ func testWBLReplay(t *testing.T, scenario sampleTypeScenario) { opts.ChunkDirRoot = dir opts.OutOfOrderTimeWindow.Store(30 * time.Minute.Milliseconds()) opts.EnableNativeHistograms.Store(true) - opts.EnableOOONativeHistograms.Store(true) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) require.NoError(t, err) @@ -5317,7 +5314,7 @@ func testWBLReplay(t *testing.T, scenario sampleTypeScenario) { var expOOOSamples []chunks.Sample l := labels.FromStrings("foo", "bar") - appendSample := func(mins int64, val float64, isOOO bool) { + appendSample := func(mins int64, _ float64, isOOO bool) { app := h.Appender(context.Background()) _, s, err := scenario.appendFunc(app, l, mins*time.Minute.Milliseconds(), mins) require.NoError(t, err) @@ -5347,9 +5344,9 @@ func testWBLReplay(t *testing.T, scenario sampleTypeScenario) { // Restart head. require.NoError(t, h.Close()) - wal, err = wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wal, err = wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) - oooWlog, err = wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, wlog.CompressionSnappy) + oooWlog, err = wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, compression.Snappy) require.NoError(t, err) h, err = NewHead(nil, nil, wal, oooWlog, opts, nil) require.NoError(t, err) @@ -5393,9 +5390,9 @@ func TestOOOMmapReplay(t *testing.T) { func testOOOMmapReplay(t *testing.T, scenario sampleTypeScenario) { dir := t.TempDir() - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) - oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, wlog.CompressionSnappy) + oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, compression.Snappy) require.NoError(t, err) opts := DefaultHeadOptions() @@ -5404,7 +5401,6 @@ func testOOOMmapReplay(t *testing.T, scenario sampleTypeScenario) { opts.OutOfOrderCapMax.Store(30) opts.OutOfOrderTimeWindow.Store(1000 * time.Minute.Milliseconds()) opts.EnableNativeHistograms.Store(true) - opts.EnableOOONativeHistograms.Store(true) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) require.NoError(t, err) @@ -5445,9 +5441,9 @@ func testOOOMmapReplay(t *testing.T, scenario sampleTypeScenario) { // Restart head. require.NoError(t, h.Close()) - wal, err = wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wal, err = wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) - oooWlog, err = wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, wlog.CompressionSnappy) + oooWlog, err = wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, compression.Snappy) require.NoError(t, err) h, err = NewHead(nil, nil, wal, oooWlog, opts, nil) require.NoError(t, err) @@ -5476,7 +5472,7 @@ func testOOOMmapReplay(t *testing.T, scenario sampleTypeScenario) { } func TestHeadInit_DiscardChunksWithUnsupportedEncoding(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + h, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -5520,7 +5516,7 @@ func TestHeadInit_DiscardChunksWithUnsupportedEncoding(t *testing.T) { require.NoError(t, h.Close()) - wal, err := wlog.NewSize(nil, nil, filepath.Join(h.opts.ChunkDirRoot, "wal"), 32768, wlog.CompressionNone) + wal, err := wlog.NewSize(nil, nil, filepath.Join(h.opts.ChunkDirRoot, "wal"), 32768, compression.None) require.NoError(t, err) h, err = NewHead(nil, nil, wal, nil, h.opts, nil) require.NoError(t, err) @@ -5555,7 +5551,7 @@ func (c *unsupportedChunk) Encoding() chunkenc.Encoding { // Tests https://github.com/prometheus/prometheus/issues/10277. func TestMmapPanicAfterMmapReplayCorruption(t *testing.T) { dir := t.TempDir() - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionNone) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.None) require.NoError(t, err) opts := DefaultHeadOptions() @@ -5588,7 +5584,7 @@ func TestMmapPanicAfterMmapReplayCorruption(t *testing.T) { addChunks() require.NoError(t, h.Close()) - wal, err = wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionNone) + wal, err = wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.None) require.NoError(t, err) mmapFilePath := filepath.Join(dir, "chunks_head", "000001") @@ -5614,7 +5610,7 @@ func TestReplayAfterMmapReplayError(t *testing.T) { var err error openHead := func() { - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionNone) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.None) require.NoError(t, err) opts := DefaultHeadOptions() @@ -5697,9 +5693,9 @@ func TestOOOAppendWithNoSeries(t *testing.T) { func testOOOAppendWithNoSeries(t *testing.T, appendFunc func(appender storage.Appender, lbls labels.Labels, ts, value int64) (storage.SeriesRef, sample, error)) { dir := t.TempDir() - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) - oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, wlog.CompressionSnappy) + oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, compression.Snappy) require.NoError(t, err) opts := DefaultHeadOptions() @@ -5707,7 +5703,6 @@ func testOOOAppendWithNoSeries(t *testing.T, appendFunc func(appender storage.Ap opts.OutOfOrderCapMax.Store(30) opts.OutOfOrderTimeWindow.Store(120 * time.Minute.Milliseconds()) opts.EnableNativeHistograms.Store(true) - opts.EnableOOONativeHistograms.Store(true) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) require.NoError(t, err) @@ -5790,16 +5785,15 @@ func TestHeadMinOOOTimeUpdate(t *testing.T) { func testHeadMinOOOTimeUpdate(t *testing.T, scenario sampleTypeScenario) { dir := t.TempDir() - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionSnappy) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.Snappy) require.NoError(t, err) - oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, wlog.CompressionSnappy) + oooWlog, err := wlog.NewSize(nil, nil, filepath.Join(dir, wlog.WblDirName), 32768, compression.Snappy) require.NoError(t, err) opts := DefaultHeadOptions() opts.ChunkDirRoot = dir opts.OutOfOrderTimeWindow.Store(10 * time.Minute.Milliseconds()) opts.EnableNativeHistograms.Store(true) - opts.EnableOOONativeHistograms.Store(true) h, err := NewHead(nil, nil, wal, oooWlog, opts, nil) require.NoError(t, err) @@ -5837,7 +5831,7 @@ func testHeadMinOOOTimeUpdate(t *testing.T, scenario sampleTypeScenario) { func TestGaugeHistogramWALAndChunkHeader(t *testing.T) { l := labels.FromStrings("a", "b") - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) @@ -5870,7 +5864,7 @@ func TestGaugeHistogramWALAndChunkHeader(t *testing.T) { expHeaders := []chunkenc.CounterResetHeader{ chunkenc.UnknownCounterReset, chunkenc.GaugeType, - chunkenc.UnknownCounterReset, + chunkenc.NotCounterReset, chunkenc.GaugeType, } for i, mmapChunk := range ms.mmappedChunks { @@ -5902,7 +5896,7 @@ func TestGaugeHistogramWALAndChunkHeader(t *testing.T) { require.NoError(t, head.Close()) require.NoError(t, os.RemoveAll(mmappedChunksDir(head.opts.ChunkDirRoot))) - w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) require.NoError(t, err) head, err = NewHead(nil, nil, w, nil, head.opts, nil) require.NoError(t, err) @@ -5913,7 +5907,7 @@ func TestGaugeHistogramWALAndChunkHeader(t *testing.T) { func TestGaugeFloatHistogramWALAndChunkHeader(t *testing.T) { l := labels.FromStrings("a", "b") - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) t.Cleanup(func() { require.NoError(t, head.Close()) }) @@ -5978,7 +5972,7 @@ func TestGaugeFloatHistogramWALAndChunkHeader(t *testing.T) { require.NoError(t, head.Close()) require.NoError(t, os.RemoveAll(mmappedChunksDir(head.opts.ChunkDirRoot))) - w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, err := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) require.NoError(t, err) head, err = NewHead(nil, nil, w, nil, head.opts, nil) require.NoError(t, err) @@ -5988,7 +5982,7 @@ func TestGaugeFloatHistogramWALAndChunkHeader(t *testing.T) { } func TestSnapshotAheadOfWALError(t *testing.T) { - head, _ := newTestHead(t, 120*4, wlog.CompressionNone, false) + head, _ := newTestHead(t, 120*4, compression.None, false) head.opts.EnableMemorySnapshotOnShutdown = true // Add a sample to fill WAL. app := head.Appender(context.Background()) @@ -6011,7 +6005,7 @@ func TestSnapshotAheadOfWALError(t *testing.T) { // to keep using the same snapshot directory instead of a random one. require.NoError(t, os.RemoveAll(head.wal.Dir())) head.opts.EnableMemorySnapshotOnShutdown = false - w, _ := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, _ := wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) head, err = NewHead(nil, nil, w, nil, head.opts, nil) require.NoError(t, err) // Add a sample to fill WAL. @@ -6030,7 +6024,7 @@ func TestSnapshotAheadOfWALError(t *testing.T) { // Create new Head which should detect the incorrect index and delete the snapshot. head.opts.EnableMemorySnapshotOnShutdown = true - w, _ = wlog.NewSize(nil, nil, head.wal.Dir(), 32768, wlog.CompressionNone) + w, _ = wlog.NewSize(nil, nil, head.wal.Dir(), 32768, compression.None) head, err = NewHead(nil, nil, w, nil, head.opts, nil) require.NoError(t, err) require.NoError(t, head.Init(math.MinInt64)) @@ -6049,7 +6043,7 @@ func BenchmarkCuttingHeadHistogramChunks(b *testing.B) { ) samples := histogram.GenerateBigTestHistograms(numSamples, numBuckets) - h, _ := newTestHead(b, DefaultBlockDuration, wlog.CompressionNone, false) + h, _ := newTestHead(b, DefaultBlockDuration, compression.None, false) defer func() { require.NoError(b, h.Close()) }() @@ -6080,7 +6074,7 @@ func TestCuttingNewHeadChunks(t *testing.T) { }{ "float samples": { numTotalSamples: 180, - floatValFunc: func(i int) float64 { + floatValFunc: func(_ int) float64 { return 1. }, expectedChks: []struct { @@ -6166,7 +6160,7 @@ func TestCuttingNewHeadChunks(t *testing.T) { } for testName, tc := range testCases { t.Run(testName, func(t *testing.T) { - h, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + h, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -6229,7 +6223,7 @@ func TestCuttingNewHeadChunks(t *testing.T) { func TestAppendQuietZeroDuplicates(t *testing.T) { ts := int64(1695209650) lbls := labels.FromStrings("foo", "bar") - h, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + h, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -6277,7 +6271,7 @@ func TestAppendQuietZeroDuplicates(t *testing.T) { func TestQuietZeroWALReplay(t *testing.T) { ts := int64(1695209650) lbls := labels.FromStrings("foo", "bar") - h, w := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, true) + h, w := newTestHead(t, DefaultBlockDuration, compression.None, true) a := h.Appender(context.Background()) _, err := a.Append(0, lbls, ts, 42.0) @@ -6303,7 +6297,7 @@ func TestQuietZeroWALReplay(t *testing.T) { require.NoError(t, h.Close()) // Next we replay the WAL by creating a new head and then verify that previous samples are there as we expect them. - w, err = wlog.New(nil, nil, w.Dir(), wlog.CompressionNone) + w, err = wlog.New(nil, nil, w.Dir(), compression.None) require.NoError(t, err) opts := DefaultHeadOptions() opts.ChunkRange = 1000 @@ -6346,7 +6340,7 @@ func TestHeadDetectsDuplicateSampleAtSizeLimit(t *testing.T) { numSamples := 1000 baseTS := int64(1695209650) - h, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + h, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -6413,7 +6407,7 @@ func TestWALSampleAndExemplarOrder(t *testing.T) { for testName, tc := range testcases { t.Run(testName, func(t *testing.T) { - h, w := newTestHead(t, 1000, wlog.CompressionNone, false) + h, w := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -6450,7 +6444,7 @@ func TestWALSampleAndExemplarOrder(t *testing.T) { // `signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0xbb03d1` // panic, that we have seen in the wild once. func TestHeadCompactionWhileAppendAndCommitExemplar(t *testing.T) { - h, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + h, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) app := h.Appender(context.Background()) lbls := labels.FromStrings("foo", "bar") ref, err := app.Append(0, lbls, 1, 1) @@ -6585,7 +6579,7 @@ func TestSecondaryHashFunction(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { dir := t.TempDir() - wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, wlog.CompressionNone) + wal, err := wlog.NewSize(nil, nil, filepath.Join(dir, "wal"), 32768, compression.None) require.NoError(t, err) opts := DefaultHeadOptions() @@ -6653,7 +6647,7 @@ func TestPostingsCardinalityStats(t *testing.T) { } func TestHeadAppender_AppendFloatWithSameTimestampAsPreviousHistogram(t *testing.T) { - head, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + head, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) t.Cleanup(func() { head.Close() }) ls := labels.FromStrings(labels.MetricName, "test") @@ -6869,7 +6863,7 @@ func TestHeadAppender_AppendCT(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - h, _ := newTestHead(t, DefaultBlockDuration, wlog.CompressionNone, false) + h, _ := newTestHead(t, DefaultBlockDuration, compression.None, false) defer func() { require.NoError(t, h.Close()) }() @@ -6907,7 +6901,7 @@ func TestHeadCompactableDoesNotCompactEmptyHead(t *testing.T) { // was compactable using default values for min and max times, `Head.compactable()` // would return true which is incorrect. This test verifies that we short-circuit // the check when the head has not yet had any samples added. - head, _ := newTestHead(t, 1, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1, compression.None, false) defer func() { require.NoError(t, head.Close()) }() @@ -6949,7 +6943,7 @@ func TestHeadAppendHistogramAndCommitConcurrency(t *testing.T) { } func testHeadAppendHistogramAndCommitConcurrency(t *testing.T, appendFn func(storage.Appender, int) error) { - head, _ := newTestHead(t, 1000, wlog.CompressionNone, false) + head, _ := newTestHead(t, 1000, compression.None, false) defer func() { require.NoError(t, head.Close()) }() diff --git a/tsdb/head_wal.go b/tsdb/head_wal.go index b85dc3ecf4..7635e30639 100644 --- a/tsdb/head_wal.go +++ b/tsdb/head_wal.go @@ -158,11 +158,10 @@ func (h *Head) loadWAL(r *wlog.Reader, syms *labels.SymbolTable, multiRef map[ch var err error dec := record.NewDecoder(syms) for r.Next() { - rec := r.Record() - switch dec.Type(rec) { + switch dec.Type(r.Record()) { case record.Series: series := h.wlReplaySeriesPool.Get()[:0] - series, err = dec.Series(rec, series) + series, err = dec.Series(r.Record(), series) if err != nil { decodeErr = &wlog.CorruptionErr{ Err: fmt.Errorf("decode series: %w", err), @@ -174,7 +173,7 @@ func (h *Head) loadWAL(r *wlog.Reader, syms *labels.SymbolTable, multiRef map[ch decoded <- series case record.Samples: samples := h.wlReplaySamplesPool.Get()[:0] - samples, err = dec.Samples(rec, samples) + samples, err = dec.Samples(r.Record(), samples) if err != nil { decodeErr = &wlog.CorruptionErr{ Err: fmt.Errorf("decode samples: %w", err), @@ -186,7 +185,7 @@ func (h *Head) loadWAL(r *wlog.Reader, syms *labels.SymbolTable, multiRef map[ch decoded <- samples case record.Tombstones: tstones := h.wlReplaytStonesPool.Get()[:0] - tstones, err = dec.Tombstones(rec, tstones) + tstones, err = dec.Tombstones(r.Record(), tstones) if err != nil { decodeErr = &wlog.CorruptionErr{ Err: fmt.Errorf("decode tombstones: %w", err), @@ -198,7 +197,7 @@ func (h *Head) loadWAL(r *wlog.Reader, syms *labels.SymbolTable, multiRef map[ch decoded <- tstones case record.Exemplars: exemplars := h.wlReplayExemplarsPool.Get()[:0] - exemplars, err = dec.Exemplars(rec, exemplars) + exemplars, err = dec.Exemplars(r.Record(), exemplars) if err != nil { decodeErr = &wlog.CorruptionErr{ Err: fmt.Errorf("decode exemplars: %w", err), @@ -210,7 +209,7 @@ func (h *Head) loadWAL(r *wlog.Reader, syms *labels.SymbolTable, multiRef map[ch decoded <- exemplars case record.HistogramSamples, record.CustomBucketsHistogramSamples: hists := h.wlReplayHistogramsPool.Get()[:0] - hists, err = dec.HistogramSamples(rec, hists) + hists, err = dec.HistogramSamples(r.Record(), hists) if err != nil { decodeErr = &wlog.CorruptionErr{ Err: fmt.Errorf("decode histograms: %w", err), @@ -222,7 +221,7 @@ func (h *Head) loadWAL(r *wlog.Reader, syms *labels.SymbolTable, multiRef map[ch decoded <- hists case record.FloatHistogramSamples, record.CustomBucketsFloatHistogramSamples: hists := h.wlReplayFloatHistogramsPool.Get()[:0] - hists, err = dec.FloatHistogramSamples(rec, hists) + hists, err = dec.FloatHistogramSamples(r.Record(), hists) if err != nil { decodeErr = &wlog.CorruptionErr{ Err: fmt.Errorf("decode float histograms: %w", err), @@ -234,7 +233,7 @@ func (h *Head) loadWAL(r *wlog.Reader, syms *labels.SymbolTable, multiRef map[ch decoded <- hists case record.Metadata: meta := h.wlReplayMetadataPool.Get()[:0] - meta, err := dec.Metadata(rec, meta) + meta, err := dec.Metadata(r.Record(), meta) if err != nil { decodeErr = &wlog.CorruptionErr{ Err: fmt.Errorf("decode metadata: %w", err), diff --git a/tsdb/index/index.go b/tsdb/index/index.go index 6a1064b356..4ffd7e448c 100644 --- a/tsdb/index/index.go +++ b/tsdb/index/index.go @@ -1510,7 +1510,7 @@ func (r *Reader) Close() error { return r.c.Close() } -func (r *Reader) lookupSymbol(ctx context.Context, o uint32) (string, error) { +func (r *Reader) lookupSymbol(_ context.Context, o uint32) (string, error) { if s, ok := r.nameSymbols[o]; ok { return s, nil } diff --git a/tsdb/isolation_test.go b/tsdb/isolation_test.go index 36083a1029..70404efbbf 100644 --- a/tsdb/isolation_test.go +++ b/tsdb/isolation_test.go @@ -72,7 +72,7 @@ func TestIsolation(t *testing.T) { func countOpenReads(iso *isolation) int { count := 0 - iso.TraverseOpenReads(func(s *isolationState) bool { + iso.TraverseOpenReads(func(_ *isolationState) bool { count++ return true }) diff --git a/tsdb/ooo_head.go b/tsdb/ooo_head.go index 0ed9f36484..a3d6b3567b 100644 --- a/tsdb/ooo_head.go +++ b/tsdb/ooo_head.go @@ -72,7 +72,7 @@ func (o *OOOChunk) NumSamples() int { // ToEncodedChunks returns chunks with the samples in the OOOChunk. // -//nolint:revive // unexported-return. +//nolint:revive func (o *OOOChunk) ToEncodedChunks(mint, maxt int64) (chks []memChunk, err error) { if len(o.samples) == 0 { return nil, nil diff --git a/tsdb/ooo_head_read.go b/tsdb/ooo_head_read.go index 745cd5d5fe..362ee5ebd2 100644 --- a/tsdb/ooo_head_read.go +++ b/tsdb/ooo_head_read.go @@ -20,7 +20,7 @@ import ( "math" "slices" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/storage" @@ -500,15 +500,15 @@ func (ir *OOOCompactionHeadIndexReader) Series(ref storage.SeriesRef, builder *l return getOOOSeriesChunks(s, ir.ch.mint, ir.ch.maxt, 0, ir.ch.lastMmapRef, false, 0, chks) } -func (ir *OOOCompactionHeadIndexReader) SortedLabelValues(_ context.Context, name string, matchers ...*labels.Matcher) ([]string, error) { +func (ir *OOOCompactionHeadIndexReader) SortedLabelValues(_ context.Context, _ string, _ ...*labels.Matcher) ([]string, error) { return nil, errors.New("not implemented") } -func (ir *OOOCompactionHeadIndexReader) LabelValues(_ context.Context, name string, matchers ...*labels.Matcher) ([]string, error) { +func (ir *OOOCompactionHeadIndexReader) LabelValues(_ context.Context, _ string, _ ...*labels.Matcher) ([]string, error) { return nil, errors.New("not implemented") } -func (ir *OOOCompactionHeadIndexReader) PostingsForMatchers(_ context.Context, concurrent bool, ms ...*labels.Matcher) (index.Postings, error) { +func (ir *OOOCompactionHeadIndexReader) PostingsForMatchers(_ context.Context, _ bool, _ ...*labels.Matcher) (index.Postings, error) { return nil, errors.New("not implemented") } @@ -520,7 +520,7 @@ func (ir *OOOCompactionHeadIndexReader) LabelValueFor(context.Context, storage.S return "", errors.New("not implemented") } -func (ir *OOOCompactionHeadIndexReader) LabelNamesFor(ctx context.Context, postings index.Postings) ([]string, error) { +func (ir *OOOCompactionHeadIndexReader) LabelNamesFor(_ context.Context, _ index.Postings) ([]string, error) { return nil, errors.New("not implemented") } diff --git a/tsdb/ooo_head_read_test.go b/tsdb/ooo_head_read_test.go index adbd3278ba..d2c490f221 100644 --- a/tsdb/ooo_head_read_test.go +++ b/tsdb/ooo_head_read_test.go @@ -28,7 +28,7 @@ import ( "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/tsdb/chunkenc" "github.com/prometheus/prometheus/tsdb/chunks" - "github.com/prometheus/prometheus/tsdb/wlog" + "github.com/prometheus/prometheus/util/compression" ) type chunkInterval struct { @@ -300,7 +300,7 @@ func TestOOOHeadIndexReader_Series(t *testing.T) { for perm, intervals := range permutations { for _, headChunk := range []bool{false, true} { t.Run(fmt.Sprintf("name=%s, permutation=%d, headChunk=%t", tc.name, perm, headChunk), func(t *testing.T) { - h, _ := newTestHead(t, 1000, wlog.CompressionNone, true) + h, _ := newTestHead(t, 1000, compression.None, true) defer func() { require.NoError(t, h.Close()) }() @@ -385,11 +385,10 @@ func TestOOOHeadChunkReader_LabelValues(t *testing.T) { } } -//nolint:revive // unexported-return. +//nolint:revive // unexported-return func testOOOHeadChunkReader_LabelValues(t *testing.T, scenario sampleTypeScenario) { chunkRange := int64(2000) - head, _ := newTestHead(t, chunkRange, wlog.CompressionNone, true) - head.opts.EnableOOONativeHistograms.Store(true) + head, _ := newTestHead(t, chunkRange, compression.None, true) t.Cleanup(func() { require.NoError(t, head.Close()) }) ctx := context.Background() @@ -489,13 +488,12 @@ func TestOOOHeadChunkReader_Chunk(t *testing.T) { } } -//nolint:revive // unexported-return. +//nolint:revive // unexported-return func testOOOHeadChunkReader_Chunk(t *testing.T, scenario sampleTypeScenario) { opts := DefaultOptions() opts.OutOfOrderCapMax = 5 opts.OutOfOrderTimeWindow = 120 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true s1 := labels.FromStrings("l", "v1") minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() } @@ -900,13 +898,12 @@ func TestOOOHeadChunkReader_Chunk_ConsistentQueryResponseDespiteOfHeadExpanding( } } -//nolint:revive // unexported-return. +//nolint:revive // unexported-return func testOOOHeadChunkReader_Chunk_ConsistentQueryResponseDespiteOfHeadExpanding(t *testing.T, scenario sampleTypeScenario) { opts := DefaultOptions() opts.OutOfOrderCapMax = 5 opts.OutOfOrderTimeWindow = 120 * time.Minute.Milliseconds() opts.EnableNativeHistograms = true - opts.EnableOOONativeHistograms = true s1 := labels.FromStrings("l", "v1") minutes := func(m int64) int64 { return m * time.Minute.Milliseconds() } diff --git a/tsdb/postings_for_matchers_cache_test.go b/tsdb/postings_for_matchers_cache_test.go index ac5ffca5b7..b59b99bfa1 100644 --- a/tsdb/postings_for_matchers_cache_test.go +++ b/tsdb/postings_for_matchers_cache_test.go @@ -96,7 +96,7 @@ func TestPostingsForMatchersCache(t *testing.T) { expectedErr := errors.New("failed successfully") reg := prometheus.NewRegistry() - c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, 5, 1000, func(_ context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, 5, 1000, func(_ context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { return nil, expectedErr }, &timeNowMock{}, false, reg) @@ -171,7 +171,7 @@ func TestPostingsForMatchersCache(t *testing.T) { if cacheEnabled { ttl = DefaultPostingsForMatchersCacheTTL } - c := newPostingsForMatchersCache(ttl, 5, 1000, func(_ context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(ttl, 5, 1000, func(_ context.Context, _ IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { select { case called <- struct{}{}: default: @@ -219,7 +219,7 @@ func TestPostingsForMatchersCache(t *testing.T) { reg := prometheus.NewRegistry() var call int - c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, 5, 1000, func(_ context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, 5, 1000, func(_ context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { call++ return index.ErrPostings(fmt.Errorf("result from call %d", call)), nil }, &timeNowMock{}, false, reg) @@ -267,7 +267,7 @@ func TestPostingsForMatchersCache(t *testing.T) { reg := prometheus.NewRegistry() var call int - c := newPostingsForMatchersCache(0, 1000, 1000, func(_ context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(0, 1000, 1000, func(_ context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { call++ return index.ErrPostings(fmt.Errorf("result from call %d", call)), nil }, &timeNowMock{}, false, reg) @@ -318,7 +318,7 @@ func TestPostingsForMatchersCache(t *testing.T) { reg := prometheus.NewRegistry() var call int - c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, 5, 1000, func(_ context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, 5, 1000, func(_ context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { call++ return index.ErrPostings(fmt.Errorf("result from call %d", call)), nil }, timeNow, false, reg) @@ -382,7 +382,7 @@ func TestPostingsForMatchersCache(t *testing.T) { } callsPerMatchers := map[string]int{} - c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, maxItems, 100000, func(_ context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, maxItems, 100000, func(_ context.Context, _ IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { k := matchersKey(ms) callsPerMatchers[k]++ return index.ErrPostings(fmt.Errorf("result from call %d", callsPerMatchers[k])), nil @@ -474,7 +474,7 @@ func TestPostingsForMatchersCache(t *testing.T) { } callsPerMatchers := map[string]int{} - c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, maxItems, maxBytes, func(_ context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(DefaultPostingsForMatchersCacheTTL, maxItems, maxBytes, func(_ context.Context, _ IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { k := matchersKey(ms) callsPerMatchers[k]++ return index.NewListPostings(refsLists[k]), nil @@ -558,7 +558,7 @@ func TestPostingsForMatchersCache(t *testing.T) { var cancelReqCtx context.CancelFunc callsCount := atomic.NewInt32(0) - c := newPostingsForMatchersCache(time.Hour, 5, 1000, func(ctx context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(time.Hour, 5, 1000, func(ctx context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { callsCount.Inc() // We want the request context to be canceled while running PostingsForMatchers() @@ -633,7 +633,7 @@ func TestPostingsForMatchersCache(t *testing.T) { waitBeforeCancelReqCtx1 := make(chan struct{}) callsCount := atomic.NewInt32(0) - c := newPostingsForMatchersCache(time.Hour, 5, 1000, func(ctx context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(time.Hour, 5, 1000, func(ctx context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { callsCount.Inc() // Cancel the initial request once the test sends the signal. The requests context is not the same @@ -732,7 +732,7 @@ func TestPostingsForMatchersCache(t *testing.T) { cancelRequests := make(chan struct{}) callsCount := atomic.NewInt32(0) - c := newPostingsForMatchersCache(time.Hour, 5, 1000, func(ctx context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c := newPostingsForMatchersCache(time.Hour, 5, 1000, func(ctx context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { callsCount.Inc() // Cancel the requests once the test sends the signal. The requests context is not the same @@ -927,7 +927,7 @@ func TestPostingsForMatchersCache_RaceConditionBetweenExecutionContextCancellati c := NewPostingsForMatchersCache(time.Hour, 5, 1000, true, NewPostingsForMatchersCacheMetrics(reg)) - c.postingsForMatchers = func(ctx context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + c.postingsForMatchers = func(ctx context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { callsCount.Inc() // We want the request context to be canceled while running PostingsForMatchers() @@ -1031,7 +1031,7 @@ func BenchmarkPostingsForMatchersCache(b *testing.B) { b.Run("no evictions", func(b *testing.B) { // Configure the cache to never evict. cache := NewPostingsForMatchersCache(time.Hour, 1000000, 1024*1024*1024, true, NewPostingsForMatchersCacheMetrics(nil)) - cache.postingsForMatchers = func(ctx context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + cache.postingsForMatchers = func(_ context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { return index.NewListPostings(refs), nil } @@ -1048,7 +1048,7 @@ func BenchmarkPostingsForMatchersCache(b *testing.B) { b.Run("high eviction rate", func(b *testing.B) { // Configure the cache to evict continuously. cache := NewPostingsForMatchersCache(time.Hour, 0, 0, true, NewPostingsForMatchersCacheMetrics(nil)) - cache.postingsForMatchers = func(ctx context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + cache.postingsForMatchers = func(_ context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { return index.NewListPostings(refs), nil } @@ -1091,7 +1091,7 @@ func BenchmarkPostingsForMatchersCache_ConcurrencyOnHighEvictionRate(b *testing. // Configure the cache to evict continuously. cache := NewPostingsForMatchersCache(time.Hour, 0, 0, true, NewPostingsForMatchersCacheMetrics(nil)) - cache.postingsForMatchers = func(ctx context.Context, ix IndexPostingsReader, ms ...*labels.Matcher) (index.Postings, error) { + cache.postingsForMatchers = func(_ context.Context, _ IndexPostingsReader, _ ...*labels.Matcher) (index.Postings, error) { return index.NewListPostings(refs), nil } diff --git a/tsdb/querier.go b/tsdb/querier.go index 0d2f1ddcd8..07ec5e5cc2 100644 --- a/tsdb/querier.go +++ b/tsdb/querier.go @@ -20,7 +20,7 @@ import ( "math" "slices" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/labels" @@ -77,12 +77,12 @@ func newBlockBaseQuerier(b BlockReader, mint, maxt int64) (*blockBaseQuerier, er }, nil } -func (q *blockBaseQuerier) LabelValues(ctx context.Context, name string, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (q *blockBaseQuerier) LabelValues(ctx context.Context, name string, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { res, err := q.index.SortedLabelValues(ctx, name, matchers...) return res, nil, err } -func (q *blockBaseQuerier) LabelNames(ctx context.Context, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (q *blockBaseQuerier) LabelNames(ctx context.Context, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { res, err := q.index.LabelNames(ctx, matchers...) return res, nil, err } diff --git a/tsdb/querier_test.go b/tsdb/querier_test.go index f4deebd0c8..328a80c049 100644 --- a/tsdb/querier_test.go +++ b/tsdb/querier_test.go @@ -26,7 +26,7 @@ import ( "testing" "time" - "github.com/oklog/ulid" + "github.com/oklog/ulid/v2" "github.com/stretchr/testify/require" "github.com/prometheus/prometheus/model/histogram" @@ -104,7 +104,7 @@ type seriesSamples struct { // Index: labels -> postings -> chunkMetas -> chunkRef. // ChunkReader: ref -> vals. func createIdxChkReaders(t *testing.T, tc []seriesSamples) (IndexReader, ChunkReader, int64, int64) { - sort.Slice(tc, func(i, j int) bool { + sort.Slice(tc, func(i, _ int) bool { return labels.Compare(labels.FromMap(tc[i].lset), labels.FromMap(tc[i].lset)) < 0 }) @@ -1547,8 +1547,6 @@ func TestPopulateWithTombSeriesIterators(t *testing.T) { expectedMinMaxTimes: []minMaxTimes{{7, 12}, {11, 16}, {10, 203}}, }, { - // This case won't actually happen until OOO native histograms is implemented. - // Issue: https://github.com/prometheus/prometheus/issues/11220. name: "int histogram iterables with counter resets", samples: [][]chunks.Sample{ { @@ -1618,8 +1616,6 @@ func TestPopulateWithTombSeriesIterators(t *testing.T) { skipChunkTest: true, }, { - // This case won't actually happen until OOO native histograms is implemented. - // Issue: https://github.com/prometheus/prometheus/issues/11220. name: "float histogram iterables with counter resets", samples: [][]chunks.Sample{ { @@ -1689,8 +1685,6 @@ func TestPopulateWithTombSeriesIterators(t *testing.T) { skipChunkTest: true, }, { - // This case won't actually happen until OOO native histograms is implemented. - // Issue: https://github.com/prometheus/prometheus/issues/11220. name: "iterables with mixed encodings and counter resets", samples: [][]chunks.Sample{ { @@ -2390,7 +2384,7 @@ func (m mockIndex) PostingsForAllLabelValues(ctx context.Context, name string) i return index.Merge(ctx, res...) } -func (m mockIndex) PostingsForMatchers(_ context.Context, concurrent bool, ms ...*labels.Matcher) (index.Postings, error) { +func (m mockIndex) PostingsForMatchers(_ context.Context, _ bool, ms ...*labels.Matcher) (index.Postings, error) { var ps []storage.SeriesRef for p, s := range m.series { if matches(ms, s.l) { @@ -3387,7 +3381,7 @@ func (m mockMatcherIndex) LabelValueFor(context.Context, storage.SeriesRef, stri return "", errors.New("label value for called") } -func (m mockMatcherIndex) LabelNamesFor(ctx context.Context, postings index.Postings) ([]string, error) { +func (m mockMatcherIndex) LabelNamesFor(_ context.Context, _ index.Postings) ([]string, error) { return nil, errors.New("label names for called") } @@ -3395,19 +3389,15 @@ func (m mockMatcherIndex) Postings(context.Context, string, ...string) (index.Po return index.EmptyPostings(), nil } -func (m mockMatcherIndex) PostingsForMatchers(bool, ...*labels.Matcher) (index.Postings, error) { - return index.EmptyPostings(), nil -} - -func (m mockMatcherIndex) SortedPostings(p index.Postings) index.Postings { +func (m mockMatcherIndex) SortedPostings(_ index.Postings) index.Postings { return index.EmptyPostings() } -func (m mockMatcherIndex) ShardedPostings(ps index.Postings, shardIndex, shardCount uint64) index.Postings { +func (m mockMatcherIndex) ShardedPostings(ps index.Postings, _, _ uint64) index.Postings { return ps } -func (m mockMatcherIndex) Series(ref storage.SeriesRef, builder *labels.ScratchBuilder, chks *[]chunks.Meta) error { +func (m mockMatcherIndex) Series(_ storage.SeriesRef, _ *labels.ScratchBuilder, _ *[]chunks.Meta) error { return nil } @@ -3663,13 +3653,13 @@ func TestQueryWithDeletedHistograms(t *testing.T) { "intCounter": func(i int) (*histogram.Histogram, *histogram.FloatHistogram) { return tsdbutil.GenerateTestHistogram(int64(i)), nil }, - "intgauge": func(i int) (*histogram.Histogram, *histogram.FloatHistogram) { + "intgauge": func(_ int) (*histogram.Histogram, *histogram.FloatHistogram) { return tsdbutil.GenerateTestGaugeHistogram(rand.Int63() % 1000), nil }, "floatCounter": func(i int) (*histogram.Histogram, *histogram.FloatHistogram) { return nil, tsdbutil.GenerateTestFloatHistogram(int64(i)) }, - "floatGauge": func(i int) (*histogram.Histogram, *histogram.FloatHistogram) { + "floatGauge": func(_ int) (*histogram.Histogram, *histogram.FloatHistogram) { return nil, tsdbutil.GenerateTestGaugeFloatHistogram(rand.Int63() % 1000) }, } diff --git a/tsdb/record/record.go b/tsdb/record/record.go index 4d2a52b9af..692976cdf8 100644 --- a/tsdb/record/record.go +++ b/tsdb/record/record.go @@ -204,7 +204,7 @@ type Decoder struct { builder labels.ScratchBuilder } -func NewDecoder(t *labels.SymbolTable) Decoder { // FIXME remove t +func NewDecoder(_ *labels.SymbolTable) Decoder { // FIXME remove t return Decoder{builder: labels.NewScratchBuilder(0)} } diff --git a/tsdb/wlog/checkpoint_test.go b/tsdb/wlog/checkpoint_test.go index 047b89790b..7a0687aedc 100644 --- a/tsdb/wlog/checkpoint_test.go +++ b/tsdb/wlog/checkpoint_test.go @@ -23,14 +23,14 @@ import ( "strings" "testing" - "github.com/stretchr/testify/require" - "github.com/prometheus/common/promslog" + "github.com/stretchr/testify/require" "github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/tsdb/chunks" "github.com/prometheus/prometheus/tsdb/record" + "github.com/prometheus/prometheus/util/compression" "github.com/prometheus/prometheus/util/testutil" ) @@ -170,7 +170,7 @@ func TestCheckpoint(t *testing.T) { } } - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() @@ -385,7 +385,7 @@ func TestCheckpoint(t *testing.T) { func TestCheckpointNoTmpFolderAfterError(t *testing.T) { // Create a new wlog with invalid data. dir := t.TempDir() - w, err := NewSize(nil, nil, dir, 64*1024, CompressionNone) + w, err := NewSize(nil, nil, dir, 64*1024, compression.None) require.NoError(t, err) var enc record.Encoder require.NoError(t, w.Log(enc.Series([]record.RefSeries{ diff --git a/tsdb/wlog/live_reader.go b/tsdb/wlog/live_reader.go index a017d362d1..04f24387bf 100644 --- a/tsdb/wlog/live_reader.go +++ b/tsdb/wlog/live_reader.go @@ -22,9 +22,9 @@ import ( "io" "log/slog" - "github.com/golang/snappy" - "github.com/klauspost/compress/zstd" "github.com/prometheus/client_golang/prometheus" + + "github.com/prometheus/prometheus/util/compression" ) // LiveReaderMetrics holds all metrics exposed by the LiveReader. @@ -51,14 +51,11 @@ func NewLiveReaderMetrics(reg prometheus.Registerer) *LiveReaderMetrics { // NewLiveReader returns a new live reader. func NewLiveReader(logger *slog.Logger, metrics *LiveReaderMetrics, r io.Reader) *LiveReader { - // Calling zstd.NewReader with a nil io.Reader and no options cannot return an error. - zstdReader, _ := zstd.NewReader(nil) - lr := &LiveReader{ - logger: logger, - rdr: r, - zstdReader: zstdReader, - metrics: metrics, + logger: logger, + rdr: r, + decBuf: compression.NewSyncDecodeBuffer(), + metrics: metrics, // Until we understand how they come about, make readers permissive // to records spanning pages. @@ -72,12 +69,13 @@ func NewLiveReader(logger *slog.Logger, metrics *LiveReaderMetrics, r io.Reader) // that are still in the process of being written, and returns records as soon // as they can be read. type LiveReader struct { - logger *slog.Logger - rdr io.Reader - err error - rec []byte - compressBuf []byte - zstdReader *zstd.Decoder + logger *slog.Logger + rdr io.Reader + err error + rec []byte + + precomprBuf []byte + decBuf compression.DecodeBuffer hdr [recordHeaderSize]byte buf [pageSize]byte readIndex int // Index in buf to start at for next read. @@ -195,39 +193,29 @@ func (r *LiveReader) buildRecord() (bool, error) { rt := recTypeFromHeader(r.hdr[0]) if rt == recFirst || rt == recFull { - r.rec = r.rec[:0] - r.compressBuf = r.compressBuf[:0] + r.precomprBuf = r.precomprBuf[:0] } - isSnappyCompressed := r.hdr[0]&snappyMask == snappyMask - isZstdCompressed := r.hdr[0]&zstdMask == zstdMask - - if isSnappyCompressed || isZstdCompressed { - r.compressBuf = append(r.compressBuf, temp...) - } else { - r.rec = append(r.rec, temp...) + // Segment format has only 2 bits, so it's either of those 3 options. + // https://github.com/prometheus/prometheus/blob/main/tsdb/docs/format/wal.md#records-encoding + compr := compression.None + if r.hdr[0]&snappyMask == snappyMask { + compr = compression.Snappy + } else if r.hdr[0]&zstdMask == zstdMask { + compr = compression.Zstd } + r.precomprBuf = append(r.precomprBuf, temp...) + if err := validateRecord(rt, r.index); err != nil { r.index = 0 return false, err } if rt == recLast || rt == recFull { r.index = 0 - if isSnappyCompressed && len(r.compressBuf) > 0 { - // The snappy library uses `len` to calculate if we need a new buffer. - // In order to allocate as few buffers as possible make the length - // equal to the capacity. - r.rec = r.rec[:cap(r.rec)] - r.rec, err = snappy.Decode(r.rec, r.compressBuf) - if err != nil { - return false, err - } - } else if isZstdCompressed && len(r.compressBuf) > 0 { - r.rec, err = r.zstdReader.DecodeAll(r.compressBuf, r.rec[:0]) - if err != nil { - return false, err - } + r.rec, err = compression.Decode(compr, r.precomprBuf, r.decBuf) + if err != nil { + return false, err } return true, nil } diff --git a/tsdb/wlog/reader.go b/tsdb/wlog/reader.go index a744b0cc4b..c559d85b89 100644 --- a/tsdb/wlog/reader.go +++ b/tsdb/wlog/reader.go @@ -21,17 +21,17 @@ import ( "hash/crc32" "io" - "github.com/golang/snappy" - "github.com/klauspost/compress/zstd" + "github.com/prometheus/prometheus/util/compression" ) // Reader reads WAL records from an io.Reader. type Reader struct { - rdr io.Reader - err error - rec []byte - compressBuf []byte - zstdReader *zstd.Decoder + rdr io.Reader + err error + rec []byte + + precomprBuf []byte + decBuf compression.DecodeBuffer buf [pageSize]byte total int64 // Total bytes processed. curRecTyp recType // Used for checking that the last record is not torn. @@ -39,15 +39,13 @@ type Reader struct { // NewReader returns a new reader. func NewReader(r io.Reader) *Reader { - // Calling zstd.NewReader with a nil io.Reader and no options cannot return an error. - zstdReader, _ := zstd.NewReader(nil) - return &Reader{rdr: r, zstdReader: zstdReader} + return &Reader{rdr: r, decBuf: compression.NewSyncDecodeBuffer()} } // Next advances the reader to the next records and returns true if it exists. // It must not be called again after it returned false. func (r *Reader) Next() bool { - err := r.next() + err := r.nextNew() if err != nil && errors.Is(err, io.EOF) { // The last WAL segment record shouldn't be torn(should be full or last). // The last record would be torn after a crash just before @@ -61,14 +59,13 @@ func (r *Reader) Next() bool { return r.err == nil } -func (r *Reader) next() (err error) { +func (r *Reader) nextNew() (err error) { // We have to use r.buf since allocating byte arrays here fails escape // analysis and ends up on the heap, even though it seemingly should not. hdr := r.buf[:recordHeaderSize] buf := r.buf[recordHeaderSize:] - r.rec = r.rec[:0] - r.compressBuf = r.compressBuf[:0] + r.precomprBuf = r.precomprBuf[:0] i := 0 for { @@ -77,8 +74,13 @@ func (r *Reader) next() (err error) { } r.total++ r.curRecTyp = recTypeFromHeader(hdr[0]) - isSnappyCompressed := hdr[0]&snappyMask == snappyMask - isZstdCompressed := hdr[0]&zstdMask == zstdMask + + compr := compression.None + if hdr[0]&snappyMask == snappyMask { + compr = compression.Snappy + } else if hdr[0]&zstdMask == zstdMask { + compr = compression.Zstd + } // Gobble up zero bytes. if r.curRecTyp == recPageTerm { @@ -133,29 +135,14 @@ func (r *Reader) next() (err error) { if c := crc32.Checksum(buf[:length], castagnoliTable); c != crc { return fmt.Errorf("unexpected checksum %x, expected %x", c, crc) } - - if isSnappyCompressed || isZstdCompressed { - r.compressBuf = append(r.compressBuf, buf[:length]...) - } else { - r.rec = append(r.rec, buf[:length]...) - } - if err := validateRecord(r.curRecTyp, i); err != nil { return err } + + r.precomprBuf = append(r.precomprBuf, buf[:length]...) if r.curRecTyp == recLast || r.curRecTyp == recFull { - if isSnappyCompressed && len(r.compressBuf) > 0 { - // The snappy library uses `len` to calculate if we need a new buffer. - // In order to allocate as few buffers as possible make the length - // equal to the capacity. - r.rec = r.rec[:cap(r.rec)] - r.rec, err = snappy.Decode(r.rec, r.compressBuf) - return err - } else if isZstdCompressed && len(r.compressBuf) > 0 { - r.rec, err = r.zstdReader.DecodeAll(r.compressBuf, r.rec[:0]) - return err - } - return nil + r.rec, err = compression.Decode(compr, r.precomprBuf, r.decBuf) + return err } // Only increment i for non-zero records since we use it diff --git a/tsdb/wlog/reader_test.go b/tsdb/wlog/reader_test.go index 2ac63cbf15..0cbe882844 100644 --- a/tsdb/wlog/reader_test.go +++ b/tsdb/wlog/reader_test.go @@ -29,11 +29,11 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" - "github.com/prometheus/common/promslog" + "github.com/stretchr/testify/require" tsdb_errors "github.com/prometheus/prometheus/tsdb/errors" + "github.com/prometheus/prometheus/util/compression" ) type reader interface { @@ -315,7 +315,7 @@ func allSegments(dir string) (io.ReadCloser, error) { func TestReaderFuzz(t *testing.T) { for name, fn := range readerConstructors { - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("%s,compress=%s", name, compress), func(t *testing.T) { dir := t.TempDir() @@ -354,7 +354,7 @@ func TestReaderFuzz(t *testing.T) { func TestReaderFuzz_Live(t *testing.T) { logger := promslog.NewNopLogger() - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() @@ -444,7 +444,7 @@ func TestLiveReaderCorrupt_ShortFile(t *testing.T) { logger := promslog.NewNopLogger() dir := t.TempDir() - w, err := NewSize(nil, nil, dir, pageSize, CompressionNone) + w, err := NewSize(nil, nil, dir, pageSize, compression.None) require.NoError(t, err) rec := make([]byte, pageSize-recordHeaderSize) @@ -484,7 +484,7 @@ func TestLiveReaderCorrupt_RecordTooLongAndShort(t *testing.T) { logger := promslog.NewNopLogger() dir := t.TempDir() - w, err := NewSize(nil, nil, dir, pageSize*2, CompressionNone) + w, err := NewSize(nil, nil, dir, pageSize*2, compression.None) require.NoError(t, err) rec := make([]byte, pageSize-recordHeaderSize) @@ -531,7 +531,7 @@ func TestReaderData(t *testing.T) { for name, fn := range readerConstructors { t.Run(name, func(t *testing.T) { - w, err := New(nil, nil, dir, CompressionSnappy) + w, err := New(nil, nil, dir, compression.Snappy) require.NoError(t, err) sr, err := allSegments(dir) diff --git a/tsdb/wlog/watcher.go b/tsdb/wlog/watcher.go index ca74a9ceaf..f171a8bdc1 100644 --- a/tsdb/wlog/watcher.go +++ b/tsdb/wlog/watcher.go @@ -491,12 +491,13 @@ func (w *Watcher) readSegment(r *LiveReader, segmentNum int, tail bool) error { metadata []record.RefMetadata ) for r.Next() && !isClosed(w.quit) { + var err error rec := r.Record() w.recordsReadMetric.WithLabelValues(dec.Type(rec).String()).Inc() switch dec.Type(rec) { case record.Series: - series, err := dec.Series(rec, series[:0]) + series, err = dec.Series(rec, series[:0]) if err != nil { w.recordDecodeFailsMetric.Inc() return err @@ -509,7 +510,7 @@ func (w *Watcher) readSegment(r *LiveReader, segmentNum int, tail bool) error { if !tail { break } - samples, err := dec.Samples(rec, samples[:0]) + samples, err = dec.Samples(rec, samples[:0]) if err != nil { w.recordDecodeFailsMetric.Inc() return err @@ -539,7 +540,7 @@ func (w *Watcher) readSegment(r *LiveReader, segmentNum int, tail bool) error { if !tail { break } - exemplars, err := dec.Exemplars(rec, exemplars[:0]) + exemplars, err = dec.Exemplars(rec, exemplars[:0]) if err != nil { w.recordDecodeFailsMetric.Inc() return err @@ -554,7 +555,7 @@ func (w *Watcher) readSegment(r *LiveReader, segmentNum int, tail bool) error { if !tail { break } - histograms, err := dec.HistogramSamples(rec, histograms[:0]) + histograms, err = dec.HistogramSamples(rec, histograms[:0]) if err != nil { w.recordDecodeFailsMetric.Inc() return err @@ -582,7 +583,7 @@ func (w *Watcher) readSegment(r *LiveReader, segmentNum int, tail bool) error { if !tail { break } - floatHistograms, err := dec.FloatHistogramSamples(rec, floatHistograms[:0]) + floatHistograms, err = dec.FloatHistogramSamples(rec, floatHistograms[:0]) if err != nil { w.recordDecodeFailsMetric.Inc() return err @@ -606,12 +607,12 @@ func (w *Watcher) readSegment(r *LiveReader, segmentNum int, tail bool) error { if !w.sendMetadata { break } - meta, err := dec.Metadata(rec, metadata[:0]) + metadata, err = dec.Metadata(rec, metadata[:0]) if err != nil { w.recordDecodeFailsMetric.Inc() return err } - w.writer.StoreMetadata(meta) + w.writer.StoreMetadata(metadata) case record.Unknown: // Could be corruption, or reading from a WAL from a newer Prometheus. diff --git a/tsdb/wlog/watcher_test.go b/tsdb/wlog/watcher_test.go index 0e22bc50a7..6aebe7dab3 100644 --- a/tsdb/wlog/watcher_test.go +++ b/tsdb/wlog/watcher_test.go @@ -31,6 +31,7 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/tsdb/chunks" "github.com/prometheus/prometheus/tsdb/record" + "github.com/prometheus/prometheus/util/compression" ) var ( @@ -142,7 +143,7 @@ func TestTailSamples(t *testing.T) { const samplesCount = 250 const exemplarsCount = 25 const histogramsCount = 50 - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { now := time.Now() @@ -290,7 +291,7 @@ func TestReadToEndNoCheckpoint(t *testing.T) { const seriesCount = 10 const samplesCount = 250 - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() wdir := path.Join(dir, "wal") @@ -358,7 +359,7 @@ func TestReadToEndWithCheckpoint(t *testing.T) { const seriesCount = 10 const samplesCount = 250 - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() @@ -446,7 +447,7 @@ func TestReadCheckpoint(t *testing.T) { const seriesCount = 10 const samplesCount = 250 - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() @@ -519,7 +520,7 @@ func TestReadCheckpointMultipleSegments(t *testing.T) { const seriesCount = 20 const samplesCount = 300 - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() @@ -590,11 +591,11 @@ func TestCheckpointSeriesReset(t *testing.T) { const seriesCount = 20 const samplesCount = 350 testCases := []struct { - compress CompressionType + compress compression.Type segments int }{ - {compress: CompressionNone, segments: 14}, - {compress: CompressionSnappy, segments: 13}, + {compress: compression.None, segments: 14}, + {compress: compression.Snappy, segments: 13}, } for _, tc := range testCases { @@ -681,8 +682,8 @@ func TestRun_StartupTime(t *testing.T) { const seriesCount = 20 const samplesCount = 300 - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { - t.Run(string(compress), func(t *testing.T) { + for _, compress := range compression.Types() { + t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() wdir := path.Join(dir, "wal") @@ -774,8 +775,8 @@ func TestRun_AvoidNotifyWhenBehind(t *testing.T) { const seriesCount = 10 const samplesCount = 50 - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { - t.Run(string(compress), func(t *testing.T) { + for _, compress := range compression.Types() { + t.Run(fmt.Sprintf("compress=%s", compress), func(t *testing.T) { dir := t.TempDir() wdir := path.Join(dir, "wal") diff --git a/tsdb/wlog/wlog.go b/tsdb/wlog/wlog.go index 54c257d61a..dec41ad2c7 100644 --- a/tsdb/wlog/wlog.go +++ b/tsdb/wlog/wlog.go @@ -29,12 +29,12 @@ import ( "sync" "time" - "github.com/golang/snappy" - "github.com/klauspost/compress/zstd" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/common/promslog" "github.com/prometheus/prometheus/tsdb/fileutil" + "github.com/prometheus/prometheus/util/compression" ) const ( @@ -169,26 +169,6 @@ func OpenReadSegment(fn string) (*Segment, error) { return &Segment{SegmentFile: f, i: k, dir: filepath.Dir(fn)}, nil } -type CompressionType string - -const ( - CompressionNone CompressionType = "none" - CompressionSnappy CompressionType = "snappy" - CompressionZstd CompressionType = "zstd" -) - -// ParseCompressionType parses the two compression-related configuration values and returns the CompressionType. If -// compression is enabled but the compressType is unrecognized, we default to Snappy compression. -func ParseCompressionType(compress bool, compressType string) CompressionType { - if compress { - if compressType == "zstd" { - return CompressionZstd - } - return CompressionSnappy - } - return CompressionNone -} - // WL is a write log that stores records in segment files. // It must be read from start to end once before logging new data. // If an error occurs during read, the repair procedure must be called @@ -210,9 +190,8 @@ type WL struct { stopc chan chan struct{} actorc chan func() closed bool // To allow calling Close() more than once without blocking. - compress CompressionType - compressBuf []byte - zstdWriter *zstd.Encoder + compress compression.Type + cEnc compression.EncodeBuffer WriteNotified WriteNotified @@ -220,14 +199,17 @@ type WL struct { } type wlMetrics struct { - fsyncDuration prometheus.Summary - pageFlushes prometheus.Counter - pageCompletions prometheus.Counter - truncateFail prometheus.Counter - truncateTotal prometheus.Counter - currentSegment prometheus.Gauge - writesFailed prometheus.Counter - walFileSize prometheus.GaugeFunc + fsyncDuration prometheus.Summary + pageFlushes prometheus.Counter + pageCompletions prometheus.Counter + truncateFail prometheus.Counter + truncateTotal prometheus.Counter + currentSegment prometheus.Gauge + writesFailed prometheus.Counter + walFileSize prometheus.GaugeFunc + recordPartWrites prometheus.Counter + recordPartBytes prometheus.Counter + recordBytesSaved *prometheus.CounterVec r prometheus.Registerer } @@ -244,78 +226,78 @@ func (w *wlMetrics) Unregister() { w.r.Unregister(w.currentSegment) w.r.Unregister(w.writesFailed) w.r.Unregister(w.walFileSize) + w.r.Unregister(w.recordPartWrites) + w.r.Unregister(w.recordPartBytes) + w.r.Unregister(w.recordBytesSaved) } func newWLMetrics(w *WL, r prometheus.Registerer) *wlMetrics { - m := &wlMetrics{ + return &wlMetrics{ r: r, + fsyncDuration: promauto.With(r).NewSummary(prometheus.SummaryOpts{ + Name: "fsync_duration_seconds", + Help: "Duration of write log fsync.", + Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, + }), + pageFlushes: promauto.With(r).NewCounter(prometheus.CounterOpts{ + Name: "page_flushes_total", + Help: "Total number of page flushes.", + }), + pageCompletions: promauto.With(r).NewCounter(prometheus.CounterOpts{ + Name: "completed_pages_total", + Help: "Total number of completed pages.", + }), + truncateFail: promauto.With(r).NewCounter(prometheus.CounterOpts{ + Name: "truncations_failed_total", + Help: "Total number of write log truncations that failed.", + }), + truncateTotal: promauto.With(r).NewCounter(prometheus.CounterOpts{ + Name: "truncations_total", + Help: "Total number of write log truncations attempted.", + }), + currentSegment: promauto.With(r).NewGauge(prometheus.GaugeOpts{ + Name: "segment_current", + Help: "Write log segment index that TSDB is currently writing to.", + }), + writesFailed: promauto.With(r).NewCounter(prometheus.CounterOpts{ + Name: "writes_failed_total", + Help: "Total number of write log writes that failed.", + }), + walFileSize: promauto.With(r).NewGaugeFunc(prometheus.GaugeOpts{ + Name: "storage_size_bytes", + Help: "Size of the write log directory.", + }, func() float64 { + val, err := w.Size() + if err != nil { + w.logger.Error("Failed to calculate size of \"wal\" dir", "err", err.Error()) + } + return float64(val) + }), + recordPartWrites: promauto.With(r).NewCounter(prometheus.CounterOpts{ + Name: "record_part_writes_total", + Help: "Total number of record parts written before flushing.", + }), + recordPartBytes: promauto.With(r).NewCounter(prometheus.CounterOpts{ + Name: "record_parts_bytes_written_total", + Help: "Total number of record part bytes written before flushing, including" + + " CRC and compression headers.", + }), + recordBytesSaved: promauto.With(r).NewCounterVec(prometheus.CounterOpts{ + Name: "record_bytes_saved_total", + Help: "Total number of bytes saved by the optional record compression." + + " Use this metric to learn about the effectiveness compression.", + }, []string{"compression"}), } - - m.fsyncDuration = prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "fsync_duration_seconds", - Help: "Duration of write log fsync.", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }) - m.pageFlushes = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "page_flushes_total", - Help: "Total number of page flushes.", - }) - m.pageCompletions = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "completed_pages_total", - Help: "Total number of completed pages.", - }) - m.truncateFail = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "truncations_failed_total", - Help: "Total number of write log truncations that failed.", - }) - m.truncateTotal = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "truncations_total", - Help: "Total number of write log truncations attempted.", - }) - m.currentSegment = prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "segment_current", - Help: "Write log segment index that TSDB is currently writing to.", - }) - m.writesFailed = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "writes_failed_total", - Help: "Total number of write log writes that failed.", - }) - m.walFileSize = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ - Name: "storage_size_bytes", - Help: "Size of the write log directory.", - }, func() float64 { - val, err := w.Size() - if err != nil { - w.logger.Error("Failed to calculate size of \"wal\" dir", - "err", err.Error()) - } - return float64(val) - }) - - if r != nil { - r.MustRegister( - m.fsyncDuration, - m.pageFlushes, - m.pageCompletions, - m.truncateFail, - m.truncateTotal, - m.currentSegment, - m.writesFailed, - m.walFileSize, - ) - } - - return m } // New returns a new WAL over the given directory. -func New(logger *slog.Logger, reg prometheus.Registerer, dir string, compress CompressionType) (*WL, error) { +func New(logger *slog.Logger, reg prometheus.Registerer, dir string, compress compression.Type) (*WL, error) { return NewSize(logger, reg, dir, DefaultSegmentSize, compress) } // NewSize returns a new write log over the given directory. // New segments are created with the specified size. -func NewSize(logger *slog.Logger, reg prometheus.Registerer, dir string, segmentSize int, compress CompressionType) (*WL, error) { +func NewSize(logger *slog.Logger, reg prometheus.Registerer, dir string, segmentSize int, compress compression.Type) (*WL, error) { if segmentSize%pageSize != 0 { return nil, errors.New("invalid segment size") } @@ -326,15 +308,6 @@ func NewSize(logger *slog.Logger, reg prometheus.Registerer, dir string, segment logger = promslog.NewNopLogger() } - var zstdWriter *zstd.Encoder - if compress == CompressionZstd { - var err error - zstdWriter, err = zstd.NewWriter(nil) - if err != nil { - return nil, err - } - } - w := &WL{ dir: dir, logger: logger, @@ -343,7 +316,7 @@ func NewSize(logger *slog.Logger, reg prometheus.Registerer, dir string, segment actorc: make(chan func(), 100), stopc: make(chan chan struct{}), compress: compress, - zstdWriter: zstdWriter, + cEnc: compression.NewSyncEncodeBuffer(), } prefix := "prometheus_tsdb_wal_" if filepath.Base(dir) == WblDirName { @@ -382,22 +355,16 @@ func Open(logger *slog.Logger, dir string) (*WL, error) { if logger == nil { logger = promslog.NewNopLogger() } - zstdWriter, err := zstd.NewWriter(nil) - if err != nil { - return nil, err - } w := &WL{ - dir: dir, - logger: logger, - zstdWriter: zstdWriter, + dir: dir, + logger: logger, } - return w, nil } // CompressionType returns if compression is enabled on this WAL. -func (w *WL) CompressionType() CompressionType { +func (w *WL) CompressionType() compression.Type { return w.compress } @@ -715,26 +682,23 @@ func (w *WL) log(rec []byte, final bool) error { } // Compress the record before calculating if a new segment is needed. - compressed := false - if w.compress == CompressionSnappy && len(rec) > 0 { - // If MaxEncodedLen is less than 0 the record is too large to be compressed. - if len(rec) > 0 && snappy.MaxEncodedLen(len(rec)) >= 0 { - // The snappy library uses `len` to calculate if we need a new buffer. - // In order to allocate as few buffers as possible make the length - // equal to the capacity. - w.compressBuf = w.compressBuf[:cap(w.compressBuf)] - w.compressBuf = snappy.Encode(w.compressBuf, rec) - if len(w.compressBuf) < len(rec) { - rec = w.compressBuf - compressed = true - } - } - } else if w.compress == CompressionZstd && len(rec) > 0 { - w.compressBuf = w.zstdWriter.EncodeAll(rec, w.compressBuf[:0]) - if len(w.compressBuf) < len(rec) { - rec = w.compressBuf - compressed = true + finalCompression := w.compress + enc, err := compression.Encode(w.compress, rec, w.cEnc) + if err != nil { + return err + } + if w.compress != compression.None { + savedBytes := len(rec) - len(enc) + + // Even if the compression was applied, skip it, if there's no benefit + // in the WAL record size (we have a choice). For small records e.g. snappy + // compression can yield larger records than the uncompressed. + if savedBytes <= 0 { + enc = rec + finalCompression = compression.None + savedBytes = 0 } + w.metrics.recordBytesSaved.WithLabelValues(w.compress).Add(float64(savedBytes)) } // If the record is too big to fit within the active page in the current @@ -743,7 +707,7 @@ func (w *WL) log(rec []byte, final bool) error { left := w.page.remaining() - recordHeaderSize // Free space in the active page. left += (pageSize - recordHeaderSize) * (w.pagesPerSegment() - w.donePages - 1) // Free pages in the active segment. - if len(rec) > left { + if len(enc) > left { if _, err := w.nextSegment(true); err != nil { return err } @@ -751,32 +715,36 @@ func (w *WL) log(rec []byte, final bool) error { // Populate as many pages as necessary to fit the record. // Be careful to always do one pass to ensure we write zero-length records. - for i := 0; i == 0 || len(rec) > 0; i++ { + for i := 0; i == 0 || len(enc) > 0; i++ { p := w.page // Find how much of the record we can fit into the page. var ( - l = min(len(rec), (pageSize-p.alloc)-recordHeaderSize) - part = rec[:l] + l = min(len(enc), (pageSize-p.alloc)-recordHeaderSize) + part = enc[:l] buf = p.buf[p.alloc:] typ recType ) switch { - case i == 0 && len(part) == len(rec): + case i == 0 && len(part) == len(enc): typ = recFull - case len(part) == len(rec): + case len(part) == len(enc): typ = recLast case i == 0: typ = recFirst default: typ = recMiddle } - if compressed { - if w.compress == CompressionSnappy { + + if finalCompression != compression.None { + switch finalCompression { + case compression.Snappy: typ |= snappyMask - } else if w.compress == CompressionZstd { + case compression.Zstd: typ |= zstdMask + default: + return fmt.Errorf("unsupported compression type: %v", finalCompression) } } @@ -788,6 +756,9 @@ func (w *WL) log(rec []byte, final bool) error { copy(buf[recordHeaderSize:], part) p.alloc += len(part) + recordHeaderSize + w.metrics.recordPartWrites.Inc() + w.metrics.recordPartBytes.Add(float64(len(part) + recordHeaderSize)) + if w.page.full() { if err := w.flushPage(true); err != nil { // TODO When the flushing fails at this point and the record has not been @@ -796,7 +767,7 @@ func (w *WL) log(rec []byte, final bool) error { return err } } - rec = rec[l:] + enc = enc[l:] } // If it's the final record of the batch and the page is not empty, flush it. diff --git a/tsdb/wlog/wlog_test.go b/tsdb/wlog/wlog_test.go index 5380798b42..d56dbd2b08 100644 --- a/tsdb/wlog/wlog_test.go +++ b/tsdb/wlog/wlog_test.go @@ -29,6 +29,7 @@ import ( "github.com/stretchr/testify/require" "github.com/prometheus/prometheus/tsdb/fileutil" + "github.com/prometheus/prometheus/util/compression" "github.com/prometheus/prometheus/util/testutil" ) @@ -125,7 +126,7 @@ func TestWALRepair_ReadingError(t *testing.T) { // then corrupt a given record in a given segment. // As a result we want a repaired WAL with given intact records. segSize := 3 * pageSize - w, err := NewSize(nil, nil, dir, segSize, CompressionNone) + w, err := NewSize(nil, nil, dir, segSize, compression.None) require.NoError(t, err) var records [][]byte @@ -150,7 +151,7 @@ func TestWALRepair_ReadingError(t *testing.T) { require.NoError(t, f.Close()) - w, err = NewSize(nil, nil, dir, segSize, CompressionNone) + w, err = NewSize(nil, nil, dir, segSize, compression.None) require.NoError(t, err) defer w.Close() @@ -222,7 +223,7 @@ func TestCorruptAndCarryOn(t *testing.T) { // Produce a WAL with a two segments of 3 pages with 3 records each, // so when we truncate the file we're guaranteed to split a record. { - w, err := NewSize(logger, nil, dir, segmentSize, CompressionNone) + w, err := NewSize(logger, nil, dir, segmentSize, compression.None) require.NoError(t, err) for i := 0; i < 18; i++ { @@ -293,7 +294,7 @@ func TestCorruptAndCarryOn(t *testing.T) { err = sr.Close() require.NoError(t, err) - w, err := NewSize(logger, nil, dir, segmentSize, CompressionNone) + w, err := NewSize(logger, nil, dir, segmentSize, compression.None) require.NoError(t, err) err = w.Repair(corruptionErr) @@ -336,7 +337,7 @@ func TestCorruptAndCarryOn(t *testing.T) { // TestClose ensures that calling Close more than once doesn't panic and doesn't block. func TestClose(t *testing.T) { dir := t.TempDir() - w, err := NewSize(nil, nil, dir, pageSize, CompressionNone) + w, err := NewSize(nil, nil, dir, pageSize, compression.None) require.NoError(t, err) require.NoError(t, w.Close()) require.Error(t, w.Close()) @@ -349,7 +350,7 @@ func TestSegmentMetric(t *testing.T) { ) dir := t.TempDir() - w, err := NewSize(nil, nil, dir, segmentSize, CompressionNone) + w, err := NewSize(nil, nil, dir, segmentSize, compression.None) require.NoError(t, err) initialSegment := client_testutil.ToFloat64(w.metrics.currentSegment) @@ -368,7 +369,7 @@ func TestSegmentMetric(t *testing.T) { } func TestCompression(t *testing.T) { - bootstrap := func(compressed CompressionType) string { + bootstrap := func(compressed compression.Type) string { const ( segmentSize = pageSize recordSize = (pageSize / 2) - recordHeaderSize @@ -396,10 +397,10 @@ func TestCompression(t *testing.T) { } }() - dirUnCompressed := bootstrap(CompressionNone) + dirUnCompressed := bootstrap(compression.None) tmpDirs = append(tmpDirs, dirUnCompressed) - for _, compressionType := range []CompressionType{CompressionSnappy, CompressionZstd} { + for _, compressionType := range []compression.Type{compression.Snappy, compression.Zstd} { dirCompressed := bootstrap(compressionType) tmpDirs = append(tmpDirs, dirCompressed) @@ -443,7 +444,7 @@ func TestLogPartialWrite(t *testing.T) { t.Run(testName, func(t *testing.T) { dirPath := t.TempDir() - w, err := NewSize(nil, nil, dirPath, segmentSize, CompressionNone) + w, err := NewSize(nil, nil, dirPath, segmentSize, compression.None) require.NoError(t, err) // Replace the underlying segment file with a mocked one that injects a failure. @@ -510,7 +511,7 @@ func (f *faultySegmentFile) Write(p []byte) (int, error) { } func BenchmarkWAL_LogBatched(b *testing.B) { - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { b.Run(fmt.Sprintf("compress=%s", compress), func(b *testing.B) { dir := b.TempDir() @@ -540,7 +541,7 @@ func BenchmarkWAL_LogBatched(b *testing.B) { } func BenchmarkWAL_Log(b *testing.B) { - for _, compress := range []CompressionType{CompressionNone, CompressionSnappy, CompressionZstd} { + for _, compress := range compression.Types() { b.Run(fmt.Sprintf("compress=%s", compress), func(b *testing.B) { dir := b.TempDir() @@ -567,7 +568,7 @@ func TestUnregisterMetrics(t *testing.T) { reg := prometheus.NewRegistry() for i := 0; i < 2; i++ { - wl, err := New(promslog.NewNopLogger(), reg, t.TempDir(), CompressionNone) + wl, err := New(promslog.NewNopLogger(), reg, t.TempDir(), compression.None) require.NoError(t, err) require.NoError(t, wl.Close()) } diff --git a/util/compression/buffers.go b/util/compression/buffers.go new file mode 100644 index 0000000000..765bc64c0b --- /dev/null +++ b/util/compression/buffers.go @@ -0,0 +1,142 @@ +// Copyright 2025 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 compression + +import ( + "sync" + + "github.com/klauspost/compress/zstd" +) + +type EncodeBuffer interface { + zstdEncBuf() *zstd.Encoder + get() []byte + set([]byte) +} + +type syncEBuffer struct { + onceZstd sync.Once + w *zstd.Encoder + buf []byte +} + +// NewSyncEncodeBuffer returns synchronous buffer that can only be used +// on one encoding goroutine at once. Notably, the encoded byte slice returned +// by Encode is valid only until the next Encode call. +func NewSyncEncodeBuffer() EncodeBuffer { + return &syncEBuffer{} +} + +func (b *syncEBuffer) zstdEncBuf() *zstd.Encoder { + b.onceZstd.Do(func() { + // Without params this never returns error. + b.w, _ = zstd.NewWriter(nil) + }) + return b.w +} + +func (b *syncEBuffer) get() []byte { + return b.buf +} + +func (b *syncEBuffer) set(buf []byte) { + b.buf = buf +} + +type concurrentEBuffer struct { + onceZstd sync.Once + w *zstd.Encoder +} + +// NewConcurrentEncodeBuffer returns a buffer that can be used concurrently. +// NOTE: For Zstd compression, a concurrency limit equal to GOMAXPROCS is implied. +func NewConcurrentEncodeBuffer() EncodeBuffer { + return &concurrentEBuffer{} +} + +func (b *concurrentEBuffer) zstdEncBuf() *zstd.Encoder { + b.onceZstd.Do(func() { + // Without params this never returns error. + b.w, _ = zstd.NewWriter(nil) + }) + return b.w +} + +// TODO(bwplotka): We could use pool, but putting it back into the pool needs to be +// on the caller side, so no pool for now. +func (b *concurrentEBuffer) get() []byte { + return nil +} + +func (b *concurrentEBuffer) set([]byte) {} + +type DecodeBuffer interface { + zstdDecBuf() *zstd.Decoder + get() []byte + set([]byte) +} + +type syncDBuffer struct { + onceZstd sync.Once + r *zstd.Decoder + buf []byte +} + +// NewSyncDecodeBuffer returns synchronous buffer that can only be used +// on one decoding goroutine at once. Notably, the decoded byte slice returned +// by Decode is valid only until the next Decode call. +func NewSyncDecodeBuffer() DecodeBuffer { + return &syncDBuffer{} +} + +func (b *syncDBuffer) zstdDecBuf() *zstd.Decoder { + b.onceZstd.Do(func() { + // Without params this never returns error. + b.r, _ = zstd.NewReader(nil) + }) + return b.r +} + +func (b *syncDBuffer) get() []byte { + return b.buf +} + +func (b *syncDBuffer) set(buf []byte) { + b.buf = buf +} + +type concurrentDBuffer struct { + onceZstd sync.Once + r *zstd.Decoder +} + +// NewConcurrentDecodeBuffer returns a buffer that can be used concurrently. +// NOTE: For Zstd compression a concurrency limit, equal to GOMAXPROCS is implied. +func NewConcurrentDecodeBuffer() DecodeBuffer { + return &concurrentDBuffer{} +} + +func (b *concurrentDBuffer) zstdDecBuf() *zstd.Decoder { + b.onceZstd.Do(func() { + // Without params this never returns error. + b.r, _ = zstd.NewReader(nil) + }) + return b.r +} + +func (b *concurrentDBuffer) get() []byte { + return nil +} + +func (b *concurrentDBuffer) set([]byte) {} diff --git a/util/compression/compression.go b/util/compression/compression.go new file mode 100644 index 0000000000..a1e9b7e530 --- /dev/null +++ b/util/compression/compression.go @@ -0,0 +1,122 @@ +// Copyright 2025 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 compression + +import ( + "errors" + "fmt" + + "github.com/golang/snappy" +) + +// Type represents a valid compression type supported by this package. +type Type = string + +const ( + // None represents no compression case. + // None is the default when Type is empty. + None Type = "none" + // Snappy represents snappy block format. + Snappy Type = "snappy" + // Zstd represents "speed" mode of Zstd (Zstandard https://facebook.github.io/zstd/). + // This is roughly equivalent to the default Zstandard mode (level 3). + Zstd Type = "zstd" +) + +func Types() []Type { return []Type{None, Snappy, Zstd} } + +// Encode returns the encoded form of src for the given compression type. +// For None or empty message the encoding is not attempted. +// +// The buf allows passing various buffer implementations that make encoding more +// efficient. See NewSyncEncodeBuffer and NewConcurrentEncodeBuffer for further +// details. For non-zstd compression types, it is valid to pass nil buf. +// +// Encode is concurrency-safe, however note the concurrency limits for the +// buffer of your choice. +func Encode(t Type, src []byte, buf EncodeBuffer) (ret []byte, err error) { + if len(src) == 0 || t == "" || t == None { + return src, nil + } + if t == Snappy { + // If MaxEncodedLen is less than 0 the record is too large to be compressed. + if snappy.MaxEncodedLen(len(src)) < 0 { + return src, fmt.Errorf("compression: Snappy can't encode such a large message: %v", len(src)) + } + var b []byte + if buf != nil { + b = buf.get() + defer func() { + buf.set(ret) + }() + } + + // The snappy library uses `len` to calculate if we need a new buffer. + // In order to allocate as few buffers as possible make the length + // equal to the capacity. + b = b[:cap(b)] + return snappy.Encode(b, src), nil + } + if t == Zstd { + if buf == nil { + return nil, errors.New("zstd requested but EncodeBuffer was not provided") + } + b := buf.get() + defer func() { + buf.set(ret) + }() + + return buf.zstdEncBuf().EncodeAll(src, b[:0]), nil + } + return nil, fmt.Errorf("unsupported compression type: %s", t) +} + +// Decode returns the decoded form of src for the given compression type. +// +// The buf allows passing various buffer implementations that make decoding more +// efficient. See NewSyncDecodeBuffer and NewConcurrentDecodeBuffer for further +// details. For non-zstd compression types, it is valid to pass nil buf. +// +// Decode is concurrency-safe, however note the concurrency limits for the +// buffer of your choice. +func Decode(t Type, src []byte, buf DecodeBuffer) (ret []byte, err error) { + if len(src) == 0 || t == "" || t == None { + return src, nil + } + if t == Snappy { + var b []byte + if buf != nil { + b = buf.get() + defer func() { + buf.set(ret) + }() + } + // The snappy library uses `len` to calculate if we need a new buffer. + // In order to allocate as few buffers as possible make the length + // equal to the capacity. + b = b[:cap(b)] + return snappy.Decode(b, src) + } + if t == Zstd { + if buf == nil { + return nil, errors.New("zstd requested but DecodeBuffer was not provided") + } + b := buf.get() + defer func() { + buf.set(ret) + }() + return buf.zstdDecBuf().DecodeAll(src, b[:0]) + } + return nil, fmt.Errorf("unsupported compression type: %s", t) +} diff --git a/util/compression/compression_test.go b/util/compression/compression_test.go new file mode 100644 index 0000000000..b0091d5dd0 --- /dev/null +++ b/util/compression/compression_test.go @@ -0,0 +1,193 @@ +// Copyright 2025 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 compression + +import ( + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +const compressible = `ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +fsfsdfsfddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa2 +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa12 +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa1 +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa121 +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa324 +ddddddddddsfpgjsdoadjgfpajdspfgjasfjapddddddddddaaaaaaaa145 +` + +func TestEncodeDecode(t *testing.T) { + for _, tcase := range []struct { + name string + + src string + types []Type + encBuf EncodeBuffer + decBuf DecodeBuffer + expectCompression bool + expectEncErr error + }{ + { + name: "empty src; no buffers", + types: Types(), + src: "", + expectCompression: false, + }, + { + name: "empty src; sync buffers", + types: Types(), + encBuf: NewSyncEncodeBuffer(), decBuf: NewSyncDecodeBuffer(), + src: "", + expectCompression: false, + }, + { + name: "empty src; concurrent buffers", + types: Types(), + encBuf: NewConcurrentEncodeBuffer(), decBuf: NewConcurrentDecodeBuffer(), + src: "", + expectCompression: false, + }, + { + name: "no buffers", + types: []Type{None}, + src: compressible, + expectCompression: false, + }, + { + name: "no buffers", + types: []Type{Snappy}, + src: compressible, + expectCompression: true, + }, + { + name: "no buffers", + types: []Type{Zstd}, + src: compressible, + expectEncErr: errors.New("zstd requested but EncodeBuffer was not provided"), + }, + { + name: "sync buffers", + types: []Type{None}, + encBuf: NewSyncEncodeBuffer(), decBuf: NewSyncDecodeBuffer(), + src: compressible, + expectCompression: false, + }, + { + name: "sync buffers", + types: Types()[1:], // All but none + encBuf: NewSyncEncodeBuffer(), decBuf: NewSyncDecodeBuffer(), + src: compressible, + expectCompression: true, + }, + { + name: "concurrent buffers", + types: []Type{None}, + encBuf: NewConcurrentEncodeBuffer(), decBuf: NewConcurrentDecodeBuffer(), + src: compressible, + expectCompression: false, + }, + { + name: "concurrent buffers", + types: Types()[1:], // All but none + encBuf: NewConcurrentEncodeBuffer(), decBuf: NewConcurrentDecodeBuffer(), + src: compressible, + expectCompression: true, + }, + } { + require.NotEmpty(t, tcase.types, "must specify at least one type") + for _, typ := range tcase.types { + t.Run(fmt.Sprintf("case=%v/type=%v", tcase.name, typ), func(t *testing.T) { + res, err := Encode(typ, []byte(tcase.src), tcase.encBuf) + if tcase.expectEncErr != nil { + require.ErrorContains(t, err, tcase.expectEncErr.Error()) + return + } + require.NoError(t, err) + if tcase.expectCompression { + require.Less(t, len(res), len(tcase.src)) + } + + // Decode back. + got, err := Decode(typ, res, tcase.decBuf) + require.NoError(t, err) + require.Equal(t, tcase.src, string(got)) + }) + } + } +} + +/* + export bench=encode-v1 && go test ./util/compression/... \ + -run '^$' -bench '^BenchmarkEncode' \ + -benchtime 5s -count 6 -cpu 2 -timeout 999m \ + | tee ${bench}.txt +*/ +func BenchmarkEncode(b *testing.B) { + for _, typ := range Types() { + b.Run(fmt.Sprintf("type=%v", typ), func(b *testing.B) { + var buf EncodeBuffer + compressible := []byte(compressible) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if buf == nil { + buf = NewSyncEncodeBuffer() + } + res, err := Encode(typ, compressible, buf) + require.NoError(b, err) + b.ReportMetric(float64(len(res)), "B") + } + }) + } +} + +/* + export bench=decode-v1 && go test ./util/compression/... \ + -run '^$' -bench '^BenchmarkDecode' \ + -benchtime 5s -count 6 -cpu 2 -timeout 999m \ + | tee ${bench}.txt +*/ +func BenchmarkDecode(b *testing.B) { + for _, typ := range Types() { + b.Run(fmt.Sprintf("type=%v", typ), func(b *testing.B) { + var buf DecodeBuffer + res, err := Encode(typ, []byte(compressible), NewConcurrentEncodeBuffer()) + require.NoError(b, err) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + if buf == nil { + buf = NewSyncDecodeBuffer() + } + _, err := Decode(typ, res, buf) + require.NoError(b, err) + } + }) + } +} diff --git a/util/httputil/compression_test.go b/util/httputil/compression_test.go index fd3f1f66d4..212a08fa93 100644 --- a/util/httputil/compression_test.go +++ b/util/httputil/compression_test.go @@ -40,7 +40,7 @@ func setup() func() { } func getCompressionHandlerFunc() CompressionHandler { - hf := func(w http.ResponseWriter, r *http.Request) { + hf := func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("Hello World!")) } diff --git a/util/logging/file.go b/util/logging/file.go index 27fdec2758..3f97b17f09 100644 --- a/util/logging/file.go +++ b/util/logging/file.go @@ -45,7 +45,7 @@ func NewJSONFileLogger(s string) (*JSONFileLogger, error) { return nil, fmt.Errorf("can't create json log file: %w", err) } - jsonFmt := &promslog.AllowedFormat{} + jsonFmt := promslog.NewFormat() _ = jsonFmt.Set("json") return &JSONFileLogger{ handler: promslog.New(&promslog.Config{Format: jsonFmt, Writer: f}).Handler(), diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 729c7bffc1..414f774c87 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -1022,6 +1022,7 @@ type ScrapePoolsDiscovery struct { type DroppedTarget struct { // Labels before any processing. DiscoveredLabels labels.Labels `json:"discoveredLabels"` + ScrapePool string `json:"scrapePool"` } // TargetDiscovery has all the active targets. @@ -1106,15 +1107,15 @@ func (api *API) scrapePools(r *http.Request) apiFuncResult { } func (api *API) targets(r *http.Request) apiFuncResult { - sortKeys := func(targets map[string][]*scrape.Target) ([]string, int) { + getSortedPools := func(targets map[string][]*scrape.Target) ([]string, int) { var n int - keys := make([]string, 0, len(targets)) - for k := range targets { - keys = append(keys, k) - n += len(targets[k]) + pools := make([]string, 0, len(targets)) + for p, t := range targets { + pools = append(pools, p) + n += len(t) } - slices.Sort(keys) - return keys, n + slices.Sort(pools) + return pools, n } scrapePool := r.URL.Query().Get("scrapePool") @@ -1126,14 +1127,14 @@ func (api *API) targets(r *http.Request) apiFuncResult { if showActive { targetsActive := api.targetRetriever(r.Context()).TargetsActive() - activeKeys, numTargets := sortKeys(targetsActive) + activePools, numTargets := getSortedPools(targetsActive) res.ActiveTargets = make([]*Target, 0, numTargets) - for _, key := range activeKeys { - if scrapePool != "" && key != scrapePool { + for _, pool := range activePools { + if scrapePool != "" && pool != scrapePool { continue } - for _, target := range targetsActive[key] { + for _, target := range targetsActive[pool] { lastErrStr := "" lastErr := target.LastError() if lastErr != nil { @@ -1145,7 +1146,7 @@ func (api *API) targets(r *http.Request) apiFuncResult { res.ActiveTargets = append(res.ActiveTargets, &Target{ DiscoveredLabels: target.DiscoveredLabels(builder), Labels: target.Labels(builder), - ScrapePool: key, + ScrapePool: pool, ScrapeURL: target.URL().String(), GlobalURL: globalURL.String(), LastError: func() string { @@ -1171,18 +1172,18 @@ func (api *API) targets(r *http.Request) apiFuncResult { } if showDropped { res.DroppedTargetCounts = api.targetRetriever(r.Context()).TargetsDroppedCounts() - } - if showDropped { + targetsDropped := api.targetRetriever(r.Context()).TargetsDropped() - droppedKeys, numTargets := sortKeys(targetsDropped) + droppedPools, numTargets := getSortedPools(targetsDropped) res.DroppedTargets = make([]*DroppedTarget, 0, numTargets) - for _, key := range droppedKeys { - if scrapePool != "" && key != scrapePool { + for _, pool := range droppedPools { + if scrapePool != "" && pool != scrapePool { continue } - for _, target := range targetsDropped[key] { + for _, target := range targetsDropped[pool] { res.DroppedTargets = append(res.DroppedTargets, &DroppedTarget{ DiscoveredLabels: target.DiscoveredLabels(builder), + ScrapePool: pool, }) } } diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index fcf9c2a243..79026037c6 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -314,7 +314,7 @@ func (m *rulesRetrieverMock) CreateRuleGroups() { Appendable: storage, Context: context.Background(), Logger: promslog.NewNopLogger(), - NotifyFunc: func(ctx context.Context, expr string, alerts ...*rules.Alert) {}, + NotifyFunc: func(_ context.Context, _ string, _ ...*rules.Alert) {}, } var r []rules.Rule @@ -480,15 +480,15 @@ func TestEndpoints(t *testing.T) { u, err := url.Parse(server.URL) require.NoError(t, err) - al := promslog.AllowedLevel{} + al := promslog.NewLevel() require.NoError(t, al.Set("debug")) - af := promslog.AllowedFormat{} + af := promslog.NewFormat() require.NoError(t, af.Set("logfmt")) promslogConfig := promslog.Config{ - Level: &al, - Format: &af, + Level: al, + Format: af, } dbDir := t.TempDir() @@ -951,7 +951,7 @@ func TestStats(t *testing.T) { }, { name: "custom handler with known value", - renderer: func(ctx context.Context, s *stats.Statistics, p string) stats.QueryStats { + renderer: func(_ context.Context, _ *stats.Statistics, p string) stats.QueryStats { if p == "known" { return testStats{"Custom Value"} } @@ -1117,7 +1117,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E metadata []targetMetadata exemplars []exemplar.QueryResult zeroFunc func(interface{}) - nameValidationScheme model.ValidationScheme } rulesZeroFunc := func(i interface{}) { @@ -1767,6 +1766,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E "__scrape_interval__", "30s", "__scrape_timeout__", "15s", ), + ScrapePool: "blackbox", }, }, DroppedTargetCounts: map[string]int{"blackbox": 1}, @@ -1816,6 +1816,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E "__scrape_interval__", "30s", "__scrape_timeout__", "15s", ), + ScrapePool: "blackbox", }, }, DroppedTargetCounts: map[string]int{"blackbox": 1}, @@ -1875,6 +1876,7 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E "__scrape_interval__", "30s", "__scrape_timeout__", "15s", ), + ScrapePool: "blackbox", }, }, DroppedTargetCounts: map[string]int{"blackbox": 1}, @@ -3244,14 +3246,13 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E "boo", }, }, - // Bad name parameter for legacy validation. + // Bad name parameter { endpoint: api.labelValues, params: map[string]string{ - "name": "host.name", + "name": "host.name\xff", }, - nameValidationScheme: model.LegacyValidation, - errType: errorBadData, + errType: errorBadData, }, // Valid utf8 name parameter for utf8 validation. { @@ -3259,7 +3260,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E params: map[string]string{ "name": "host.name", }, - nameValidationScheme: model.UTF8Validation, response: []string{ "localhost", }, @@ -3270,7 +3270,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E params: map[string]string{ "name": "U__junk_0a__7b__7d__2c__3d_:_20__20_chars", }, - nameValidationScheme: model.UTF8Validation, response: []string{ "bar", }, @@ -3703,8 +3702,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E ctx = route.WithParam(ctx, p, v) } - model.NameValidationScheme = test.nameValidationScheme - req, err := request(method, test.query) require.NoError(t, err) @@ -4127,7 +4124,7 @@ func TestRespondSuccess_DefaultCodecCannotEncodeResponse(t *testing.T) { } func TestRespondError(t *testing.T) { - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { api := API{} api.respondError(w, &apiError{errorTimeout, errors.New("message")}, "test") })) @@ -4723,11 +4720,11 @@ type fakeEngine struct { query fakeQuery } -func (e *fakeEngine) NewInstantQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, ts time.Time) (promql.Query, error) { +func (e *fakeEngine) NewInstantQuery(_ context.Context, _ storage.Queryable, _ promql.QueryOpts, _ string, _ 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) { +func (e *fakeEngine) NewRangeQuery(_ context.Context, _ storage.Queryable, _ promql.QueryOpts, _ string, _, _ time.Time, _ time.Duration) (promql.Query, error) { return &e.query, nil } diff --git a/web/api/v1/errors_test.go b/web/api/v1/errors_test.go index a3fb49c8a6..56ef3ce2ab 100644 --- a/web/api/v1/errors_test.go +++ b/web/api/v1/errors_test.go @@ -159,15 +159,15 @@ type errorTestQueryable struct { err error } -func (t errorTestQueryable) ExemplarQuerier(ctx context.Context) (storage.ExemplarQuerier, error) { +func (t errorTestQueryable) ExemplarQuerier(_ context.Context) (storage.ExemplarQuerier, error) { return nil, t.err } -func (t errorTestQueryable) ChunkQuerier(mint, maxt int64) (storage.ChunkQuerier, error) { +func (t errorTestQueryable) ChunkQuerier(_, _ int64) (storage.ChunkQuerier, error) { return nil, t.err } -func (t errorTestQueryable) Querier(mint, maxt int64) (storage.Querier, error) { +func (t errorTestQueryable) Querier(_, _ int64) (storage.Querier, error) { if t.q != nil { return t.q, nil } @@ -191,7 +191,7 @@ func (t errorTestQuerier) Close() error { return nil } -func (t errorTestQuerier) Select(_ context.Context, sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet { +func (t errorTestQuerier) Select(_ context.Context, _ bool, _ *storage.SelectHints, _ ...*labels.Matcher) storage.SeriesSet { if t.s != nil { return t.s } diff --git a/web/ui/mantine-ui/package.json b/web/ui/mantine-ui/package.json index 54546c76ad..5c3957c10f 100644 --- a/web/ui/mantine-ui/package.json +++ b/web/ui/mantine-ui/package.json @@ -1,7 +1,7 @@ { "name": "@prometheus-io/mantine-ui", "private": true, - "version": "0.301.0", + "version": "0.302.1", "type": "module", "scripts": { "start": "vite", @@ -28,12 +28,12 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.301.0", + "@prometheus-io/codemirror-promql": "0.302.1", "@reduxjs/toolkit": "^2.5.0", "@tabler/icons-react": "^3.28.1", - "@tanstack/react-query": "^5.62.11", + "@tanstack/react-query": "^5.67.1", "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.1.0", + "@testing-library/react": "^16.2.0", "@types/lodash": "^4.17.13", "@types/sanitize-html": "^2.13.0", "@uiw/react-codemirror": "^4.23.7", @@ -53,21 +53,21 @@ "devDependencies": { "@eslint/compat": "^1.2.4", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.17.0", + "@eslint/js": "^9.21.0", "@types/react": "^19.0.6", "@types/react-dom": "^19.0.0", "@typescript-eslint/eslint-plugin": "^8.20.0", - "@typescript-eslint/parser": "^8.20.0", + "@typescript-eslint/parser": "^8.25.0", "@vitejs/plugin-react": "^4.3.4", "eslint": "^9.18.0", "eslint-plugin-react-hooks": "^5.1.0", - "eslint-plugin-react-refresh": "^0.4.16", + "eslint-plugin-react-refresh": "^0.4.19", "globals": "^15.14.0", "jsdom": "^25.0.1", "postcss": "^8.4.47", "postcss-preset-mantine": "^1.17.0", "postcss-simple-vars": "^7.0.1", - "vite": "^6.0.7", - "vitest": "^2.1.8" + "vite": "^6.2.1", + "vitest": "^3.0.8" } } diff --git a/web/ui/mantine-ui/src/api/responseTypes/targets.ts b/web/ui/mantine-ui/src/api/responseTypes/targets.ts index cc0e891f05..c054247284 100644 --- a/web/ui/mantine-ui/src/api/responseTypes/targets.ts +++ b/web/ui/mantine-ui/src/api/responseTypes/targets.ts @@ -18,6 +18,7 @@ export type Target = { export interface DroppedTarget { discoveredLabels: Labels; + scrapePool: string; } // Result type for /api/v1/targets endpoint. diff --git a/web/ui/mantine-ui/src/components/RuleDefinition.tsx b/web/ui/mantine-ui/src/components/RuleDefinition.tsx index f3c4c88485..f428df46a8 100644 --- a/web/ui/mantine-ui/src/components/RuleDefinition.tsx +++ b/web/ui/mantine-ui/src/components/RuleDefinition.tsx @@ -85,7 +85,7 @@ const RuleDefinition: FC<{ rule: Rule }> = ({ rule }) => { styles={{ label: { textTransform: "none" } }} leftSection={} > - keep_firing_for: {formatPrometheusDuration(rule.duration * 1000)} + keep_firing_for: {formatPrometheusDuration(rule.keepFiringFor * 1000)} )} diff --git a/web/ui/mantine-ui/src/pages/query/SeriesName.tsx b/web/ui/mantine-ui/src/pages/query/SeriesName.tsx index d03b530f03..ab3edb081b 100644 --- a/web/ui/mantine-ui/src/pages/query/SeriesName.tsx +++ b/web/ui/mantine-ui/src/pages/query/SeriesName.tsx @@ -3,7 +3,6 @@ import React, { FC } from "react"; import { formatSeries } from "../../lib/formatSeries"; import classes from "./SeriesName.module.css"; import { escapeString } from "../../lib/escapeString"; -import { useClipboard } from "@mantine/hooks"; import { notifications } from "@mantine/notifications"; import { maybeQuoteLabelName, @@ -15,9 +14,34 @@ interface SeriesNameProps { format: boolean; } -const SeriesName: FC = ({ labels, format }) => { - const clipboard = useClipboard(); +const copyMatcher = (matcher: string) => { + if ("clipboard" in navigator) { + navigator.clipboard + .writeText(matcher) + .then(() => + notifications.show({ + title: "Copied matcher!", + message: `Label matcher ${matcher} copied to clipboard`, + }) + ) + .catch(() => + notifications.show({ + color: "red", + title: "Failed to copy matcher!", + message: "Label matcher could not be copied to clipboard.", + }) + ); + } else { + notifications.show({ + color: "red", + title: "Failed to copy matcher!", + message: + "Clipboard API is not supported in this context (most likely due to non-HTTPS origin).", + }); + } +}; +const SeriesName: FC = ({ labels, format }) => { const renderFormatted = (): React.ReactElement => { const metricExtendedCharset = labels && metricContainsExtendedCharset(labels.__name__ || ""); @@ -49,15 +73,8 @@ const SeriesName: FC = ({ labels, format }) => { {!first && ", "} { - const text = e.currentTarget.innerText; - clipboard.copy(text); - notifications.show({ - title: "Copied matcher!", - message: `Label matcher ${text} copied to clipboard`, - }); - }} - title="Click to copy label matcher" + onDoubleClick={(e) => copyMatcher(e.currentTarget.innerText)} + title="Double click to copy label matcher" > {maybeQuoteLabelName(label)} diff --git a/web/ui/mantine-ui/src/pages/query/UPlotChart.tsx b/web/ui/mantine-ui/src/pages/query/UPlotChart.tsx index f105cb54d6..b3b2d75578 100644 --- a/web/ui/mantine-ui/src/pages/query/UPlotChart.tsx +++ b/web/ui/mantine-ui/src/pages/query/UPlotChart.tsx @@ -5,7 +5,7 @@ import { GraphDisplayMode } from "../../state/queryPageSlice"; import uPlot from "uplot"; import UplotReact from "uplot-react"; import { useSettings } from "../../state/settingsSlice"; -import { useComputedColorScheme } from "@mantine/core"; +import { useComputedColorScheme, Text } from "@mantine/core"; import "uplot/dist/uPlot.min.css"; import "./uplot.css"; @@ -88,11 +88,18 @@ const UPlotChart: FC = ({ } return ( - + <> + + + Click: show single series,{" "} + {navigator.userAgent.includes("Mac") ? "⌘" : "Ctrl"} + click: hide + single series + + ); }; diff --git a/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts b/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts index ac77fee596..3249afd454 100644 --- a/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts +++ b/web/ui/mantine-ui/src/pages/query/uPlotChartHelpers.ts @@ -313,6 +313,7 @@ export const getUPlotOptions = ( legend: { show: true, live: false, + isolate: true, markers: { fill: ( _u: uPlot, @@ -339,8 +340,8 @@ export const getUPlotOptions = ( stroke: light ? "#00000010" : "#ffffff20", }, grid: { - show: false, - stroke: light ? "#eee" : "#333", + show: true, + stroke: light ? "#00000010" : "#ffffff20", width: 2, dash: [], }, diff --git a/web/ui/mantine-ui/src/pages/service-discovery/ServiceDiscoveryPoolsList.tsx b/web/ui/mantine-ui/src/pages/service-discovery/ServiceDiscoveryPoolsList.tsx index 798783da2f..6aec62fcc5 100644 --- a/web/ui/mantine-ui/src/pages/service-discovery/ServiceDiscoveryPoolsList.tsx +++ b/web/ui/mantine-ui/src/pages/service-discovery/ServiceDiscoveryPoolsList.tsx @@ -109,8 +109,7 @@ const buildPoolsData = ( } for (const target of droppedTargets) { - const { job: poolName } = target.discoveredLabels; - const pool = pools[poolName]; + const pool = pools[target.scrapePool]; if (!pool) { // TODO: Should we do better here? throw new Error( @@ -131,7 +130,7 @@ const buildPoolsData = ( .map((value) => value.original); for (const target of filteredDroppedTargets) { - pools[target.discoveredLabels.job].targets.push({ + pools[target.scrapePool].targets.push({ discoveredLabels: target.discoveredLabels, isDropped: true, labels: {}, diff --git a/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx b/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx index 1e29c568e1..80eb58540c 100644 --- a/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx +++ b/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx @@ -54,7 +54,7 @@ type ScrapePools = { }; const poolPanelHealthClass = (pool: ScrapePool) => - pool.count > 1 && pool.downCount === pool.count + pool.count > 0 && pool.downCount === pool.count ? panelClasses.panelHealthErr : pool.downCount >= 1 ? panelClasses.panelHealthWarn diff --git a/web/ui/mantine-ui/src/promql/tools/go.mod b/web/ui/mantine-ui/src/promql/tools/go.mod index 40a7876a0a..0d0b46e547 100644 --- a/web/ui/mantine-ui/src/promql/tools/go.mod +++ b/web/ui/mantine-ui/src/promql/tools/go.mod @@ -1,6 +1,6 @@ module github.com/prometheus/prometheus/web/ui/mantine-ui/src/promql/tools -go 1.22.7 +go 1.23.0 require ( github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc diff --git a/web/ui/module/codemirror-promql/package.json b/web/ui/module/codemirror-promql/package.json index 270fa16b29..75931bc76b 100644 --- a/web/ui/module/codemirror-promql/package.json +++ b/web/ui/module/codemirror-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/codemirror-promql", - "version": "0.301.0", + "version": "0.302.1", "description": "a CodeMirror mode for the PromQL language", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md", "dependencies": { - "@prometheus-io/lezer-promql": "0.301.0", + "@prometheus-io/lezer-promql": "0.302.1", "lru-cache": "^11.0.2" }, "devDependencies": { @@ -41,7 +41,7 @@ "@lezer/common": "^1.2.3", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.4.2", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.3", "isomorphic-fetch": "^3.0.0", "nock": "^13.5.6" }, diff --git a/web/ui/module/lezer-promql/package.json b/web/ui/module/lezer-promql/package.json index 270e57797f..b4f1a793a6 100644 --- a/web/ui/module/lezer-promql/package.json +++ b/web/ui/module/lezer-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/lezer-promql", - "version": "0.301.0", + "version": "0.302.1", "description": "lezer-based PromQL grammar", "main": "dist/index.cjs", "type": "module", diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index dd251c660e..9cba7f7336 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "prometheus-io", - "version": "0.301.0", + "version": "0.302.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prometheus-io", - "version": "0.301.0", + "version": "0.302.1", "workspaces": [ "mantine-ui", "module/*" @@ -14,17 +14,17 @@ "devDependencies": { "@types/jest": "^29.5.14", "@typescript-eslint/eslint-plugin": "^8.20.0", - "@typescript-eslint/parser": "^8.20.0", - "eslint-config-prettier": "^9.1.0", + "@typescript-eslint/parser": "^8.25.0", + "eslint-config-prettier": "^10.1.1", "prettier": "^3.4.2", "ts-jest": "^29.2.2", "typescript": "^5.7.2", - "vite": "^6.0.7" + "vite": "^6.2.1" } }, "mantine-ui": { "name": "@prometheus-io/mantine-ui", - "version": "0.301.0", + "version": "0.302.1", "dependencies": { "@codemirror/autocomplete": "^6.18.4", "@codemirror/language": "^6.10.8", @@ -42,12 +42,12 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.301.0", + "@prometheus-io/codemirror-promql": "0.302.1", "@reduxjs/toolkit": "^2.5.0", "@tabler/icons-react": "^3.28.1", - "@tanstack/react-query": "^5.62.11", + "@tanstack/react-query": "^5.67.1", "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.1.0", + "@testing-library/react": "^16.2.0", "@types/lodash": "^4.17.13", "@types/sanitize-html": "^2.13.0", "@uiw/react-codemirror": "^4.23.7", @@ -67,22 +67,22 @@ "devDependencies": { "@eslint/compat": "^1.2.4", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.17.0", + "@eslint/js": "^9.21.0", "@types/react": "^19.0.6", "@types/react-dom": "^19.0.0", "@typescript-eslint/eslint-plugin": "^8.20.0", - "@typescript-eslint/parser": "^8.20.0", + "@typescript-eslint/parser": "^8.25.0", "@vitejs/plugin-react": "^4.3.4", "eslint": "^9.18.0", "eslint-plugin-react-hooks": "^5.1.0", - "eslint-plugin-react-refresh": "^0.4.16", + "eslint-plugin-react-refresh": "^0.4.19", "globals": "^15.14.0", "jsdom": "^25.0.1", "postcss": "^8.4.47", "postcss-preset-mantine": "^1.17.0", "postcss-simple-vars": "^7.0.1", - "vite": "^6.0.7", - "vitest": "^2.1.8" + "vite": "^6.2.1", + "vitest": "^3.0.8" } }, "mantine-ui/node_modules/eslint": { @@ -144,12 +144,22 @@ } } }, + "mantine-ui/node_modules/eslint/node_modules/@eslint/js": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", + "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "module/codemirror-promql": { "name": "@prometheus-io/codemirror-promql", - "version": "0.301.0", + "version": "0.302.1", "license": "Apache-2.0", "dependencies": { - "@prometheus-io/lezer-promql": "0.301.0", + "@prometheus-io/lezer-promql": "0.302.1", "lru-cache": "^11.0.2" }, "devDependencies": { @@ -161,7 +171,7 @@ "@lezer/common": "^1.2.3", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.4.2", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.3", "isomorphic-fetch": "^3.0.0", "nock": "^13.5.6" }, @@ -179,7 +189,7 @@ }, "module/lezer-promql": { "name": "@prometheus-io/lezer-promql", - "version": "0.301.0", + "version": "0.302.1", "license": "Apache-2.0", "devDependencies": { "@lezer/generator": "^1.7.2", @@ -867,13 +877,14 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -883,13 +894,14 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -899,13 +911,14 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -915,13 +928,14 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -931,13 +945,14 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -947,13 +962,14 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -963,13 +979,14 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -979,13 +996,14 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -995,13 +1013,14 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1011,13 +1030,14 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1027,13 +1047,14 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1043,13 +1064,14 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1059,13 +1081,14 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1075,13 +1098,14 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1091,13 +1115,14 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1107,13 +1132,14 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1123,13 +1149,14 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -1139,13 +1166,14 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -1155,13 +1183,14 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -1171,13 +1200,14 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -1187,13 +1217,14 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -1203,13 +1234,14 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -1219,13 +1251,14 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1235,13 +1268,14 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1251,13 +1285,14 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1385,10 +1420,11 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", + "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -2355,234 +2391,266 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", - "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.9.tgz", + "integrity": "sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", - "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.9.tgz", + "integrity": "sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz", - "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz", + "integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", - "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz", + "integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", - "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.9.tgz", + "integrity": "sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", - "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.9.tgz", + "integrity": "sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", - "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.9.tgz", + "integrity": "sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", - "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.9.tgz", + "integrity": "sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", - "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz", + "integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", - "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz", + "integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.9.tgz", + "integrity": "sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", - "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.9.tgz", + "integrity": "sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", - "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.9.tgz", + "integrity": "sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", - "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.9.tgz", + "integrity": "sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", - "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz", + "integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", - "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz", + "integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", - "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz", + "integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", - "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.9.tgz", + "integrity": "sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", - "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz", + "integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -2642,20 +2710,22 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.62.9", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.62.9.tgz", - "integrity": "sha512-lwePd8hNYhyQ4nM/iRQ+Wz2cDtspGeZZHFZmCzHJ7mfKXt+9S301fULiY2IR2byJYY6Z03T427E5PoVfMexHjw==", + "version": "5.67.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.67.1.tgz", + "integrity": "sha512-AkFmuukVejyqVIjEQoFhLb3q+xHl7JG8G9cANWTMe3s8iKzD9j1VBSYXgCjy6vm6xM8cUCR9zP2yqWxY9pTWOA==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/react-query": { - "version": "5.62.11", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.62.11.tgz", - "integrity": "sha512-Xb1nw0cYMdtFmwkvH9+y5yYFhXvLRCnXoqlzSw7UkqtCVFq3cG8q+rHZ2Yz1XrC+/ysUaTqbLKJqk95mCgC1oQ==", + "version": "5.67.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.67.1.tgz", + "integrity": "sha512-fH5u4JLwB6A+wLFdi8wWBWAYoJV5deYif2OveJ26ktAWjU499uvVFS1wPWnyEyq5LvZX1MZInvv9QRaIZANRaQ==", + "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.62.9" + "@tanstack/query-core": "5.67.1" }, "funding": { "type": "github", @@ -2724,9 +2794,9 @@ "license": "MIT" }, "node_modules/@testing-library/react": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.1.0.tgz", - "integrity": "sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.2.0.tgz", + "integrity": "sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" @@ -3012,15 +3082,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz", - "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.25.0.tgz", + "integrity": "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/scope-manager": "8.25.0", + "@typescript-eslint/types": "8.25.0", + "@typescript-eslint/typescript-estree": "8.25.0", + "@typescript-eslint/visitor-keys": "8.25.0", "debug": "^4.3.4" }, "engines": { @@ -3035,6 +3106,109 @@ "typescript": ">=4.8.4 <5.8.0" } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.25.0.tgz", + "integrity": "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.25.0", + "@typescript-eslint/visitor-keys": "8.25.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.25.0.tgz", + "integrity": "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.25.0.tgz", + "integrity": "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.25.0", + "@typescript-eslint/visitor-keys": "8.25.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.25.0.tgz", + "integrity": "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.25.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/scope-manager": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", @@ -3264,67 +3438,94 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.8.tgz", - "integrity": "sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.8.tgz", + "integrity": "sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.0.8", + "@vitest/utils": "3.0.8", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.8.tgz", + "integrity": "sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.8", - "@vitest/utils": "2.1.8", - "chai": "^5.1.2", - "tinyrainbow": "^1.2.0" + "@vitest/spy": "3.0.8", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" }, "funding": { "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", - "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.8.tgz", + "integrity": "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^1.2.0" + "tinyrainbow": "^2.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.8.tgz", - "integrity": "sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.8.tgz", + "integrity": "sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.8", - "pathe": "^1.1.2" + "@vitest/utils": "3.0.8", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.8.tgz", - "integrity": "sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.8.tgz", + "integrity": "sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.8", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" + "@vitest/pretty-format": "3.0.8", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.8.tgz", - "integrity": "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.8.tgz", + "integrity": "sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3335,15 +3536,15 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz", - "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.8.tgz", + "integrity": "sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.8", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" + "@vitest/pretty-format": "3.0.8", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -3803,9 +4004,9 @@ ] }, "node_modules/chai": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", - "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", "dev": true, "license": "MIT", "dependencies": { @@ -4358,18 +4559,19 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", "dev": true, "license": "MIT" }, "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -4377,31 +4579,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/escalade": { @@ -4484,9 +4686,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", + "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", "dev": true, "license": "MIT", "bin": { @@ -4497,9 +4699,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "license": "MIT", "dependencies": { @@ -4540,9 +4742,9 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.16.tgz", - "integrity": "sha512-slterMlxAhov/DZO8NScf6mEeMBBXodFUolijDvrtTxyezyLoTQaa73FyYus/VbTdftd8wBgBxPMRk3poleXNQ==", + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.19.tgz", + "integrity": "sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6823,9 +7025,9 @@ } }, "node_modules/loupe": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", - "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, @@ -6849,9 +7051,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.15", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.15.tgz", - "integrity": "sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, "license": "MIT", "dependencies": { @@ -7307,9 +7509,9 @@ "license": "MIT" }, "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, @@ -7428,9 +7630,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -7447,7 +7649,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -8084,10 +8286,11 @@ } }, "node_modules/rollup": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", - "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", + "version": "4.34.9", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.9.tgz", + "integrity": "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "1.0.6" }, @@ -8099,24 +8302,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.27.4", - "@rollup/rollup-android-arm64": "4.27.4", - "@rollup/rollup-darwin-arm64": "4.27.4", - "@rollup/rollup-darwin-x64": "4.27.4", - "@rollup/rollup-freebsd-arm64": "4.27.4", - "@rollup/rollup-freebsd-x64": "4.27.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", - "@rollup/rollup-linux-arm-musleabihf": "4.27.4", - "@rollup/rollup-linux-arm64-gnu": "4.27.4", - "@rollup/rollup-linux-arm64-musl": "4.27.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", - "@rollup/rollup-linux-riscv64-gnu": "4.27.4", - "@rollup/rollup-linux-s390x-gnu": "4.27.4", - "@rollup/rollup-linux-x64-gnu": "4.27.4", - "@rollup/rollup-linux-x64-musl": "4.27.4", - "@rollup/rollup-win32-arm64-msvc": "4.27.4", - "@rollup/rollup-win32-ia32-msvc": "4.27.4", - "@rollup/rollup-win32-x64-msvc": "4.27.4", + "@rollup/rollup-android-arm-eabi": "4.34.9", + "@rollup/rollup-android-arm64": "4.34.9", + "@rollup/rollup-darwin-arm64": "4.34.9", + "@rollup/rollup-darwin-x64": "4.34.9", + "@rollup/rollup-freebsd-arm64": "4.34.9", + "@rollup/rollup-freebsd-x64": "4.34.9", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.9", + "@rollup/rollup-linux-arm-musleabihf": "4.34.9", + "@rollup/rollup-linux-arm64-gnu": "4.34.9", + "@rollup/rollup-linux-arm64-musl": "4.34.9", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.9", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.9", + "@rollup/rollup-linux-riscv64-gnu": "4.34.9", + "@rollup/rollup-linux-s390x-gnu": "4.34.9", + "@rollup/rollup-linux-x64-gnu": "4.34.9", + "@rollup/rollup-linux-x64-musl": "4.34.9", + "@rollup/rollup-win32-arm64-msvc": "4.34.9", + "@rollup/rollup-win32-ia32-msvc": "4.34.9", + "@rollup/rollup-win32-x64-msvc": "4.34.9", "fsevents": "~2.3.2" } }, @@ -8554,16 +8758,16 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", - "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, "license": "MIT" }, "node_modules/tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", "dev": true, "license": "MIT", "engines": { @@ -8571,9 +8775,9 @@ } }, "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", "engines": { @@ -8655,9 +8859,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, "license": "MIT", "engines": { @@ -8980,14 +9184,15 @@ } }, "node_modules/vite": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.7.tgz", - "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.1.tgz", + "integrity": "sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "esbuild": "^0.25.0", + "postcss": "^8.5.3", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" @@ -9051,1097 +9256,94 @@ } }, "node_modules/vite-node": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.8.tgz", - "integrity": "sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.8.tgz", + "integrity": "sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.7", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", - "vite": "^5.0.0" + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], + "node_modules/vitest": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.8.tgz", + "integrity": "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@vitest/expect": "3.0.8", + "@vitest/mocker": "3.0.8", + "@vitest/pretty-format": "^3.0.8", + "@vitest/runner": "3.0.8", + "@vitest/snapshot": "3.0.8", + "@vitest/spy": "3.0.8", + "@vitest/utils": "3.0.8", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.1.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.0.8", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite-node/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vite-node/node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vitest": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.8.tgz", - "integrity": "sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.8", - "@vitest/mocker": "2.1.8", - "@vitest/pretty-format": "^2.1.8", - "@vitest/runner": "2.1.8", - "@vitest/snapshot": "2.1.8", - "@vitest/spy": "2.1.8", - "@vitest/utils": "2.1.8", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.8", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.8", - "@vitest/ui": "2.1.8", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vitest/node_modules/@vitest/mocker": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.8.tgz", - "integrity": "sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "2.1.8", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/vitest/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vitest/node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.0.8", + "@vitest/ui": "3.0.8", + "happy-dom": "*", + "jsdom": "*" }, "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { + "@edge-runtime/vm": { "optional": true }, - "lightningcss": { + "@types/debug": { "optional": true }, - "sass": { + "@types/node": { "optional": true }, - "sass-embedded": { + "@vitest/browser": { "optional": true }, - "stylus": { + "@vitest/ui": { "optional": true }, - "sugarss": { + "happy-dom": { "optional": true }, - "terser": { + "jsdom": { "optional": true } } diff --git a/web/ui/package.json b/web/ui/package.json index 8539057eeb..15575727bf 100644 --- a/web/ui/package.json +++ b/web/ui/package.json @@ -1,7 +1,7 @@ { "name": "prometheus-io", "description": "Monorepo for the Prometheus UI", - "version": "0.301.0", + "version": "0.302.1", "private": true, "scripts": { "build": "bash build_ui.sh --all", @@ -17,11 +17,11 @@ "devDependencies": { "@types/jest": "^29.5.14", "@typescript-eslint/eslint-plugin": "^8.20.0", - "@typescript-eslint/parser": "^8.20.0", - "eslint-config-prettier": "^9.1.0", + "@typescript-eslint/parser": "^8.25.0", + "eslint-config-prettier": "^10.1.1", "prettier": "^3.4.2", "ts-jest": "^29.2.2", "typescript": "^5.7.2", - "vite": "^6.0.7" + "vite": "^6.2.1" } } diff --git a/web/ui/react-app/package-lock.json b/web/ui/react-app/package-lock.json index 6f5eb5aff2..cddcb28d39 100644 --- a/web/ui/react-app/package-lock.json +++ b/web/ui/react-app/package-lock.json @@ -8,13 +8,13 @@ "name": "@prometheus-io/app", "version": "0.300.1", "dependencies": { - "@codemirror/autocomplete": "^6.18.4", - "@codemirror/commands": "^6.7.1", + "@codemirror/autocomplete": "^6.18.6", + "@codemirror/commands": "^6.8.0", "@codemirror/language": "^6.10.8", "@codemirror/lint": "^6.8.4", - "@codemirror/search": "^6.5.8", - "@codemirror/state": "^6.3.3", - "@codemirror/view": "^6.36.1", + "@codemirror/search": "^6.5.10", + "@codemirror/state": "^6.5.2", + "@codemirror/view": "^6.36.3", "@forevolve/bootstrap-dark": "^4.0.2", "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-solid-svg-icons": "6.7.2", @@ -24,7 +24,7 @@ "@lezer/lr": "^1.4.2", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.300.1", + "@prometheus-io/codemirror-promql": "0.302.1", "bootstrap": "^4.6.2", "css.escape": "^1.5.1", "downshift": "^9.0.8", @@ -32,7 +32,7 @@ "jquery": "^3.7.1", "jquery.flot.tooltip": "^0.9.0", "moment": "^2.30.1", - "moment-timezone": "^0.5.46", + "moment-timezone": "^0.5.47", "popper.js": "^1.14.3", "react": "^17.0.2", "react-copy-to-clipboard": "^5.1.0", @@ -43,7 +43,7 @@ "react-test-renderer": "^17.0.2", "reactstrap": "^8.10.1", "sanitize-html": "^2.14.0", - "sass": "1.83.0", + "sass": "1.85.1", "tempusdominus-bootstrap-4": "^5.39.2", "tempusdominus-core": "^5.19.3" }, @@ -60,20 +60,20 @@ "@types/react-dom": "^17.0.25", "@types/react-router-dom": "^5.3.3", "@types/sanitize-html": "^2.13.0", - "@types/sinon": "^17.0.3", + "@types/sinon": "^17.0.4", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.2", - "eslint-config-prettier": "^9.1.0", + "eslint-config-prettier": "^10.1.1", "eslint-config-react-app": "^7.0.1", - "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-prettier": "^5.2.3", "jest-canvas-mock": "^2.5.2", "jest-fetch-mock": "^3.0.3", "mutationobserver-shim": "^0.3.7", - "prettier": "^3.0.0", + "prettier": "^3.5.2", "react-scripts": "^5.0.1", "sinon": "^19.0.2", - "ts-jest": "^29.2.5" + "ts-jest": "^29.2.6" }, "optionalDependencies": { "fsevents": "^2.3.3" @@ -2257,9 +2257,10 @@ "dev": true }, "node_modules/@codemirror/autocomplete": { - "version": "6.18.4", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz", - "integrity": "sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==", + "version": "6.18.6", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz", + "integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==", + "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -2268,9 +2269,9 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.7.1.tgz", - "integrity": "sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.0.tgz", + "integrity": "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -2304,9 +2305,9 @@ } }, "node_modules/@codemirror/search": { - "version": "6.5.8", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz", - "integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==", + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.10.tgz", + "integrity": "sha512-RMdPdmsrUf53pb2VwflKGHEe1XVM07hI7vV2ntgw1dmqhimpatSJKva4VA9h4TLUDOD4EIF02201oZurpnEFsg==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", @@ -2315,18 +2316,19 @@ } }, "node_modules/@codemirror/state": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.0.tgz", - "integrity": "sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", + "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", "license": "MIT", "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "node_modules/@codemirror/view": { - "version": "6.36.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.1.tgz", - "integrity": "sha512-miD1nyT4m4uopZaDdO2uXU/LLHliKNYL9kB1C1wJHrunHLm/rpkb5QVSokqgw9hFqEZakrdlb/VGWX8aYZTslQ==", + "version": "6.36.3", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.3.tgz", + "integrity": "sha512-N2bilM47QWC8Hnx0rMdDxO2x2ImJ1FvZWXubwKgjeoOrWwEiFrtpA7SFHcuZ+o2Ze2VzbkgbzWVj4+V18LVkeg==", + "license": "MIT", "dependencies": { "@codemirror/state": "^6.5.0", "style-mod": "^4.1.0", @@ -4671,12 +4673,13 @@ } }, "node_modules/@prometheus-io/codemirror-promql": { - "version": "0.300.1", - "resolved": "https://registry.npmjs.org/@prometheus-io/codemirror-promql/-/codemirror-promql-0.300.1.tgz", - "integrity": "sha512-sr8cDrPgNtZfeRz0s1HPgokkwELcND21rUkwlP7zYmu9U51HrXIB8DD1c9pCfDmq8ifa5WB2CAYXQYdLDCBNww==", + "version": "0.302.1", + "resolved": "https://registry.npmjs.org/@prometheus-io/codemirror-promql/-/codemirror-promql-0.302.1.tgz", + "integrity": "sha512-u2uZbVKwz7UeJarE1LcOzbxiocetpgoqZ3ngs9HKOHG48i2dFUEXDfn4zs4dhuClQ/NixirmdGhSYq3l6b+9Yw==", + "license": "Apache-2.0", "dependencies": { - "@prometheus-io/lezer-promql": "0.300.1", - "lru-cache": "^11.0.1" + "@prometheus-io/lezer-promql": "0.302.1", + "lru-cache": "^11.0.2" }, "engines": { "node": ">=12.0.0" @@ -4691,9 +4694,10 @@ } }, "node_modules/@prometheus-io/lezer-promql": { - "version": "0.300.1", - "resolved": "https://registry.npmjs.org/@prometheus-io/lezer-promql/-/lezer-promql-0.300.1.tgz", - "integrity": "sha512-5Xw6AiRnFiat42p39djMwr9BGYUVa8MMElUSVGQ8+y9Okmkw09eVil7NPhzzFtIJ1BSZ6jZhlUNXJ/LbnYEJ5Q==", + "version": "0.302.1", + "resolved": "https://registry.npmjs.org/@prometheus-io/lezer-promql/-/lezer-promql-0.302.1.tgz", + "integrity": "sha512-pxaWbzqwRXe+/wS6VWLcMSD23bgct56GQccqTWZIu9atmwTCMHWRBjGjCaHa5OpIoQYLAgKKClIFkVZdcW00Mw==", + "license": "Apache-2.0", "peerDependencies": { "@lezer/highlight": "^1.1.2", "@lezer/lr": "^1.2.3" @@ -5591,9 +5595,9 @@ } }, "node_modules/@types/sinon": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", - "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.4.tgz", + "integrity": "sha512-RHnIrhfPO3+tJT0s7cFaXGZvsL4bbR3/k7z3P312qMS4JaS2Tk+KiwiLx1S0rQ56ERj00u1/BtdyVd0FY+Pdew==", "dev": true, "license": "MIT", "dependencies": { @@ -9358,9 +9362,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", + "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", "dev": true, "license": "MIT", "bin": { @@ -9578,9 +9582,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "license": "MIT", "dependencies": { @@ -16376,9 +16380,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.46", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz", - "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", + "version": "0.5.47", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.47.tgz", + "integrity": "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -18671,10 +18675,11 @@ } }, "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", + "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -21224,9 +21229,10 @@ "dev": true }, "node_modules/sass": { - "version": "1.83.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.0.tgz", - "integrity": "sha512-qsSxlayzoOjdvXMVLkzF84DJFc2HZEL/rFyGIKbbilYtAvlCxyuzUeff9LawTn4btVnLKg75Z8MMr1lxU1lfGw==", + "version": "1.85.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz", + "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==", + "license": "MIT", "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -21373,9 +21379,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "bin": { @@ -22780,9 +22786,9 @@ "dev": true }, "node_modules/ts-jest": { - "version": "29.2.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", - "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", + "version": "29.2.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.6.tgz", + "integrity": "sha512-yTNZVZqc8lSixm+QGVFcPe6+yj7+TWZwIesuOWvfcn4B9bz5x4NDzVCQQjOs7Hfouu36aEqfEbo9Qpo+gq8dDg==", "dev": true, "license": "MIT", "dependencies": { @@ -22793,7 +22799,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.6.3", + "semver": "^7.7.1", "yargs-parser": "^21.1.1" }, "bin": { diff --git a/web/ui/react-app/package.json b/web/ui/react-app/package.json index 232f229a3b..0455cb2b5c 100644 --- a/web/ui/react-app/package.json +++ b/web/ui/react-app/package.json @@ -3,13 +3,13 @@ "version": "0.300.1", "private": true, "dependencies": { - "@codemirror/autocomplete": "^6.18.4", - "@codemirror/commands": "^6.7.1", + "@codemirror/autocomplete": "^6.18.6", + "@codemirror/commands": "^6.8.0", "@codemirror/language": "^6.10.8", "@codemirror/lint": "^6.8.4", - "@codemirror/search": "^6.5.8", - "@codemirror/state": "^6.3.3", - "@codemirror/view": "^6.36.1", + "@codemirror/search": "^6.5.10", + "@codemirror/state": "^6.5.2", + "@codemirror/view": "^6.36.3", "@forevolve/bootstrap-dark": "^4.0.2", "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-solid-svg-icons": "6.7.2", @@ -19,7 +19,7 @@ "@lezer/lr": "^1.4.2", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.300.1", + "@prometheus-io/codemirror-promql": "0.302.1", "bootstrap": "^4.6.2", "css.escape": "^1.5.1", "downshift": "^9.0.8", @@ -27,7 +27,7 @@ "jquery": "^3.7.1", "jquery.flot.tooltip": "^0.9.0", "moment": "^2.30.1", - "moment-timezone": "^0.5.46", + "moment-timezone": "^0.5.47", "popper.js": "^1.14.3", "react": "^17.0.2", "react-copy-to-clipboard": "^5.1.0", @@ -38,7 +38,7 @@ "react-test-renderer": "^17.0.2", "reactstrap": "^8.10.1", "sanitize-html": "^2.14.0", - "sass": "1.83.0", + "sass": "1.85.1", "tempusdominus-bootstrap-4": "^5.39.2", "tempusdominus-core": "^5.19.3" }, @@ -77,20 +77,20 @@ "@types/react-dom": "^17.0.25", "@types/react-router-dom": "^5.3.3", "@types/sanitize-html": "^2.13.0", - "@types/sinon": "^17.0.3", + "@types/sinon": "^17.0.4", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.2", - "eslint-config-prettier": "^9.1.0", + "eslint-config-prettier": "^10.1.1", "eslint-config-react-app": "^7.0.1", - "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-prettier": "^5.2.3", "jest-canvas-mock": "^2.5.2", "jest-fetch-mock": "^3.0.3", "mutationobserver-shim": "^0.3.7", - "prettier": "^3.0.0", + "prettier": "^3.5.2", "react-scripts": "^5.0.1", "sinon": "^19.0.2", - "ts-jest": "^29.2.5" + "ts-jest": "^29.2.6" }, "jest": { "snapshotSerializers": [ diff --git a/web/web.go b/web/web.go index f800e01867..d6ed58fbb9 100644 --- a/web/web.go +++ b/web/web.go @@ -445,7 +445,7 @@ func New(logger *slog.Logger, o *Options) *Handler { router.Get("/consoles/*filepath", readyf(h.consoles)) - serveReactApp := func(w http.ResponseWriter, r *http.Request) { + serveReactApp := func(w http.ResponseWriter, _ *http.Request) { indexPath := reactAssetsRoot + "/index.html" f, err := ui.Assets.Open(indexPath) if err != nil { @@ -543,18 +543,18 @@ func New(logger *slog.Logger, o *Options) *Handler { router.Get("/debug/*subpath", serveDebug) router.Post("/debug/*subpath", serveDebug) - router.Get("/-/healthy", func(w http.ResponseWriter, r *http.Request) { + router.Get("/-/healthy", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "%s is Healthy.\n", o.AppName) }) router.Head("/-/healthy", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) }) - router.Get("/-/ready", readyf(func(w http.ResponseWriter, r *http.Request) { + router.Get("/-/ready", readyf(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "%s is Ready.\n", o.AppName) })) - router.Head("/-/ready", readyf(func(w http.ResponseWriter, r *http.Request) { + router.Head("/-/ready", readyf(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -900,7 +900,7 @@ func (h *Handler) consolesPath() string { } func setPathWithPrefix(prefix string) func(handlerName string, handler http.HandlerFunc) http.HandlerFunc { - return func(handlerName string, handler http.HandlerFunc) http.HandlerFunc { + return func(_ string, handler http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { handler(w, r.WithContext(httputil.ContextWithPath(r.Context(), prefix+r.URL.Path))) }