diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..4b574dfb7 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @percona/pmm-review-exporters diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 22f42bc20..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve. -title: '' -assignees: '' ---- - - - -**What did you do?** - -**What did you expect to see?** - -**What did you see instead? Under which circumstances?** - -**Environment** - -* System information: - - insert output of `uname -srm` here - -* postgres_exporter version: - - insert output of `postgres_exporter --version` here - -* postgres_exporter flags: - -``` -insert list of flags used here -``` - -* PostgreSQL version: - - insert PostgreSQL version here - -* Logs: -``` -insert logs relevant to the issue here -``` diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index d70ee5512..000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,5 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Prometheus community support - url: https://prometheus.io/community/ - about: List of communication channels for the Prometheus community. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index ee6d97a85..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project. -title: '' -labels: '' -assignees: '' ---- - - -## Proposal -**Use case. Why is this important?** - -*“Nice to have” is not a good use case. :)* diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 202ae2366..d5a0dd4b8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,19 @@ +--- version: 2 updates: - package-ecosystem: "gomod" directory: "/" schedule: - interval: "monthly" + interval: "weekly" + - package-ecosystem: "gomod" + directory: "/tools" + schedule: + interval: "weekly" + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 000000000..55a59aad6 --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,56 @@ +name: Go + +on: + push: + branches: + - main + tags: + - v[0-9]+.[0-9]+.[0-9]+* + pull_request: + +jobs: + test: + name: Test + strategy: + matrix: + postgresql-image: + - postgres:10 + - postgres:11 + - postgres:12 + - postgres:13 + - postgres:14 + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: ${{ github.workspace }}/go.mod + + - name: Run checks + run: | + go build -modfile=tools/go.mod -o bin/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint + go build -modfile=tools/go.mod -o bin/reviewdog github.com/reviewdog/reviewdog/cmd/reviewdog + bin/golangci-lint run -c=.golangci.yml --out-format=line-number | env REVIEWDOG_GITHUB_API_TOKEN=${{ secrets.GITHUB_TOKEN }} bin/reviewdog -f=golangci-lint -level=error -reporter=github-pr-review + + - name: Run Tests + run: | + sudo chown 999:999 testdata/ssl/server/* + sudo chmod 600 testdata/ssl/server/* + docker compose up -d + make + make test + env: + POSTGRESQL_IMAGE: ${{ matrix.postgresql-image }} + + - name: Run debug commands on failure + if: ${{ failure() }} + run: | + env | sort + go env | sort + git status + docker --version + docker compose --version + docker compose logs diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 15cf547be..aa44fe475 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -20,13 +20,15 @@ jobs: - name: Checkout repository uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: install Go - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 + uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: - go-version: 1.20.x + go-version-file: ${{ github.workspace }}/go.mod + - 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@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 + uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0 with: version: v1.54.2 diff --git a/.gitignore b/.gitignore index e6ae827a2..87577f881 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ /.metrics.*.removed /tools/src /vendor +/percona_tests/assets/postgres_exporter +/percona_tests/assets/postgres_exporter_percona +/percona_tests/assets/metrics.* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d17f536b..dc8f898f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,11 @@ params. See the Multi-Target Support section of the README. * [BUGFIX] Fix checkpoint_write_time value type #666 * [BUGFIX] Fix checkpoint_sync_time value type #667 +## 0.11.1 / 2022-08-01 + +* [BUGFIX] Fix checkpoint_write_time value type #666 +* [BUGFIX] Fix checkpoint_sync_time value type #667 + ## 0.11.0 / 2022-07-28 NOTE: pg_stat_bgwriter counter metrics had the `_total` suffix added #556 diff --git a/Makefile b/Makefile index 114e3438f..e0e7f7355 100644 --- a/Makefile +++ b/Makefile @@ -8,3 +8,10 @@ DOCKER_REPO ?= prometheuscommunity include Makefile.common DOCKER_IMAGE_NAME ?= postgres-exporter + +GO_BUILD_LDFLAGS = -X github.com/prometheus/common/version.Version=$(shell cat VERSION) -X github.com/prometheus/common/version.Revision=$(shell git rev-parse HEAD) -X github.com/prometheus/common/version.Branch=$(shell git describe --always --contains --all) -X github.com/prometheus/common/version.BuildUser= -X github.com/prometheus/common/version.BuildDate=$(shell date +%FT%T%z) -s -w + +export PMM_RELEASE_PATH?=. + +release: + go build -ldflags="$(GO_BUILD_LDFLAGS)" -o $(PMM_RELEASE_PATH)/postgres_exporter ./cmd/postgres_exporter diff --git a/Makefile.common b/Makefile.common index 062a28185..81a9b25fb 100644 --- a/Makefile.common +++ b/Makefile.common @@ -58,7 +58,7 @@ endif PROMU_VERSION ?= 0.15.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz -SKIP_GOLANGCI_LINT := +SKIP_GOLANGCI_LINT ?= $(CI) GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= GOLANGCI_LINT_VERSION ?= v1.54.2 @@ -106,7 +106,7 @@ endif %: common-% ; .PHONY: common-all -common-all: precheck style check_license lint yamllint unused build test +common-all: precheck style lint unused build test .PHONY: common-style common-style: @@ -118,17 +118,6 @@ common-style: exit 1; \ fi -.PHONY: common-check_license -common-check_license: - @echo ">> checking license header" - @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ - awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ - done); \ - if [ -n "$${licRes}" ]; then \ - echo "license header checking failed:"; echo "$${licRes}"; \ - exit 1; \ - fi - .PHONY: common-deps common-deps: @echo ">> getting dependencies" diff --git a/cmd/postgres_exporter/datasource.go b/cmd/postgres_exporter/datasource.go index 0b8cef04a..cfc97aae1 100644 --- a/cmd/postgres_exporter/datasource.go +++ b/cmd/postgres_exporter/datasource.go @@ -48,22 +48,16 @@ func (e *Exporter) discoverDatabaseDSNs() []string { level.Error(logger).Log("msg", "Unable to parse DSN as either URI or connstring", "dsn", loggableDSN(dsn)) continue } - - server, err := e.servers.GetServer(dsn) - if err != nil { - level.Error(logger).Log("msg", "Error opening connection to database", "dsn", loggableDSN(dsn), "err", err) - continue - } dsns[dsn] = struct{}{} // If autoDiscoverDatabases is true, set first dsn as master database (Default: false) - server.master = true + e.masterDSN = dsn - databaseNames, err := queryDatabases(server) + databaseNames, err := e.getDatabaseNames(dsn) if err != nil { - level.Error(logger).Log("msg", "Error querying databases", "dsn", loggableDSN(dsn), "err", err) continue } + for _, databaseName := range databaseNames { if contains(e.excludeDatabases, databaseName) { continue @@ -74,7 +68,11 @@ func (e *Exporter) discoverDatabaseDSNs() []string { } if dsnURI != nil { - dsnURI.Path = databaseName + if dsnURI.Host == "" && strings.HasPrefix(dsnURI.Path, "/") { + dsnURI.Path = "/" + databaseName + } else { + dsnURI.Path = databaseName + } dsn = dsnURI.String() } else { // replacing one dbname with another is complicated. @@ -95,15 +93,40 @@ func (e *Exporter) discoverDatabaseDSNs() []string { return result } -func (e *Exporter) scrapeDSN(ch chan<- prometheus.Metric, dsn string) error { - server, err := e.servers.GetServer(dsn) +func (e *Exporter) getDatabaseNames(dsn string) ([]string, error) { + if e.connSema != nil { + if err := e.connSema.Acquire(e.ctx, 1); err != nil { + level.Warn(logger).Log("msg", "Failed to acquire semaphore", "err", err) + return nil, err + } + defer e.connSema.Release(1) + } + server, err := e.GetServer(dsn) + if err != nil { + level.Error(logger).Log("msg", "Error opening connection to database", "dsn", loggableDSN(dsn), "err", err) + return nil, err + } + defer server.Close() + + dbNames, err := queryDatabases(e.ctx, server) + if err != nil { + level.Error(logger).Log("msg", "Error querying databases", "dsn", loggableDSN(dsn), "err", err) + return nil, err + } + + return dbNames, nil +} + +func (e *Exporter) scrapeDSN(ch chan<- prometheus.Metric, dsn string) error { + server, err := e.GetServer(dsn) if err != nil { return &ErrorConnectToServer{fmt.Sprintf("Error opening connection to database (%s): %s", loggableDSN(dsn), err.Error())} } + defer server.Close() // Check if autoDiscoverDatabases is false, set dsn as master database (Default: false) - if !e.autoDiscoverDatabases { + if !e.autoDiscoverDatabases || e.masterDSN == dsn { server.master = true } diff --git a/cmd/postgres_exporter/main.go b/cmd/postgres_exporter/main.go index 7d424b3d3..07f0e542a 100644 --- a/cmd/postgres_exporter/main.go +++ b/cmd/postgres_exporter/main.go @@ -16,21 +16,24 @@ package main import ( "fmt" "net/http" + _ "net/http/pprof" "os" "strings" "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/prometheus-community/postgres_exporter/collector" "github.com/prometheus-community/postgres_exporter/config" "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/client_golang/prometheus/collectors" + vc "github.com/prometheus/client_golang/prometheus/collectors/version" "github.com/prometheus/common/promlog" "github.com/prometheus/common/promlog/flag" + "github.com/prometheus/common/promslog" "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" "github.com/prometheus/exporter-toolkit/web/kingpinflag" + "golang.org/x/sync/semaphore" ) var ( @@ -38,19 +41,23 @@ var ( Config: &config.Config{}, } - configFile = kingpin.Flag("config.file", "Postgres exporter configuration file.").Default("postgres_exporter.yml").String() - webConfig = kingpinflag.AddFlags(kingpin.CommandLine, ":9187") + configFile = kingpin.Flag("config.file", "Postgres exporter configuration file.").Default("postgres_exporter.yml").String() + webConfig = kingpinflag.AddFlags(kingpin.CommandLine, ":9187") + webConfigFile = kingpin.Flag( + "web.config", + "[EXPERIMENTAL] Path to config yaml file that can enable TLS or authentication.", + ).Default("").String() // added for compatibility reasons to not break it in PMM 2. metricsPath = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").Envar("PG_EXPORTER_WEB_TELEMETRY_PATH").String() disableDefaultMetrics = kingpin.Flag("disable-default-metrics", "Do not include default metrics.").Default("false").Envar("PG_EXPORTER_DISABLE_DEFAULT_METRICS").Bool() disableSettingsMetrics = kingpin.Flag("disable-settings-metrics", "Do not include pg_settings metrics.").Default("false").Envar("PG_EXPORTER_DISABLE_SETTINGS_METRICS").Bool() autoDiscoverDatabases = kingpin.Flag("auto-discover-databases", "Whether to discover the databases on a server dynamically. (DEPRECATED)").Default("false").Envar("PG_EXPORTER_AUTO_DISCOVER_DATABASES").Bool() - queriesPath = kingpin.Flag("extend.query-path", "Path to custom queries to run. (DEPRECATED)").Default("").Envar("PG_EXPORTER_EXTEND_QUERY_PATH").String() - onlyDumpMaps = kingpin.Flag("dumpmaps", "Do not run, simply dump the maps.").Bool() - constantLabelsList = kingpin.Flag("constantLabels", "A list of label=value separated by comma(,). (DEPRECATED)").Default("").Envar("PG_EXPORTER_CONSTANT_LABELS").String() - excludeDatabases = kingpin.Flag("exclude-databases", "A list of databases to remove when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_EXCLUDE_DATABASES").String() - includeDatabases = kingpin.Flag("include-databases", "A list of databases to include when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_INCLUDE_DATABASES").String() - metricPrefix = kingpin.Flag("metric-prefix", "A metric prefix can be used to have non-default (not \"pg\") prefixes for each of the metrics").Default("pg").Envar("PG_EXPORTER_METRIC_PREFIX").String() - logger = log.NewNopLogger() + // queriesPath = kingpin.Flag("extend.query-path", "Path to custom queries to run. (DEPRECATED)").Default("").Envar("PG_EXPORTER_EXTEND_QUERY_PATH").String() + onlyDumpMaps = kingpin.Flag("dumpmaps", "Do not run, simply dump the maps.").Bool() + constantLabelsList = kingpin.Flag("constantLabels", "A list of label=value separated by comma(,). (DEPRECATED)").Default("").Envar("PG_EXPORTER_CONSTANT_LABELS").String() + excludeDatabases = kingpin.Flag("exclude-databases", "A list of databases to remove when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_EXCLUDE_DATABASES").String() + includeDatabases = kingpin.Flag("include-databases", "A list of databases to include when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_INCLUDE_DATABASES").String() + metricPrefix = kingpin.Flag("metric-prefix", "A metric prefix can be used to have non-default (not \"pg\") prefixes for each of the metrics").Default("pg").Envar("PG_EXPORTER_METRIC_PREFIX").String() + logger = log.NewNopLogger() ) // Metric name parts. @@ -73,6 +80,7 @@ func main() { promlogConfig := &promlog.Config{} flag.AddFlags(kingpin.CommandLine, promlogConfig) kingpin.HelpFlag.Short('h') + webConfig.WebConfigFile = webConfigFile kingpin.Parse() logger = promlog.New(promlogConfig) @@ -95,9 +103,9 @@ func main() { excludedDatabases := strings.Split(*excludeDatabases, ",") logger.Log("msg", "Excluded databases", "databases", fmt.Sprintf("%v", excludedDatabases)) - if *queriesPath != "" { - level.Warn(logger).Log("msg", "The extended queries.yaml config is DEPRECATED", "file", *queriesPath) - } + // if *queriesPath != "" { + // level.Warn(logger).Log("msg", "The extended queries.yaml config is DEPRECATED", "file", *queriesPath) + // } if *autoDiscoverDatabases || *excludeDatabases != "" || *includeDatabases != "" { level.Warn(logger).Log("msg", "Scraping additional databases via auto discovery is DEPRECATED") @@ -107,44 +115,18 @@ func main() { level.Warn(logger).Log("msg", "Constant labels on all metrics is DEPRECATED") } - opts := []ExporterOpt{ - DisableDefaultMetrics(*disableDefaultMetrics), - DisableSettingsMetrics(*disableSettingsMetrics), - AutoDiscoverDatabases(*autoDiscoverDatabases), - WithUserQueriesPath(*queriesPath), - WithConstantLabels(*constantLabelsList), - ExcludeDatabases(excludedDatabases), - IncludeDatabases(*includeDatabases), - } - - exporter := NewExporter(dsns, opts...) - defer func() { - exporter.servers.Close() - }() - - prometheus.MustRegister(version.NewCollector(exporterName)) + versionCollector := vc.NewCollector(exporterName) + psCollector := collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}) + goCollector := collectors.NewGoCollector() - prometheus.MustRegister(exporter) - - // TODO(@sysadmind): Remove this with multi-target support. We are removing multiple DSN support - dsn := "" - if len(dsns) > 0 { - dsn = dsns[0] - } - - pe, err := collector.NewPostgresCollector( - logger, - excludedDatabases, - dsn, - []string{}, - ) - if err != nil { - level.Warn(logger).Log("msg", "Failed to create PostgresCollector", "err", err.Error()) - } else { - prometheus.MustRegister(pe) + globalCollectors := map[string]prometheus.Collector{ + "standard.process": psCollector, + "standard.go": goCollector, + "version": versionCollector, } - http.Handle(*metricsPath, promhttp.Handler()) + connSema := semaphore.NewWeighted(*maxConnections) + http.Handle(*metricsPath, Handler(logger, dsns, connSema, globalCollectors)) if *metricsPath != "/" && *metricsPath != "" { landingConfig := web.LandingConfig{ @@ -166,10 +148,11 @@ func main() { http.Handle("/", landingPage) } - http.HandleFunc("/probe", handleProbe(logger, excludedDatabases)) + http.HandleFunc("/probe", handleProbe(logger, excludedDatabases, connSema)) + level.Info(logger).Log("msg", "Listening on address", "address", *webConfig.WebListenAddresses) srv := &http.Server{} - if err := web.ListenAndServe(srv, webConfig, logger); err != nil { + if err := web.ListenAndServe(srv, webConfig, promslog.New(&promslog.Config{})); err != nil { level.Error(logger).Log("msg", "Error running HTTP server", "err", err) os.Exit(1) } diff --git a/cmd/postgres_exporter/namespace.go b/cmd/postgres_exporter/namespace.go index 41674007d..f8aa0c9a4 100644 --- a/cmd/postgres_exporter/namespace.go +++ b/cmd/postgres_exporter/namespace.go @@ -233,7 +233,7 @@ func queryNamespaceMappings(ch chan<- prometheus.Metric, server *Server) map[str // Serious error - a namespace disappeared if err != nil { namespaceErrors[namespace] = err - level.Info(logger).Log("err", err) + level.Error(logger).Log("err", err) } // Non-serious errors - likely version or parsing problems. if len(nonFatalErrors) > 0 { diff --git a/cmd/postgres_exporter/percona-reference-metrics.txt b/cmd/postgres_exporter/percona-reference-metrics.txt new file mode 100644 index 000000000..48c8353c2 --- /dev/null +++ b/cmd/postgres_exporter/percona-reference-metrics.txt @@ -0,0 +1,1638 @@ +# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles. +# TYPE go_gc_duration_seconds summary +go_gc_duration_seconds{quantile="0"} 1.711e-05 +go_gc_duration_seconds{quantile="0.25"} 2.7717e-05 +go_gc_duration_seconds{quantile="0.5"} 3.9651e-05 +go_gc_duration_seconds{quantile="0.75"} 7.6418e-05 +go_gc_duration_seconds{quantile="1"} 0.00445376 +go_gc_duration_seconds_sum 0.053608842 +go_gc_duration_seconds_count 737 +# HELP go_goroutines Number of goroutines that currently exist. +# TYPE go_goroutines gauge +go_goroutines 24 +# HELP go_info Information about the Go environment. +# TYPE go_info gauge +go_info{version="go1.18.1"} 1 +# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use. +# TYPE go_memstats_alloc_bytes gauge +go_memstats_alloc_bytes 2.16544e+06 +# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed. +# TYPE go_memstats_alloc_bytes_total counter +go_memstats_alloc_bytes_total 1.294317752e+09 +# HELP go_memstats_buck_hash_sys_bytes Number of bytes used by the profiling bucket hash table. +# TYPE go_memstats_buck_hash_sys_bytes gauge +go_memstats_buck_hash_sys_bytes 1.587226e+06 +# HELP go_memstats_frees_total Total number of frees. +# TYPE go_memstats_frees_total counter +go_memstats_frees_total 1.4051273e+07 +# HELP go_memstats_gc_cpu_fraction The fraction of this program's available CPU time used by the GC since the program started. +# TYPE go_memstats_gc_cpu_fraction gauge +go_memstats_gc_cpu_fraction 9.458160543185982e-05 +# HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata. +# TYPE go_memstats_gc_sys_bytes gauge +go_memstats_gc_sys_bytes 5.079808e+06 +# HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use. +# TYPE go_memstats_heap_alloc_bytes gauge +go_memstats_heap_alloc_bytes 2.16544e+06 +# HELP go_memstats_heap_idle_bytes Number of heap bytes waiting to be used. +# TYPE go_memstats_heap_idle_bytes gauge +go_memstats_heap_idle_bytes 7.266304e+06 +# HELP go_memstats_heap_inuse_bytes Number of heap bytes that are in use. +# TYPE go_memstats_heap_inuse_bytes gauge +go_memstats_heap_inuse_bytes 4.399104e+06 +# HELP go_memstats_heap_objects Number of allocated objects. +# TYPE go_memstats_heap_objects gauge +go_memstats_heap_objects 13067 +# HELP go_memstats_heap_released_bytes Number of heap bytes released to OS. +# TYPE go_memstats_heap_released_bytes gauge +go_memstats_heap_released_bytes 6.26688e+06 +# HELP go_memstats_heap_sys_bytes Number of heap bytes obtained from system. +# TYPE go_memstats_heap_sys_bytes gauge +go_memstats_heap_sys_bytes 1.1665408e+07 +# HELP go_memstats_last_gc_time_seconds Number of seconds since 1970 of last garbage collection. +# TYPE go_memstats_last_gc_time_seconds gauge +go_memstats_last_gc_time_seconds 1.6534228318017354e+09 +# HELP go_memstats_lookups_total Total number of pointer lookups. +# TYPE go_memstats_lookups_total counter +go_memstats_lookups_total 0 +# HELP go_memstats_mallocs_total Total number of mallocs. +# TYPE go_memstats_mallocs_total counter +go_memstats_mallocs_total 1.406434e+07 +# HELP go_memstats_mcache_inuse_bytes Number of bytes in use by mcache structures. +# TYPE go_memstats_mcache_inuse_bytes gauge +go_memstats_mcache_inuse_bytes 7200 +# HELP go_memstats_mcache_sys_bytes Number of bytes used for mcache structures obtained from system. +# TYPE go_memstats_mcache_sys_bytes gauge +go_memstats_mcache_sys_bytes 15600 +# HELP go_memstats_mspan_inuse_bytes Number of bytes in use by mspan structures. +# TYPE go_memstats_mspan_inuse_bytes gauge +go_memstats_mspan_inuse_bytes 107576 +# HELP go_memstats_mspan_sys_bytes Number of bytes used for mspan structures obtained from system. +# TYPE go_memstats_mspan_sys_bytes gauge +go_memstats_mspan_sys_bytes 146880 +# HELP go_memstats_next_gc_bytes Number of heap bytes when next garbage collection will take place. +# TYPE go_memstats_next_gc_bytes gauge +go_memstats_next_gc_bytes 4.2164e+06 +# HELP go_memstats_other_sys_bytes Number of bytes used for other system allocations. +# TYPE go_memstats_other_sys_bytes gauge +go_memstats_other_sys_bytes 1.379902e+06 +# HELP go_memstats_stack_inuse_bytes Number of bytes in use by the stack allocator. +# TYPE go_memstats_stack_inuse_bytes gauge +go_memstats_stack_inuse_bytes 917504 +# HELP go_memstats_stack_sys_bytes Number of bytes obtained from system for stack allocator. +# TYPE go_memstats_stack_sys_bytes gauge +go_memstats_stack_sys_bytes 917504 +# HELP go_memstats_sys_bytes Number of bytes obtained from system. +# TYPE go_memstats_sys_bytes gauge +go_memstats_sys_bytes 2.0792328e+07 +# HELP go_threads Number of OS threads created. +# TYPE go_threads gauge +go_threads 9 +# HELP pg_database_size_bytes Disk space used by the database +# TYPE pg_database_size_bytes gauge +pg_database_size_bytes{collector="custom_query.mr",datname="pmm-managed",server="127.0.0.1:5432"} 8.835743e+06 +pg_database_size_bytes{collector="custom_query.mr",datname="postgres",server="127.0.0.1:5432"} 7.869087e+06 +pg_database_size_bytes{collector="custom_query.mr",datname="template0",server="127.0.0.1:5432"} 7.717379e+06 +pg_database_size_bytes{collector="custom_query.mr",datname="template1",server="127.0.0.1:5432"} 7.717379e+06 +# HELP pg_exporter_last_scrape_duration_seconds Duration of the last scrape of metrics from PostgresSQL. +# TYPE pg_exporter_last_scrape_duration_seconds gauge +pg_exporter_last_scrape_duration_seconds{collector="custom_query.hr"} 0.031032888 +pg_exporter_last_scrape_duration_seconds{collector="custom_query.lr"} 0.028413681 +pg_exporter_last_scrape_duration_seconds{collector="custom_query.mr"} 0.076106239 +pg_exporter_last_scrape_duration_seconds{collector="exporter"} 0.076724395 +# HELP pg_exporter_last_scrape_error Whether the last scrape of metrics from PostgreSQL resulted in an error (1 for error, 0 for success). +# TYPE pg_exporter_last_scrape_error gauge +pg_exporter_last_scrape_error{collector="custom_query.hr"} 0 +pg_exporter_last_scrape_error{collector="custom_query.lr"} 0 +pg_exporter_last_scrape_error{collector="custom_query.mr"} 0 +pg_exporter_last_scrape_error{collector="exporter"} 0 +# HELP pg_exporter_scrapes_total Total number of times PostgresSQL was scraped for metrics. +# TYPE pg_exporter_scrapes_total counter +pg_exporter_scrapes_total{collector="custom_query.hr"} 638 +pg_exporter_scrapes_total{collector="custom_query.lr"} 54 +pg_exporter_scrapes_total{collector="custom_query.mr"} 320 +pg_exporter_scrapes_total{collector="exporter"} 638 +# HELP pg_exporter_user_queries_load_error Whether the user queries file was loaded and parsed successfully (1 for error, 0 for success). +# TYPE pg_exporter_user_queries_load_error gauge +pg_exporter_user_queries_load_error{collector="custom_query.hr",filename="/usr/local/percona/pmm2/collectors/custom-queries/postgresql/high-resolution/example-queries-postgres.yml",hashsum="d497a1386bdf51904e434ea4a3827557a1d9a2a9ed054272d776443157331899"} 0 +pg_exporter_user_queries_load_error{collector="custom_query.hr",filename="/usr/local/percona/pmm2/collectors/custom-queries/postgresql/high-resolution/queries-postgres-uptime.yml",hashsum="088cda481b62888aa2674b361c8a390586d96f02f9be384f475dcf1d6e3997fc"} 0 +pg_exporter_user_queries_load_error{collector="custom_query.lr",filename="/usr/local/percona/pmm2/collectors/custom-queries/postgresql/low-resolution/example-queries-postgres.yml",hashsum="d497a1386bdf51904e434ea4a3827557a1d9a2a9ed054272d776443157331899"} 0 +pg_exporter_user_queries_load_error{collector="custom_query.mr",filename="/usr/local/percona/pmm2/collectors/custom-queries/postgresql/medium-resolution/example-queries-postgres.yml",hashsum="d497a1386bdf51904e434ea4a3827557a1d9a2a9ed054272d776443157331899"} 0 +pg_exporter_user_queries_load_error{collector="custom_query.mr",filename="/usr/local/percona/pmm2/collectors/custom-queries/postgresql/medium-resolution/queries.yaml",hashsum="1a22e5d3278b8f4bf9b8d1ed94918a530fb70d6f1c6ffd1a81db411d1fc332ac"} 0 +# HELP pg_locks_count Number of locks +# TYPE pg_locks_count gauge +pg_locks_count{collector="exporter",datname="pmm-managed",mode="accessexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="pmm-managed",mode="accesssharelock",server="127.0.0.1:5432"} 12 +pg_locks_count{collector="exporter",datname="pmm-managed",mode="exclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="pmm-managed",mode="rowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="pmm-managed",mode="rowsharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="pmm-managed",mode="sharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="pmm-managed",mode="sharerowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="pmm-managed",mode="shareupdateexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="postgres",mode="accessexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="postgres",mode="accesssharelock",server="127.0.0.1:5432"} 1 +pg_locks_count{collector="exporter",datname="postgres",mode="exclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="postgres",mode="rowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="postgres",mode="rowsharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="postgres",mode="sharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="postgres",mode="sharerowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="postgres",mode="shareupdateexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="accessexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="accesssharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="exclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="rowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="rowsharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="sharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="sharerowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template0",mode="shareupdateexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="accessexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="accesssharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="exclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="rowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="rowsharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="sharelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="sharerowexclusivelock",server="127.0.0.1:5432"} 0 +pg_locks_count{collector="exporter",datname="template1",mode="shareupdateexclusivelock",server="127.0.0.1:5432"} 0 +# HELP pg_postmaster_start_time_seconds Time at which postmaster started +# TYPE pg_postmaster_start_time_seconds gauge +pg_postmaster_start_time_seconds{collector="custom_query.mr",server="127.0.0.1:5432"} 1.653392259e+09 +# HELP pg_postmaster_uptime_seconds Service uptime +# TYPE pg_postmaster_uptime_seconds gauge +pg_postmaster_uptime_seconds{collector="custom_query.hr",server="127.0.0.1:5432"} 30573.962546 +# HELP pg_replication_lag Replication lag behind master in seconds +# TYPE pg_replication_lag gauge +pg_replication_lag{collector="custom_query.mr",server="127.0.0.1:5432"} 0 +# HELP pg_settings_allow_system_table_mods Allows modifications of the structure of system tables. +# TYPE pg_settings_allow_system_table_mods gauge +pg_settings_allow_system_table_mods{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_archive_timeout_seconds Forces a switch to the next WAL file if a new file has not been started within N seconds. [Units converted to seconds.] +# TYPE pg_settings_archive_timeout_seconds gauge +pg_settings_archive_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_array_nulls Enable input of NULL elements in arrays. +# TYPE pg_settings_array_nulls gauge +pg_settings_array_nulls{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_authentication_timeout_seconds Sets the maximum allowed time to complete client authentication. [Units converted to seconds.] +# TYPE pg_settings_authentication_timeout_seconds gauge +pg_settings_authentication_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 60 +# HELP pg_settings_autovacuum Starts the autovacuum subprocess. +# TYPE pg_settings_autovacuum gauge +pg_settings_autovacuum{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_autovacuum_analyze_scale_factor Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples. +# TYPE pg_settings_autovacuum_analyze_scale_factor gauge +pg_settings_autovacuum_analyze_scale_factor{collector="exporter",server="127.0.0.1:5432"} 0.1 +# HELP pg_settings_autovacuum_analyze_threshold Minimum number of tuple inserts, updates, or deletes prior to analyze. +# TYPE pg_settings_autovacuum_analyze_threshold gauge +pg_settings_autovacuum_analyze_threshold{collector="exporter",server="127.0.0.1:5432"} 50 +# HELP pg_settings_autovacuum_freeze_max_age Age at which to autovacuum a table to prevent transaction ID wraparound. +# TYPE pg_settings_autovacuum_freeze_max_age gauge +pg_settings_autovacuum_freeze_max_age{collector="exporter",server="127.0.0.1:5432"} 2e+08 +# HELP pg_settings_autovacuum_max_workers Sets the maximum number of simultaneously running autovacuum worker processes. +# TYPE pg_settings_autovacuum_max_workers gauge +pg_settings_autovacuum_max_workers{collector="exporter",server="127.0.0.1:5432"} 3 +# HELP pg_settings_autovacuum_multixact_freeze_max_age Multixact age at which to autovacuum a table to prevent multixact wraparound. +# TYPE pg_settings_autovacuum_multixact_freeze_max_age gauge +pg_settings_autovacuum_multixact_freeze_max_age{collector="exporter",server="127.0.0.1:5432"} 4e+08 +# HELP pg_settings_autovacuum_naptime_seconds Time to sleep between autovacuum runs. [Units converted to seconds.] +# TYPE pg_settings_autovacuum_naptime_seconds gauge +pg_settings_autovacuum_naptime_seconds{collector="exporter",server="127.0.0.1:5432"} 60 +# HELP pg_settings_autovacuum_vacuum_cost_delay_seconds Vacuum cost delay in milliseconds, for autovacuum. [Units converted to seconds.] +# TYPE pg_settings_autovacuum_vacuum_cost_delay_seconds gauge +pg_settings_autovacuum_vacuum_cost_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 0.02 +# HELP pg_settings_autovacuum_vacuum_cost_limit Vacuum cost amount available before napping, for autovacuum. +# TYPE pg_settings_autovacuum_vacuum_cost_limit gauge +pg_settings_autovacuum_vacuum_cost_limit{collector="exporter",server="127.0.0.1:5432"} -1 +# HELP pg_settings_autovacuum_vacuum_scale_factor Number of tuple updates or deletes prior to vacuum as a fraction of reltuples. +# TYPE pg_settings_autovacuum_vacuum_scale_factor gauge +pg_settings_autovacuum_vacuum_scale_factor{collector="exporter",server="127.0.0.1:5432"} 0.2 +# HELP pg_settings_autovacuum_vacuum_threshold Minimum number of tuple updates or deletes prior to vacuum. +# TYPE pg_settings_autovacuum_vacuum_threshold gauge +pg_settings_autovacuum_vacuum_threshold{collector="exporter",server="127.0.0.1:5432"} 50 +# HELP pg_settings_autovacuum_work_mem_bytes Sets the maximum memory to be used by each autovacuum worker process. [Units converted to bytes.] +# TYPE pg_settings_autovacuum_work_mem_bytes gauge +pg_settings_autovacuum_work_mem_bytes{collector="exporter",server="127.0.0.1:5432"} -1 +# HELP pg_settings_backend_flush_after_bytes Number of pages after which previously performed writes are flushed to disk. [Units converted to bytes.] +# TYPE pg_settings_backend_flush_after_bytes gauge +pg_settings_backend_flush_after_bytes{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_bgwriter_delay_seconds Background writer sleep time between rounds. [Units converted to seconds.] +# TYPE pg_settings_bgwriter_delay_seconds gauge +pg_settings_bgwriter_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 0.2 +# HELP pg_settings_bgwriter_flush_after_bytes Number of pages after which previously performed writes are flushed to disk. [Units converted to bytes.] +# TYPE pg_settings_bgwriter_flush_after_bytes gauge +pg_settings_bgwriter_flush_after_bytes{collector="exporter",server="127.0.0.1:5432"} 524288 +# HELP pg_settings_bgwriter_lru_maxpages Background writer maximum number of LRU pages to flush per round. +# TYPE pg_settings_bgwriter_lru_maxpages gauge +pg_settings_bgwriter_lru_maxpages{collector="exporter",server="127.0.0.1:5432"} 100 +# HELP pg_settings_bgwriter_lru_multiplier Multiple of the average buffer usage to free per round. +# TYPE pg_settings_bgwriter_lru_multiplier gauge +pg_settings_bgwriter_lru_multiplier{collector="exporter",server="127.0.0.1:5432"} 2 +# HELP pg_settings_block_size Shows the size of a disk block. +# TYPE pg_settings_block_size gauge +pg_settings_block_size{collector="exporter",server="127.0.0.1:5432"} 8192 +# HELP pg_settings_bonjour Enables advertising the server via Bonjour. +# TYPE pg_settings_bonjour gauge +pg_settings_bonjour{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_check_function_bodies Check function bodies during CREATE FUNCTION. +# TYPE pg_settings_check_function_bodies gauge +pg_settings_check_function_bodies{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_checkpoint_completion_target Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval. +# TYPE pg_settings_checkpoint_completion_target gauge +pg_settings_checkpoint_completion_target{collector="exporter",server="127.0.0.1:5432"} 0.5 +# HELP pg_settings_checkpoint_flush_after_bytes Number of pages after which previously performed writes are flushed to disk. [Units converted to bytes.] +# TYPE pg_settings_checkpoint_flush_after_bytes gauge +pg_settings_checkpoint_flush_after_bytes{collector="exporter",server="127.0.0.1:5432"} 262144 +# HELP pg_settings_checkpoint_timeout_seconds Sets the maximum time between automatic WAL checkpoints. [Units converted to seconds.] +# TYPE pg_settings_checkpoint_timeout_seconds gauge +pg_settings_checkpoint_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 300 +# HELP pg_settings_checkpoint_warning_seconds Enables warnings if checkpoint segments are filled more frequently than this. [Units converted to seconds.] +# TYPE pg_settings_checkpoint_warning_seconds gauge +pg_settings_checkpoint_warning_seconds{collector="exporter",server="127.0.0.1:5432"} 30 +# HELP pg_settings_commit_delay Sets the delay in microseconds between transaction commit and flushing WAL to disk. +# TYPE pg_settings_commit_delay gauge +pg_settings_commit_delay{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_commit_siblings Sets the minimum concurrent open transactions before performing commit_delay. +# TYPE pg_settings_commit_siblings gauge +pg_settings_commit_siblings{collector="exporter",server="127.0.0.1:5432"} 5 +# HELP pg_settings_cpu_index_tuple_cost Sets the planner's estimate of the cost of processing each index entry during an index scan. +# TYPE pg_settings_cpu_index_tuple_cost gauge +pg_settings_cpu_index_tuple_cost{collector="exporter",server="127.0.0.1:5432"} 0.005 +# HELP pg_settings_cpu_operator_cost Sets the planner's estimate of the cost of processing each operator or function call. +# TYPE pg_settings_cpu_operator_cost gauge +pg_settings_cpu_operator_cost{collector="exporter",server="127.0.0.1:5432"} 0.0025 +# HELP pg_settings_cpu_tuple_cost Sets the planner's estimate of the cost of processing each tuple (row). +# TYPE pg_settings_cpu_tuple_cost gauge +pg_settings_cpu_tuple_cost{collector="exporter",server="127.0.0.1:5432"} 0.01 +# HELP pg_settings_cursor_tuple_fraction Sets the planner's estimate of the fraction of a cursor's rows that will be retrieved. +# TYPE pg_settings_cursor_tuple_fraction gauge +pg_settings_cursor_tuple_fraction{collector="exporter",server="127.0.0.1:5432"} 0.1 +# HELP pg_settings_data_checksums Shows whether data checksums are turned on for this cluster. +# TYPE pg_settings_data_checksums gauge +pg_settings_data_checksums{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_data_directory_mode Mode of the data directory. +# TYPE pg_settings_data_directory_mode gauge +pg_settings_data_directory_mode{collector="exporter",server="127.0.0.1:5432"} 700 +# HELP pg_settings_data_sync_retry Whether to continue running after a failure to sync data files. +# TYPE pg_settings_data_sync_retry gauge +pg_settings_data_sync_retry{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_db_user_namespace Enables per-database user names. +# TYPE pg_settings_db_user_namespace gauge +pg_settings_db_user_namespace{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_deadlock_timeout_seconds Sets the time to wait on a lock before checking for deadlock. [Units converted to seconds.] +# TYPE pg_settings_deadlock_timeout_seconds gauge +pg_settings_deadlock_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_debug_assertions Shows whether the running server has assertion checks enabled. +# TYPE pg_settings_debug_assertions gauge +pg_settings_debug_assertions{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_debug_pretty_print Indents parse and plan tree displays. +# TYPE pg_settings_debug_pretty_print gauge +pg_settings_debug_pretty_print{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_debug_print_parse Logs each query's parse tree. +# TYPE pg_settings_debug_print_parse gauge +pg_settings_debug_print_parse{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_debug_print_plan Logs each query's execution plan. +# TYPE pg_settings_debug_print_plan gauge +pg_settings_debug_print_plan{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_debug_print_rewritten Logs each query's rewritten parse tree. +# TYPE pg_settings_debug_print_rewritten gauge +pg_settings_debug_print_rewritten{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_default_statistics_target Sets the default statistics target. +# TYPE pg_settings_default_statistics_target gauge +pg_settings_default_statistics_target{collector="exporter",server="127.0.0.1:5432"} 100 +# HELP pg_settings_default_transaction_deferrable Sets the default deferrable status of new transactions. +# TYPE pg_settings_default_transaction_deferrable gauge +pg_settings_default_transaction_deferrable{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_default_transaction_read_only Sets the default read-only status of new transactions. +# TYPE pg_settings_default_transaction_read_only gauge +pg_settings_default_transaction_read_only{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_default_with_oids Create new tables with OIDs by default. +# TYPE pg_settings_default_with_oids gauge +pg_settings_default_with_oids{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_effective_cache_size_bytes Sets the planner's assumption about the total size of the data caches. [Units converted to bytes.] +# TYPE pg_settings_effective_cache_size_bytes gauge +pg_settings_effective_cache_size_bytes{collector="exporter",server="127.0.0.1:5432"} 4.294967296e+09 +# HELP pg_settings_effective_io_concurrency Number of simultaneous requests that can be handled efficiently by the disk subsystem. +# TYPE pg_settings_effective_io_concurrency gauge +pg_settings_effective_io_concurrency{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_bitmapscan Enables the planner's use of bitmap-scan plans. +# TYPE pg_settings_enable_bitmapscan gauge +pg_settings_enable_bitmapscan{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_gathermerge Enables the planner's use of gather merge plans. +# TYPE pg_settings_enable_gathermerge gauge +pg_settings_enable_gathermerge{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_hashagg Enables the planner's use of hashed aggregation plans. +# TYPE pg_settings_enable_hashagg gauge +pg_settings_enable_hashagg{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_hashjoin Enables the planner's use of hash join plans. +# TYPE pg_settings_enable_hashjoin gauge +pg_settings_enable_hashjoin{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_indexonlyscan Enables the planner's use of index-only-scan plans. +# TYPE pg_settings_enable_indexonlyscan gauge +pg_settings_enable_indexonlyscan{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_indexscan Enables the planner's use of index-scan plans. +# TYPE pg_settings_enable_indexscan gauge +pg_settings_enable_indexscan{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_material Enables the planner's use of materialization. +# TYPE pg_settings_enable_material gauge +pg_settings_enable_material{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_mergejoin Enables the planner's use of merge join plans. +# TYPE pg_settings_enable_mergejoin gauge +pg_settings_enable_mergejoin{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_nestloop Enables the planner's use of nested-loop join plans. +# TYPE pg_settings_enable_nestloop gauge +pg_settings_enable_nestloop{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_parallel_append Enables the planner's use of parallel append plans. +# TYPE pg_settings_enable_parallel_append gauge +pg_settings_enable_parallel_append{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_parallel_hash Enables the planner's use of parallel hash plans. +# TYPE pg_settings_enable_parallel_hash gauge +pg_settings_enable_parallel_hash{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_partition_pruning Enable plan-time and run-time partition pruning. +# TYPE pg_settings_enable_partition_pruning gauge +pg_settings_enable_partition_pruning{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_partitionwise_aggregate Enables partitionwise aggregation and grouping. +# TYPE pg_settings_enable_partitionwise_aggregate gauge +pg_settings_enable_partitionwise_aggregate{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_enable_partitionwise_join Enables partitionwise join. +# TYPE pg_settings_enable_partitionwise_join gauge +pg_settings_enable_partitionwise_join{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_enable_seqscan Enables the planner's use of sequential-scan plans. +# TYPE pg_settings_enable_seqscan gauge +pg_settings_enable_seqscan{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_sort Enables the planner's use of explicit sort steps. +# TYPE pg_settings_enable_sort gauge +pg_settings_enable_sort{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_enable_tidscan Enables the planner's use of TID scan plans. +# TYPE pg_settings_enable_tidscan gauge +pg_settings_enable_tidscan{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_escape_string_warning Warn about backslash escapes in ordinary string literals. +# TYPE pg_settings_escape_string_warning gauge +pg_settings_escape_string_warning{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_exit_on_error Terminate session on any error. +# TYPE pg_settings_exit_on_error gauge +pg_settings_exit_on_error{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_extra_float_digits Sets the number of digits displayed for floating-point values. +# TYPE pg_settings_extra_float_digits gauge +pg_settings_extra_float_digits{collector="exporter",server="127.0.0.1:5432"} 2 +# HELP pg_settings_from_collapse_limit Sets the FROM-list size beyond which subqueries are not collapsed. +# TYPE pg_settings_from_collapse_limit gauge +pg_settings_from_collapse_limit{collector="exporter",server="127.0.0.1:5432"} 8 +# HELP pg_settings_fsync Forces synchronization of updates to disk. +# TYPE pg_settings_fsync gauge +pg_settings_fsync{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_full_page_writes Writes full pages to WAL when first modified after a checkpoint. +# TYPE pg_settings_full_page_writes gauge +pg_settings_full_page_writes{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_geqo Enables genetic query optimization. +# TYPE pg_settings_geqo gauge +pg_settings_geqo{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_geqo_effort GEQO: effort is used to set the default for other GEQO parameters. +# TYPE pg_settings_geqo_effort gauge +pg_settings_geqo_effort{collector="exporter",server="127.0.0.1:5432"} 5 +# HELP pg_settings_geqo_generations GEQO: number of iterations of the algorithm. +# TYPE pg_settings_geqo_generations gauge +pg_settings_geqo_generations{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_geqo_pool_size GEQO: number of individuals in the population. +# TYPE pg_settings_geqo_pool_size gauge +pg_settings_geqo_pool_size{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_geqo_seed GEQO: seed for random path selection. +# TYPE pg_settings_geqo_seed gauge +pg_settings_geqo_seed{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_geqo_selection_bias GEQO: selective pressure within the population. +# TYPE pg_settings_geqo_selection_bias gauge +pg_settings_geqo_selection_bias{collector="exporter",server="127.0.0.1:5432"} 2 +# HELP pg_settings_geqo_threshold Sets the threshold of FROM items beyond which GEQO is used. +# TYPE pg_settings_geqo_threshold gauge +pg_settings_geqo_threshold{collector="exporter",server="127.0.0.1:5432"} 12 +# HELP pg_settings_gin_fuzzy_search_limit Sets the maximum allowed result for exact search by GIN. +# TYPE pg_settings_gin_fuzzy_search_limit gauge +pg_settings_gin_fuzzy_search_limit{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_gin_pending_list_limit_bytes Sets the maximum size of the pending list for GIN index. [Units converted to bytes.] +# TYPE pg_settings_gin_pending_list_limit_bytes gauge +pg_settings_gin_pending_list_limit_bytes{collector="exporter",server="127.0.0.1:5432"} 4.194304e+06 +# HELP pg_settings_hot_standby Allows connections and queries during recovery. +# TYPE pg_settings_hot_standby gauge +pg_settings_hot_standby{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_hot_standby_feedback Allows feedback from a hot standby to the primary that will avoid query conflicts. +# TYPE pg_settings_hot_standby_feedback gauge +pg_settings_hot_standby_feedback{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_idle_in_transaction_session_timeout_seconds Sets the maximum allowed duration of any idling transaction. [Units converted to seconds.] +# TYPE pg_settings_idle_in_transaction_session_timeout_seconds gauge +pg_settings_idle_in_transaction_session_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_ignore_checksum_failure Continues processing after a checksum failure. +# TYPE pg_settings_ignore_checksum_failure gauge +pg_settings_ignore_checksum_failure{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_ignore_system_indexes Disables reading from system indexes. +# TYPE pg_settings_ignore_system_indexes gauge +pg_settings_ignore_system_indexes{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_integer_datetimes Datetimes are integer based. +# TYPE pg_settings_integer_datetimes gauge +pg_settings_integer_datetimes{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_jit Allow JIT compilation. +# TYPE pg_settings_jit gauge +pg_settings_jit{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_jit_above_cost Perform JIT compilation if query is more expensive. +# TYPE pg_settings_jit_above_cost gauge +pg_settings_jit_above_cost{collector="exporter",server="127.0.0.1:5432"} 100000 +# HELP pg_settings_jit_debugging_support Register JIT compiled function with debugger. +# TYPE pg_settings_jit_debugging_support gauge +pg_settings_jit_debugging_support{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_jit_dump_bitcode Write out LLVM bitcode to facilitate JIT debugging. +# TYPE pg_settings_jit_dump_bitcode gauge +pg_settings_jit_dump_bitcode{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_jit_expressions Allow JIT compilation of expressions. +# TYPE pg_settings_jit_expressions gauge +pg_settings_jit_expressions{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_jit_inline_above_cost Perform JIT inlining if query is more expensive. +# TYPE pg_settings_jit_inline_above_cost gauge +pg_settings_jit_inline_above_cost{collector="exporter",server="127.0.0.1:5432"} 500000 +# HELP pg_settings_jit_optimize_above_cost Optimize JITed functions if query is more expensive. +# TYPE pg_settings_jit_optimize_above_cost gauge +pg_settings_jit_optimize_above_cost{collector="exporter",server="127.0.0.1:5432"} 500000 +# HELP pg_settings_jit_profiling_support Register JIT compiled function with perf profiler. +# TYPE pg_settings_jit_profiling_support gauge +pg_settings_jit_profiling_support{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_jit_tuple_deforming Allow JIT compilation of tuple deforming. +# TYPE pg_settings_jit_tuple_deforming gauge +pg_settings_jit_tuple_deforming{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_join_collapse_limit Sets the FROM-list size beyond which JOIN constructs are not flattened. +# TYPE pg_settings_join_collapse_limit gauge +pg_settings_join_collapse_limit{collector="exporter",server="127.0.0.1:5432"} 8 +# HELP pg_settings_krb_caseins_users Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive. +# TYPE pg_settings_krb_caseins_users gauge +pg_settings_krb_caseins_users{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_lo_compat_privileges Enables backward compatibility mode for privilege checks on large objects. +# TYPE pg_settings_lo_compat_privileges gauge +pg_settings_lo_compat_privileges{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_lock_timeout_seconds Sets the maximum allowed duration of any wait for a lock. [Units converted to seconds.] +# TYPE pg_settings_lock_timeout_seconds gauge +pg_settings_lock_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_autovacuum_min_duration_seconds Sets the minimum execution time above which autovacuum actions will be logged. [Units converted to seconds.] +# TYPE pg_settings_log_autovacuum_min_duration_seconds gauge +pg_settings_log_autovacuum_min_duration_seconds{collector="exporter",server="127.0.0.1:5432"} -1 +# HELP pg_settings_log_checkpoints Logs each checkpoint. +# TYPE pg_settings_log_checkpoints gauge +pg_settings_log_checkpoints{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_connections Logs each successful connection. +# TYPE pg_settings_log_connections gauge +pg_settings_log_connections{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_disconnections Logs end of a session, including duration. +# TYPE pg_settings_log_disconnections gauge +pg_settings_log_disconnections{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_duration Logs the duration of each completed SQL statement. +# TYPE pg_settings_log_duration gauge +pg_settings_log_duration{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_executor_stats Writes executor performance statistics to the server log. +# TYPE pg_settings_log_executor_stats gauge +pg_settings_log_executor_stats{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_file_mode Sets the file permissions for log files. +# TYPE pg_settings_log_file_mode gauge +pg_settings_log_file_mode{collector="exporter",server="127.0.0.1:5432"} 600 +# HELP pg_settings_log_hostname Logs the host name in the connection logs. +# TYPE pg_settings_log_hostname gauge +pg_settings_log_hostname{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_lock_waits Logs long lock waits. +# TYPE pg_settings_log_lock_waits gauge +pg_settings_log_lock_waits{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_min_duration_statement_seconds Sets the minimum execution time above which statements will be logged. [Units converted to seconds.] +# TYPE pg_settings_log_min_duration_statement_seconds gauge +pg_settings_log_min_duration_statement_seconds{collector="exporter",server="127.0.0.1:5432"} -1 +# HELP pg_settings_log_parser_stats Writes parser performance statistics to the server log. +# TYPE pg_settings_log_parser_stats gauge +pg_settings_log_parser_stats{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_planner_stats Writes planner performance statistics to the server log. +# TYPE pg_settings_log_planner_stats gauge +pg_settings_log_planner_stats{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_replication_commands Logs each replication command. +# TYPE pg_settings_log_replication_commands gauge +pg_settings_log_replication_commands{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_rotation_age_seconds Automatic log file rotation will occur after N minutes. [Units converted to seconds.] +# TYPE pg_settings_log_rotation_age_seconds gauge +pg_settings_log_rotation_age_seconds{collector="exporter",server="127.0.0.1:5432"} 86400 +# HELP pg_settings_log_rotation_size_bytes Automatic log file rotation will occur after N kilobytes. [Units converted to bytes.] +# TYPE pg_settings_log_rotation_size_bytes gauge +pg_settings_log_rotation_size_bytes{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_statement_stats Writes cumulative performance statistics to the server log. +# TYPE pg_settings_log_statement_stats gauge +pg_settings_log_statement_stats{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_log_temp_files_bytes Log the use of temporary files larger than this number of kilobytes. [Units converted to bytes.] +# TYPE pg_settings_log_temp_files_bytes gauge +pg_settings_log_temp_files_bytes{collector="exporter",server="127.0.0.1:5432"} -1 +# HELP pg_settings_log_truncate_on_rotation Truncate existing log files of same name during log rotation. +# TYPE pg_settings_log_truncate_on_rotation gauge +pg_settings_log_truncate_on_rotation{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_logging_collector Start a subprocess to capture stderr output and/or csvlogs into log files. +# TYPE pg_settings_logging_collector gauge +pg_settings_logging_collector{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_maintenance_work_mem_bytes Sets the maximum memory to be used for maintenance operations. [Units converted to bytes.] +# TYPE pg_settings_maintenance_work_mem_bytes gauge +pg_settings_maintenance_work_mem_bytes{collector="exporter",server="127.0.0.1:5432"} 6.7108864e+07 +# HELP pg_settings_max_connections Sets the maximum number of concurrent connections. +# TYPE pg_settings_max_connections gauge +pg_settings_max_connections{collector="exporter",server="127.0.0.1:5432"} 100 +# HELP pg_settings_max_files_per_process Sets the maximum number of simultaneously open files for each server process. +# TYPE pg_settings_max_files_per_process gauge +pg_settings_max_files_per_process{collector="exporter",server="127.0.0.1:5432"} 1000 +# HELP pg_settings_max_function_args Shows the maximum number of function arguments. +# TYPE pg_settings_max_function_args gauge +pg_settings_max_function_args{collector="exporter",server="127.0.0.1:5432"} 100 +# HELP pg_settings_max_identifier_length Shows the maximum identifier length. +# TYPE pg_settings_max_identifier_length gauge +pg_settings_max_identifier_length{collector="exporter",server="127.0.0.1:5432"} 63 +# HELP pg_settings_max_index_keys Shows the maximum number of index keys. +# TYPE pg_settings_max_index_keys gauge +pg_settings_max_index_keys{collector="exporter",server="127.0.0.1:5432"} 32 +# HELP pg_settings_max_locks_per_transaction Sets the maximum number of locks per transaction. +# TYPE pg_settings_max_locks_per_transaction gauge +pg_settings_max_locks_per_transaction{collector="exporter",server="127.0.0.1:5432"} 64 +# HELP pg_settings_max_logical_replication_workers Maximum number of logical replication worker processes. +# TYPE pg_settings_max_logical_replication_workers gauge +pg_settings_max_logical_replication_workers{collector="exporter",server="127.0.0.1:5432"} 4 +# HELP pg_settings_max_parallel_maintenance_workers Sets the maximum number of parallel processes per maintenance operation. +# TYPE pg_settings_max_parallel_maintenance_workers gauge +pg_settings_max_parallel_maintenance_workers{collector="exporter",server="127.0.0.1:5432"} 2 +# HELP pg_settings_max_parallel_workers Sets the maximum number of parallel workers that can be active at one time. +# TYPE pg_settings_max_parallel_workers gauge +pg_settings_max_parallel_workers{collector="exporter",server="127.0.0.1:5432"} 8 +# HELP pg_settings_max_parallel_workers_per_gather Sets the maximum number of parallel processes per executor node. +# TYPE pg_settings_max_parallel_workers_per_gather gauge +pg_settings_max_parallel_workers_per_gather{collector="exporter",server="127.0.0.1:5432"} 2 +# HELP pg_settings_max_pred_locks_per_page Sets the maximum number of predicate-locked tuples per page. +# TYPE pg_settings_max_pred_locks_per_page gauge +pg_settings_max_pred_locks_per_page{collector="exporter",server="127.0.0.1:5432"} 2 +# HELP pg_settings_max_pred_locks_per_relation Sets the maximum number of predicate-locked pages and tuples per relation. +# TYPE pg_settings_max_pred_locks_per_relation gauge +pg_settings_max_pred_locks_per_relation{collector="exporter",server="127.0.0.1:5432"} -2 +# HELP pg_settings_max_pred_locks_per_transaction Sets the maximum number of predicate locks per transaction. +# TYPE pg_settings_max_pred_locks_per_transaction gauge +pg_settings_max_pred_locks_per_transaction{collector="exporter",server="127.0.0.1:5432"} 64 +# HELP pg_settings_max_prepared_transactions Sets the maximum number of simultaneously prepared transactions. +# TYPE pg_settings_max_prepared_transactions gauge +pg_settings_max_prepared_transactions{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_max_replication_slots Sets the maximum number of simultaneously defined replication slots. +# TYPE pg_settings_max_replication_slots gauge +pg_settings_max_replication_slots{collector="exporter",server="127.0.0.1:5432"} 10 +# HELP pg_settings_max_stack_depth_bytes Sets the maximum stack depth, in kilobytes. [Units converted to bytes.] +# TYPE pg_settings_max_stack_depth_bytes gauge +pg_settings_max_stack_depth_bytes{collector="exporter",server="127.0.0.1:5432"} 2.097152e+06 +# HELP pg_settings_max_standby_archive_delay_seconds Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data. [Units converted to seconds.] +# TYPE pg_settings_max_standby_archive_delay_seconds gauge +pg_settings_max_standby_archive_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 30 +# HELP pg_settings_max_standby_streaming_delay_seconds Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data. [Units converted to seconds.] +# TYPE pg_settings_max_standby_streaming_delay_seconds gauge +pg_settings_max_standby_streaming_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 30 +# HELP pg_settings_max_sync_workers_per_subscription Maximum number of table synchronization workers per subscription. +# TYPE pg_settings_max_sync_workers_per_subscription gauge +pg_settings_max_sync_workers_per_subscription{collector="exporter",server="127.0.0.1:5432"} 2 +# HELP pg_settings_max_wal_senders Sets the maximum number of simultaneously running WAL sender processes. +# TYPE pg_settings_max_wal_senders gauge +pg_settings_max_wal_senders{collector="exporter",server="127.0.0.1:5432"} 10 +# HELP pg_settings_max_wal_size_bytes Sets the WAL size that triggers a checkpoint. [Units converted to bytes.] +# TYPE pg_settings_max_wal_size_bytes gauge +pg_settings_max_wal_size_bytes{collector="exporter",server="127.0.0.1:5432"} 1.073741824e+09 +# HELP pg_settings_max_worker_processes Maximum number of concurrent worker processes. +# TYPE pg_settings_max_worker_processes gauge +pg_settings_max_worker_processes{collector="exporter",server="127.0.0.1:5432"} 8 +# HELP pg_settings_min_parallel_index_scan_size_bytes Sets the minimum amount of index data for a parallel scan. [Units converted to bytes.] +# TYPE pg_settings_min_parallel_index_scan_size_bytes gauge +pg_settings_min_parallel_index_scan_size_bytes{collector="exporter",server="127.0.0.1:5432"} 524288 +# HELP pg_settings_min_parallel_table_scan_size_bytes Sets the minimum amount of table data for a parallel scan. [Units converted to bytes.] +# TYPE pg_settings_min_parallel_table_scan_size_bytes gauge +pg_settings_min_parallel_table_scan_size_bytes{collector="exporter",server="127.0.0.1:5432"} 8.388608e+06 +# HELP pg_settings_min_wal_size_bytes Sets the minimum size to shrink the WAL to. [Units converted to bytes.] +# TYPE pg_settings_min_wal_size_bytes gauge +pg_settings_min_wal_size_bytes{collector="exporter",server="127.0.0.1:5432"} 8.388608e+07 +# HELP pg_settings_old_snapshot_threshold_seconds Time before a snapshot is too old to read pages changed after the snapshot was taken. [Units converted to seconds.] +# TYPE pg_settings_old_snapshot_threshold_seconds gauge +pg_settings_old_snapshot_threshold_seconds{collector="exporter",server="127.0.0.1:5432"} -1 +# HELP pg_settings_operator_precedence_warning Emit a warning for constructs that changed meaning since PostgreSQL 9.4. +# TYPE pg_settings_operator_precedence_warning gauge +pg_settings_operator_precedence_warning{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_parallel_leader_participation Controls whether Gather and Gather Merge also run subplans. +# TYPE pg_settings_parallel_leader_participation gauge +pg_settings_parallel_leader_participation{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_parallel_setup_cost Sets the planner's estimate of the cost of starting up worker processes for parallel query. +# TYPE pg_settings_parallel_setup_cost gauge +pg_settings_parallel_setup_cost{collector="exporter",server="127.0.0.1:5432"} 1000 +# HELP pg_settings_parallel_tuple_cost Sets the planner's estimate of the cost of passing each tuple (row) from worker to master backend. +# TYPE pg_settings_parallel_tuple_cost gauge +pg_settings_parallel_tuple_cost{collector="exporter",server="127.0.0.1:5432"} 0.1 +# HELP pg_settings_pg_stat_statements_max Sets the maximum number of statements tracked by pg_stat_statements. +# TYPE pg_settings_pg_stat_statements_max gauge +pg_settings_pg_stat_statements_max{collector="exporter",server="127.0.0.1:5432"} 10000 +# HELP pg_settings_pg_stat_statements_save Save pg_stat_statements statistics across server shutdowns. +# TYPE pg_settings_pg_stat_statements_save gauge +pg_settings_pg_stat_statements_save{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_pg_stat_statements_track_utility Selects whether utility commands are tracked by pg_stat_statements. +# TYPE pg_settings_pg_stat_statements_track_utility gauge +pg_settings_pg_stat_statements_track_utility{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_port Sets the TCP port the server listens on. +# TYPE pg_settings_port gauge +pg_settings_port{collector="exporter",server="127.0.0.1:5432"} 5432 +# HELP pg_settings_post_auth_delay_seconds Waits N seconds on connection startup after authentication. [Units converted to seconds.] +# TYPE pg_settings_post_auth_delay_seconds gauge +pg_settings_post_auth_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_pre_auth_delay_seconds Waits N seconds on connection startup before authentication. [Units converted to seconds.] +# TYPE pg_settings_pre_auth_delay_seconds gauge +pg_settings_pre_auth_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_quote_all_identifiers When generating SQL fragments, quote all identifiers. +# TYPE pg_settings_quote_all_identifiers gauge +pg_settings_quote_all_identifiers{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_random_page_cost Sets the planner's estimate of the cost of a nonsequentially fetched disk page. +# TYPE pg_settings_random_page_cost gauge +pg_settings_random_page_cost{collector="exporter",server="127.0.0.1:5432"} 4 +# HELP pg_settings_restart_after_crash Reinitialize server after backend crash. +# TYPE pg_settings_restart_after_crash gauge +pg_settings_restart_after_crash{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_row_security Enable row security. +# TYPE pg_settings_row_security gauge +pg_settings_row_security{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_segment_size_bytes Shows the number of pages per disk file. [Units converted to bytes.] +# TYPE pg_settings_segment_size_bytes gauge +pg_settings_segment_size_bytes{collector="exporter",server="127.0.0.1:5432"} 1.073741824e+09 +# HELP pg_settings_seq_page_cost Sets the planner's estimate of the cost of a sequentially fetched disk page. +# TYPE pg_settings_seq_page_cost gauge +pg_settings_seq_page_cost{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_server_version_num Shows the server version as an integer. +# TYPE pg_settings_server_version_num gauge +pg_settings_server_version_num{collector="exporter",server="127.0.0.1:5432"} 110015 +# HELP pg_settings_shared_buffers_bytes Sets the number of shared memory buffers used by the server. [Units converted to bytes.] +# TYPE pg_settings_shared_buffers_bytes gauge +pg_settings_shared_buffers_bytes{collector="exporter",server="127.0.0.1:5432"} 1.34217728e+08 +# HELP pg_settings_ssl Enables SSL connections. +# TYPE pg_settings_ssl gauge +pg_settings_ssl{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_ssl_passphrase_command_supports_reload Also use ssl_passphrase_command during server reload. +# TYPE pg_settings_ssl_passphrase_command_supports_reload gauge +pg_settings_ssl_passphrase_command_supports_reload{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_ssl_prefer_server_ciphers Give priority to server ciphersuite order. +# TYPE pg_settings_ssl_prefer_server_ciphers gauge +pg_settings_ssl_prefer_server_ciphers{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_standard_conforming_strings Causes '...' strings to treat backslashes literally. +# TYPE pg_settings_standard_conforming_strings gauge +pg_settings_standard_conforming_strings{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_statement_timeout_seconds Sets the maximum allowed duration of any statement. [Units converted to seconds.] +# TYPE pg_settings_statement_timeout_seconds gauge +pg_settings_statement_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_superuser_reserved_connections Sets the number of connection slots reserved for superusers. +# TYPE pg_settings_superuser_reserved_connections gauge +pg_settings_superuser_reserved_connections{collector="exporter",server="127.0.0.1:5432"} 3 +# HELP pg_settings_synchronize_seqscans Enable synchronized sequential scans. +# TYPE pg_settings_synchronize_seqscans gauge +pg_settings_synchronize_seqscans{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_syslog_sequence_numbers Add sequence number to syslog messages to avoid duplicate suppression. +# TYPE pg_settings_syslog_sequence_numbers gauge +pg_settings_syslog_sequence_numbers{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_syslog_split_messages Split messages sent to syslog by lines and to fit into 1024 bytes. +# TYPE pg_settings_syslog_split_messages gauge +pg_settings_syslog_split_messages{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_tcp_keepalives_count Maximum number of TCP keepalive retransmits. +# TYPE pg_settings_tcp_keepalives_count gauge +pg_settings_tcp_keepalives_count{collector="exporter",server="127.0.0.1:5432"} 9 +# HELP pg_settings_tcp_keepalives_idle_seconds Time between issuing TCP keepalives. [Units converted to seconds.] +# TYPE pg_settings_tcp_keepalives_idle_seconds gauge +pg_settings_tcp_keepalives_idle_seconds{collector="exporter",server="127.0.0.1:5432"} 7200 +# HELP pg_settings_tcp_keepalives_interval_seconds Time between TCP keepalive retransmits. [Units converted to seconds.] +# TYPE pg_settings_tcp_keepalives_interval_seconds gauge +pg_settings_tcp_keepalives_interval_seconds{collector="exporter",server="127.0.0.1:5432"} 75 +# HELP pg_settings_temp_buffers_bytes Sets the maximum number of temporary buffers used by each session. [Units converted to bytes.] +# TYPE pg_settings_temp_buffers_bytes gauge +pg_settings_temp_buffers_bytes{collector="exporter",server="127.0.0.1:5432"} 8.388608e+06 +# HELP pg_settings_temp_file_limit_bytes Limits the total size of all temporary files used by each process. [Units converted to bytes.] +# TYPE pg_settings_temp_file_limit_bytes gauge +pg_settings_temp_file_limit_bytes{collector="exporter",server="127.0.0.1:5432"} -1 +# HELP pg_settings_trace_notify Generates debugging output for LISTEN and NOTIFY. +# TYPE pg_settings_trace_notify gauge +pg_settings_trace_notify{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_trace_sort Emit information about resource usage in sorting. +# TYPE pg_settings_trace_sort gauge +pg_settings_trace_sort{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_track_activities Collects information about executing commands. +# TYPE pg_settings_track_activities gauge +pg_settings_track_activities{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_track_activity_query_size_bytes Sets the size reserved for pg_stat_activity.query, in bytes. [Units converted to bytes.] +# TYPE pg_settings_track_activity_query_size_bytes gauge +pg_settings_track_activity_query_size_bytes{collector="exporter",server="127.0.0.1:5432"} 1024 +# HELP pg_settings_track_commit_timestamp Collects transaction commit time. +# TYPE pg_settings_track_commit_timestamp gauge +pg_settings_track_commit_timestamp{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_track_counts Collects statistics on database activity. +# TYPE pg_settings_track_counts gauge +pg_settings_track_counts{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_track_io_timing Collects timing statistics for database I/O activity. +# TYPE pg_settings_track_io_timing gauge +pg_settings_track_io_timing{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_transaction_deferrable Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures. +# TYPE pg_settings_transaction_deferrable gauge +pg_settings_transaction_deferrable{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_transaction_read_only Sets the current transaction's read-only status. +# TYPE pg_settings_transaction_read_only gauge +pg_settings_transaction_read_only{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_transform_null_equals Treats "expr=NULL" as "expr IS NULL". +# TYPE pg_settings_transform_null_equals gauge +pg_settings_transform_null_equals{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_unix_socket_permissions Sets the access permissions of the Unix-domain socket. +# TYPE pg_settings_unix_socket_permissions gauge +pg_settings_unix_socket_permissions{collector="exporter",server="127.0.0.1:5432"} 777 +# HELP pg_settings_update_process_title Updates the process title to show the active SQL command. +# TYPE pg_settings_update_process_title gauge +pg_settings_update_process_title{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_vacuum_cleanup_index_scale_factor Number of tuple inserts prior to index cleanup as a fraction of reltuples. +# TYPE pg_settings_vacuum_cleanup_index_scale_factor gauge +pg_settings_vacuum_cleanup_index_scale_factor{collector="exporter",server="127.0.0.1:5432"} 0.1 +# HELP pg_settings_vacuum_cost_delay_seconds Vacuum cost delay in milliseconds. [Units converted to seconds.] +# TYPE pg_settings_vacuum_cost_delay_seconds gauge +pg_settings_vacuum_cost_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_vacuum_cost_limit Vacuum cost amount available before napping. +# TYPE pg_settings_vacuum_cost_limit gauge +pg_settings_vacuum_cost_limit{collector="exporter",server="127.0.0.1:5432"} 200 +# HELP pg_settings_vacuum_cost_page_dirty Vacuum cost for a page dirtied by vacuum. +# TYPE pg_settings_vacuum_cost_page_dirty gauge +pg_settings_vacuum_cost_page_dirty{collector="exporter",server="127.0.0.1:5432"} 20 +# HELP pg_settings_vacuum_cost_page_hit Vacuum cost for a page found in the buffer cache. +# TYPE pg_settings_vacuum_cost_page_hit gauge +pg_settings_vacuum_cost_page_hit{collector="exporter",server="127.0.0.1:5432"} 1 +# HELP pg_settings_vacuum_cost_page_miss Vacuum cost for a page not found in the buffer cache. +# TYPE pg_settings_vacuum_cost_page_miss gauge +pg_settings_vacuum_cost_page_miss{collector="exporter",server="127.0.0.1:5432"} 10 +# HELP pg_settings_vacuum_defer_cleanup_age Number of transactions by which VACUUM and HOT cleanup should be deferred, if any. +# TYPE pg_settings_vacuum_defer_cleanup_age gauge +pg_settings_vacuum_defer_cleanup_age{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_vacuum_freeze_min_age Minimum age at which VACUUM should freeze a table row. +# TYPE pg_settings_vacuum_freeze_min_age gauge +pg_settings_vacuum_freeze_min_age{collector="exporter",server="127.0.0.1:5432"} 5e+07 +# HELP pg_settings_vacuum_freeze_table_age Age at which VACUUM should scan whole table to freeze tuples. +# TYPE pg_settings_vacuum_freeze_table_age gauge +pg_settings_vacuum_freeze_table_age{collector="exporter",server="127.0.0.1:5432"} 1.5e+08 +# HELP pg_settings_vacuum_multixact_freeze_min_age Minimum age at which VACUUM should freeze a MultiXactId in a table row. +# TYPE pg_settings_vacuum_multixact_freeze_min_age gauge +pg_settings_vacuum_multixact_freeze_min_age{collector="exporter",server="127.0.0.1:5432"} 5e+06 +# HELP pg_settings_vacuum_multixact_freeze_table_age Multixact age at which VACUUM should scan whole table to freeze tuples. +# TYPE pg_settings_vacuum_multixact_freeze_table_age gauge +pg_settings_vacuum_multixact_freeze_table_age{collector="exporter",server="127.0.0.1:5432"} 1.5e+08 +# HELP pg_settings_wal_block_size Shows the block size in the write ahead log. +# TYPE pg_settings_wal_block_size gauge +pg_settings_wal_block_size{collector="exporter",server="127.0.0.1:5432"} 8192 +# HELP pg_settings_wal_buffers_bytes Sets the number of disk-page buffers in shared memory for WAL. [Units converted to bytes.] +# TYPE pg_settings_wal_buffers_bytes gauge +pg_settings_wal_buffers_bytes{collector="exporter",server="127.0.0.1:5432"} 4.194304e+06 +# HELP pg_settings_wal_compression Compresses full-page writes written in WAL file. +# TYPE pg_settings_wal_compression gauge +pg_settings_wal_compression{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_wal_keep_segments Sets the number of WAL files held for standby servers. +# TYPE pg_settings_wal_keep_segments gauge +pg_settings_wal_keep_segments{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_wal_log_hints Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification. +# TYPE pg_settings_wal_log_hints gauge +pg_settings_wal_log_hints{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_settings_wal_receiver_status_interval_seconds Sets the maximum interval between WAL receiver status reports to the primary. [Units converted to seconds.] +# TYPE pg_settings_wal_receiver_status_interval_seconds gauge +pg_settings_wal_receiver_status_interval_seconds{collector="exporter",server="127.0.0.1:5432"} 10 +# HELP pg_settings_wal_receiver_timeout_seconds Sets the maximum wait time to receive data from the primary. [Units converted to seconds.] +# TYPE pg_settings_wal_receiver_timeout_seconds gauge +pg_settings_wal_receiver_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 60 +# HELP pg_settings_wal_retrieve_retry_interval_seconds Sets the time to wait before retrying to retrieve WAL after a failed attempt. [Units converted to seconds.] +# TYPE pg_settings_wal_retrieve_retry_interval_seconds gauge +pg_settings_wal_retrieve_retry_interval_seconds{collector="exporter",server="127.0.0.1:5432"} 5 +# HELP pg_settings_wal_segment_size_bytes Shows the size of write ahead log segments. [Units converted to bytes.] +# TYPE pg_settings_wal_segment_size_bytes gauge +pg_settings_wal_segment_size_bytes{collector="exporter",server="127.0.0.1:5432"} 1.6777216e+07 +# HELP pg_settings_wal_sender_timeout_seconds Sets the maximum time to wait for WAL replication. [Units converted to seconds.] +# TYPE pg_settings_wal_sender_timeout_seconds gauge +pg_settings_wal_sender_timeout_seconds{collector="exporter",server="127.0.0.1:5432"} 60 +# HELP pg_settings_wal_writer_delay_seconds Time between WAL flushes performed in the WAL writer. [Units converted to seconds.] +# TYPE pg_settings_wal_writer_delay_seconds gauge +pg_settings_wal_writer_delay_seconds{collector="exporter",server="127.0.0.1:5432"} 0.2 +# HELP pg_settings_wal_writer_flush_after_bytes Amount of WAL written out by WAL writer that triggers a flush. [Units converted to bytes.] +# TYPE pg_settings_wal_writer_flush_after_bytes gauge +pg_settings_wal_writer_flush_after_bytes{collector="exporter",server="127.0.0.1:5432"} 1.048576e+06 +# HELP pg_settings_work_mem_bytes Sets the maximum memory to be used for query workspaces. [Units converted to bytes.] +# TYPE pg_settings_work_mem_bytes gauge +pg_settings_work_mem_bytes{collector="exporter",server="127.0.0.1:5432"} 4.194304e+06 +# HELP pg_settings_zero_damaged_pages Continues processing past damaged page headers. +# TYPE pg_settings_zero_damaged_pages gauge +pg_settings_zero_damaged_pages{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_stat_activity_count number of connections in this state +# TYPE pg_stat_activity_count gauge +pg_stat_activity_count{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="active"} 0 +pg_stat_activity_count{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_count{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_count{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="idle"} 4 +pg_stat_activity_count{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_count{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +pg_stat_activity_count{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="active"} 1 +pg_stat_activity_count{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_count{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_count{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="idle"} 1 +pg_stat_activity_count{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_count{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +pg_stat_activity_count{collector="exporter",datname="template0",server="127.0.0.1:5432",state="active"} 0 +pg_stat_activity_count{collector="exporter",datname="template0",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_count{collector="exporter",datname="template0",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_count{collector="exporter",datname="template0",server="127.0.0.1:5432",state="idle"} 0 +pg_stat_activity_count{collector="exporter",datname="template0",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_count{collector="exporter",datname="template0",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +pg_stat_activity_count{collector="exporter",datname="template1",server="127.0.0.1:5432",state="active"} 0 +pg_stat_activity_count{collector="exporter",datname="template1",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_count{collector="exporter",datname="template1",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_count{collector="exporter",datname="template1",server="127.0.0.1:5432",state="idle"} 0 +pg_stat_activity_count{collector="exporter",datname="template1",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_count{collector="exporter",datname="template1",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +# HELP pg_stat_activity_max_tx_duration max duration in seconds any active transaction has been running +# TYPE pg_stat_activity_max_tx_duration gauge +pg_stat_activity_max_tx_duration{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="active"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="idle"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="pmm-managed",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="active"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="idle"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="postgres",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template0",server="127.0.0.1:5432",state="active"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template0",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template0",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template0",server="127.0.0.1:5432",state="idle"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template0",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template0",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template1",server="127.0.0.1:5432",state="active"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template1",server="127.0.0.1:5432",state="disabled"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template1",server="127.0.0.1:5432",state="fastpath function call"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template1",server="127.0.0.1:5432",state="idle"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template1",server="127.0.0.1:5432",state="idle in transaction"} 0 +pg_stat_activity_max_tx_duration{collector="exporter",datname="template1",server="127.0.0.1:5432",state="idle in transaction (aborted)"} 0 +# HELP pg_stat_archiver_archived_count Number of WAL files that have been successfully archived +# TYPE pg_stat_archiver_archived_count counter +pg_stat_archiver_archived_count{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_stat_archiver_failed_count Number of failed attempts for archiving WAL files +# TYPE pg_stat_archiver_failed_count counter +pg_stat_archiver_failed_count{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_stat_archiver_last_archive_age Time in seconds since last WAL segment was successfully archived +# TYPE pg_stat_archiver_last_archive_age gauge +pg_stat_archiver_last_archive_age{collector="exporter",server="127.0.0.1:5432"} NaN +# HELP pg_stat_bgwriter_buffers_alloc Number of buffers allocated +# TYPE pg_stat_bgwriter_buffers_alloc counter +pg_stat_bgwriter_buffers_alloc{collector="exporter",server="127.0.0.1:5432"} 2780 +# HELP pg_stat_bgwriter_buffers_backend Number of buffers written directly by a backend +# TYPE pg_stat_bgwriter_buffers_backend counter +pg_stat_bgwriter_buffers_backend{collector="exporter",server="127.0.0.1:5432"} 134 +# HELP pg_stat_bgwriter_buffers_backend_fsync Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write) +# TYPE pg_stat_bgwriter_buffers_backend_fsync counter +pg_stat_bgwriter_buffers_backend_fsync{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_stat_bgwriter_buffers_checkpoint Number of buffers written during checkpoints +# TYPE pg_stat_bgwriter_buffers_checkpoint counter +pg_stat_bgwriter_buffers_checkpoint{collector="exporter",server="127.0.0.1:5432"} 313 +# HELP pg_stat_bgwriter_buffers_clean Number of buffers written by the background writer +# TYPE pg_stat_bgwriter_buffers_clean counter +pg_stat_bgwriter_buffers_clean{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_stat_bgwriter_checkpoint_sync_time Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds +# TYPE pg_stat_bgwriter_checkpoint_sync_time counter +pg_stat_bgwriter_checkpoint_sync_time{collector="exporter",server="127.0.0.1:5432"} 289 +# HELP pg_stat_bgwriter_checkpoint_write_time Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds +# TYPE pg_stat_bgwriter_checkpoint_write_time counter +pg_stat_bgwriter_checkpoint_write_time{collector="exporter",server="127.0.0.1:5432"} 14240 +# HELP pg_stat_bgwriter_checkpoints_req Number of requested checkpoints that have been performed +# TYPE pg_stat_bgwriter_checkpoints_req counter +pg_stat_bgwriter_checkpoints_req{collector="exporter",server="127.0.0.1:5432"} 11 +# HELP pg_stat_bgwriter_checkpoints_timed Number of scheduled checkpoints that have been performed +# TYPE pg_stat_bgwriter_checkpoints_timed counter +pg_stat_bgwriter_checkpoints_timed{collector="exporter",server="127.0.0.1:5432"} 101 +# HELP pg_stat_bgwriter_maxwritten_clean Number of times the background writer stopped a cleaning scan because it had written too many buffers +# TYPE pg_stat_bgwriter_maxwritten_clean counter +pg_stat_bgwriter_maxwritten_clean{collector="exporter",server="127.0.0.1:5432"} 0 +# HELP pg_stat_bgwriter_stats_reset Time at which these statistics were last reset +# TYPE pg_stat_bgwriter_stats_reset counter +pg_stat_bgwriter_stats_reset{collector="exporter",server="127.0.0.1:5432"} 1.652203015e+09 +# HELP pg_stat_database_blk_read_time Time spent reading data file blocks by backends in this database, in milliseconds +# TYPE pg_stat_database_blk_read_time counter +pg_stat_database_blk_read_time{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_blk_read_time{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_blk_read_time{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_blk_read_time{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_blk_write_time Time spent writing data file blocks by backends in this database, in milliseconds +# TYPE pg_stat_database_blk_write_time counter +pg_stat_database_blk_write_time{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_blk_write_time{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_blk_write_time{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_blk_write_time{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_blks_hit Number of times disk blocks were found already in the buffer cache, so that a read was not necessary (this only includes hits in the PostgreSQL buffer cache, not the operating system's file system cache) +# TYPE pg_stat_database_blks_hit counter +pg_stat_database_blks_hit{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_blks_hit{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 3.9363176e+07 +pg_stat_database_blks_hit{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_blks_hit{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 1.0442909e+07 +# HELP pg_stat_database_blks_read Number of disk blocks read in this database +# TYPE pg_stat_database_blks_read counter +pg_stat_database_blks_read{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_blks_read{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 779 +pg_stat_database_blks_read{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_blks_read{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 729 +# HELP pg_stat_database_conflicts Number of queries canceled due to conflicts with recovery in this database. (Conflicts occur only on standby servers; see pg_stat_database_conflicts for details.) +# TYPE pg_stat_database_conflicts counter +pg_stat_database_conflicts{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_conflicts_confl_bufferpin Number of queries in this database that have been canceled due to pinned buffers +# TYPE pg_stat_database_conflicts_confl_bufferpin counter +pg_stat_database_conflicts_confl_bufferpin{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_bufferpin{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_bufferpin{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_bufferpin{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_conflicts_confl_deadlock Number of queries in this database that have been canceled due to deadlocks +# TYPE pg_stat_database_conflicts_confl_deadlock counter +pg_stat_database_conflicts_confl_deadlock{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_deadlock{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_deadlock{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_deadlock{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_conflicts_confl_lock Number of queries in this database that have been canceled due to lock timeouts +# TYPE pg_stat_database_conflicts_confl_lock counter +pg_stat_database_conflicts_confl_lock{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_lock{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_lock{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_lock{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_conflicts_confl_snapshot Number of queries in this database that have been canceled due to old snapshots +# TYPE pg_stat_database_conflicts_confl_snapshot counter +pg_stat_database_conflicts_confl_snapshot{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_snapshot{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_snapshot{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_snapshot{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_conflicts_confl_tablespace Number of queries in this database that have been canceled due to dropped tablespaces +# TYPE pg_stat_database_conflicts_confl_tablespace counter +pg_stat_database_conflicts_confl_tablespace{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_tablespace{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_tablespace{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_conflicts_confl_tablespace{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_deadlocks Number of deadlocks detected in this database +# TYPE pg_stat_database_deadlocks counter +pg_stat_database_deadlocks{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_deadlocks{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_deadlocks{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_deadlocks{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_numbackends Number of backends currently connected to this database. This is the only column in this view that returns a value reflecting current state; all other columns return the accumulated values since the last reset. +# TYPE pg_stat_database_numbackends gauge +pg_stat_database_numbackends{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_numbackends{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 2 +pg_stat_database_numbackends{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_numbackends{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 5 +# HELP pg_stat_database_stats_reset Time at which these statistics were last reset +# TYPE pg_stat_database_stats_reset counter +pg_stat_database_stats_reset{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} NaN +pg_stat_database_stats_reset{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 1.652203015e+09 +pg_stat_database_stats_reset{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} NaN +pg_stat_database_stats_reset{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 1.653392185e+09 +# HELP pg_stat_database_temp_bytes Total amount of data written to temporary files by queries in this database. All temporary files are counted, regardless of why the temporary file was created, and regardless of the log_temp_files setting. +# TYPE pg_stat_database_temp_bytes counter +pg_stat_database_temp_bytes{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_temp_bytes{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_temp_bytes{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_temp_bytes{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_temp_files Number of temporary files created by queries in this database. All temporary files are counted, regardless of why the temporary file was created (e.g., sorting or hashing), and regardless of the log_temp_files setting. +# TYPE pg_stat_database_temp_files counter +pg_stat_database_temp_files{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_temp_files{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_temp_files{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_temp_files{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 0 +# HELP pg_stat_database_tup_deleted Number of rows deleted by queries in this database +# TYPE pg_stat_database_tup_deleted counter +pg_stat_database_tup_deleted{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_deleted{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_deleted{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_deleted{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 287 +# HELP pg_stat_database_tup_fetched Number of rows fetched by queries in this database +# TYPE pg_stat_database_tup_fetched counter +pg_stat_database_tup_fetched{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_fetched{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 2.2538965e+07 +pg_stat_database_tup_fetched{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_fetched{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 5.006609e+06 +# HELP pg_stat_database_tup_inserted Number of rows inserted by queries in this database +# TYPE pg_stat_database_tup_inserted counter +pg_stat_database_tup_inserted{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_inserted{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 45 +pg_stat_database_tup_inserted{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_inserted{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 1609 +# HELP pg_stat_database_tup_returned Number of rows returned by queries in this database +# TYPE pg_stat_database_tup_returned counter +pg_stat_database_tup_returned{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_returned{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 2.7595554e+07 +pg_stat_database_tup_returned{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_returned{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 1.6754938e+07 +# HELP pg_stat_database_tup_updated Number of rows updated by queries in this database +# TYPE pg_stat_database_tup_updated counter +pg_stat_database_tup_updated{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_updated{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 9 +pg_stat_database_tup_updated{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_tup_updated{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 1584 +# HELP pg_stat_database_xact_commit Number of transactions in this database that have been committed +# TYPE pg_stat_database_xact_commit counter +pg_stat_database_xact_commit{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_xact_commit{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 523898 +pg_stat_database_xact_commit{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_xact_commit{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 162807 +# HELP pg_stat_database_xact_rollback Number of transactions in this database that have been rolled back +# TYPE pg_stat_database_xact_rollback counter +pg_stat_database_xact_rollback{collector="exporter",datid="13024",datname="template0",server="127.0.0.1:5432"} 0 +pg_stat_database_xact_rollback{collector="exporter",datid="13025",datname="postgres",server="127.0.0.1:5432"} 2 +pg_stat_database_xact_rollback{collector="exporter",datid="16703",datname="template1",server="127.0.0.1:5432"} 0 +pg_stat_database_xact_rollback{collector="exporter",datid="16969",datname="pmm-managed",server="127.0.0.1:5432"} 11 +# HELP pg_stat_user_tables_analyze_count Number of times this table has been manually analyzed +# TYPE pg_stat_user_tables_analyze_count counter +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_analyze_count{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_autoanalyze_count Number of times this table has been analyzed by the autovacuum daemon +# TYPE pg_stat_user_tables_autoanalyze_count counter +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 14 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 1 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autoanalyze_count{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_autovacuum_count Number of times this table has been vacuumed by the autovacuum daemon +# TYPE pg_stat_user_tables_autovacuum_count counter +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_autovacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_idx_scan Number of index scans initiated on this table +# TYPE pg_stat_user_tables_idx_scan counter +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 24 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 270 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 5120 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} NaN +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 9 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 4 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 2704 +pg_stat_user_tables_idx_scan{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} NaN +# HELP pg_stat_user_tables_idx_tup_fetch Number of live rows fetched by index scans +# TYPE pg_stat_user_tables_idx_tup_fetch counter +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 24 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 263 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 5115 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} NaN +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 9 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 2682 +pg_stat_user_tables_idx_tup_fetch{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} NaN +# HELP pg_stat_user_tables_last_analyze Last time at which this table was manually analyzed +# TYPE pg_stat_user_tables_last_analyze gauge +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_analyze{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_last_autoanalyze Last time at which this table was analyzed by the autovacuum daemon +# TYPE pg_stat_user_tables_last_autoanalyze gauge +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 1.653422518e+09 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 1.653392243e+09 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autoanalyze{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_last_autovacuum Last time at which this table was vacuumed by the autovacuum daemon +# TYPE pg_stat_user_tables_last_autovacuum gauge +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_autovacuum{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_last_vacuum Last time at which this table was manually vacuumed (not counting VACUUM FULL) +# TYPE pg_stat_user_tables_last_vacuum gauge +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_last_vacuum{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_n_dead_tup Estimated number of dead rows +# TYPE pg_stat_user_tables_n_dead_tup gauge +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 16 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 18 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 5 +pg_stat_user_tables_n_dead_tup{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 4 +# HELP pg_stat_user_tables_n_live_tup Estimated number of live rows +# TYPE pg_stat_user_tables_n_live_tup gauge +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 9 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 2 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 63 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 2 +pg_stat_user_tables_n_live_tup{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 1 +# HELP pg_stat_user_tables_n_mod_since_analyze Estimated number of rows changed since last analyze +# TYPE pg_stat_user_tables_n_mod_since_analyze gauge +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 24 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 28 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 2 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 2 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 10 +pg_stat_user_tables_n_mod_since_analyze{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 23 +# HELP pg_stat_user_tables_n_tup_del Number of rows deleted +# TYPE pg_stat_user_tables_n_tup_del counter +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 8 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 8 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 4 +pg_stat_user_tables_n_tup_del{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_stat_user_tables_n_tup_hot_upd Number of rows HOT updated (i.e., with no separate index update required) +# TYPE pg_stat_user_tables_n_tup_hot_upd counter +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 8 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 840 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_hot_upd{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 22 +# HELP pg_stat_user_tables_n_tup_ins Number of rows inserted +# TYPE pg_stat_user_tables_n_tup_ins counter +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 8 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 18 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 2 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 63 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 7 +pg_stat_user_tables_n_tup_ins{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 1 +# HELP pg_stat_user_tables_n_tup_upd Number of rows updated +# TYPE pg_stat_user_tables_n_tup_upd counter +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 8 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 840 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_n_tup_upd{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 22 +# HELP pg_stat_user_tables_seq_scan Number of sequential scans initiated on this table +# TYPE pg_stat_user_tables_seq_scan counter +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 58 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 6463 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 9 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 2 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 10 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 11 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 23 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 11 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 1 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 5 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 2 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 5 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 51 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 5 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 15 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 1 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 11 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 114 +pg_stat_user_tables_seq_scan{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 942 +# HELP pg_stat_user_tables_seq_tup_read Number of live rows fetched by sequential scans +# TYPE pg_stat_user_tables_seq_tup_read counter +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 39648 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 134 +pg_stat_user_tables_seq_tup_read{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 942 +# HELP pg_stat_user_tables_vacuum_count Number of times this table has been manually vacuumed (not counting VACUUM FULL) +# TYPE pg_stat_user_tables_vacuum_count counter +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_stat_user_tables_vacuum_count{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_static Version string as reported by postgres +# TYPE pg_static untyped +pg_static{collector="exporter",server="127.0.0.1:5432",short_version="11.15.0",version="PostgreSQL 11.15 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5), 64-bit"} 1 +# HELP pg_statio_user_tables_heap_blks_hit Number of buffer hits in this table +# TYPE pg_statio_user_tables_heap_blks_hit counter +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 57 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 8536 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 5127 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 71 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 2842 +pg_statio_user_tables_heap_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 963 +# HELP pg_statio_user_tables_heap_blks_read Number of disk blocks read from this table +# TYPE pg_statio_user_tables_heap_blks_read counter +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 1 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_heap_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 2 +# HELP pg_statio_user_tables_idx_blks_hit Number of buffer hits in all indexes on this table +# TYPE pg_statio_user_tables_idx_blks_hit counter +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 91 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 336 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 3 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 7 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 8 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 19 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 8 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 3 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 5272 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} NaN +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 3 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 12 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 79 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 16 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 2784 +pg_statio_user_tables_idx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} NaN +# HELP pg_statio_user_tables_idx_blks_read Number of disk blocks read from all indexes on this table +# TYPE pg_statio_user_tables_idx_blks_read counter +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 3 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 5 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 1 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 1 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 1 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 16 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} NaN +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 1 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} 4 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 8 +pg_statio_user_tables_idx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} NaN +# HELP pg_statio_user_tables_tidx_blks_hit Number of buffer hits in this table's TOAST table indexes (if any) +# TYPE pg_statio_user_tables_tidx_blks_hit counter +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 22 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} NaN +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_statio_user_tables_tidx_blks_read Number of disk blocks read from this table's TOAST table indexes (if any) +# TYPE pg_statio_user_tables_tidx_blks_read counter +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 2 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} NaN +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_tidx_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_statio_user_tables_toast_blks_hit Number of buffer hits in this table's TOAST table (if any) +# TYPE pg_statio_user_tables_toast_blks_hit counter +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 42 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} NaN +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_hit{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_statio_user_tables_toast_blks_read Number of disk blocks read from this table's TOAST table (if any) +# TYPE pg_statio_user_tables_toast_blks_read counter +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="action_results",schemaname="public",server="127.0.0.1:5432"} 6 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="agents",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="artifacts",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="backup_locations",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="check_settings",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_channels",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_rules",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="ia_templates",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="job_logs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="jobs",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="kubernetes_clusters",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="nodes",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="percona_sso_details",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="restore_history",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="scheduled_tasks",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="schema_migrations",schemaname="public",server="127.0.0.1:5432"} NaN +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="service_software_versions",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="services",schemaname="public",server="127.0.0.1:5432"} 0 +pg_statio_user_tables_toast_blks_read{collector="custom_query.mr",datname="pmm-managed",relname="settings",schemaname="public",server="127.0.0.1:5432"} 0 +# HELP pg_up Whether the last scrape of metrics from PostgreSQL was able to connect to the server (1 for yes, 0 for no). +# TYPE pg_up gauge +pg_up{collector="custom_query.hr"} 1 +pg_up{collector="custom_query.lr"} 1 +pg_up{collector="custom_query.mr"} 1 +pg_up{collector="exporter"} 1 +# HELP postgres_exporter_build_info A metric with a constant '1' value labeled by version, revision, branch, and goversion from which postgres_exporter was built. +# TYPE postgres_exporter_build_info gauge +postgres_exporter_build_info{branch="",goversion="go1.18.1",revision="",version="0.0.1"} 1 +# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. +# TYPE process_cpu_seconds_total counter +process_cpu_seconds_total 16.06 +# HELP process_max_fds Maximum number of open file descriptors. +# TYPE process_max_fds gauge +process_max_fds 1.048576e+06 +# HELP process_open_fds Number of open file descriptors. +# TYPE process_open_fds gauge +process_open_fds 16 +# HELP process_resident_memory_bytes Resident memory size in bytes. +# TYPE process_resident_memory_bytes gauge +process_resident_memory_bytes 1.8341888e+07 +# HELP process_start_time_seconds Start time of the process since unix epoch in seconds. +# TYPE process_start_time_seconds gauge +process_start_time_seconds 1.65342124309e+09 +# HELP process_virtual_memory_bytes Virtual memory size in bytes. +# TYPE process_virtual_memory_bytes gauge +process_virtual_memory_bytes 7.3322496e+08 +# HELP process_virtual_memory_max_bytes Maximum amount of virtual memory available in bytes. +# TYPE process_virtual_memory_max_bytes gauge +process_virtual_memory_max_bytes 1.8446744073709552e+19 \ No newline at end of file diff --git a/cmd/postgres_exporter/percona_compatibility_test.go b/cmd/postgres_exporter/percona_compatibility_test.go new file mode 100644 index 000000000..24bf1f30b --- /dev/null +++ b/cmd/postgres_exporter/percona_compatibility_test.go @@ -0,0 +1,143 @@ +//go:build manual +// +build manual + +package main + +import ( + "bufio" + _ "embed" + "fmt" + "net/http" + "os" + "regexp" + "sort" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +//go:embed percona-reference-metrics.txt +var referenceMetrics string + +// TestReferenceCompatibility checks that exposed metrics are not missed. +// +// Used to make sure that metrics are present after updating from upstream. +// You need you run exporter locally on port 42002. +func TestReferenceCompatibility(t *testing.T) { + client := &http.Client{ + Timeout: time.Second * 10, + } + req, err := http.NewRequest("GET", "http://localhost:42000/metrics", nil) + assert.Nil(t, err) + req.SetBasicAuth("pmm", "/agent_id/825dcdbf-af1c-4eb4-9e96-21699aa6ff7b") + resp, err := client.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + currentMetricsBytes, err := os.ReadAll(resp.Body) + assert.Nil(t, err) + + currentMetrics := toMap(t, string(currentMetricsBytes)) + referenceMetrics := toMap(t, referenceMetrics) + + //remove matches + for m := range currentMetrics { + _, found := referenceMetrics[m] + if found { + delete(referenceMetrics, m) + delete(currentMetrics, m) + } + } + + fmt.Printf("Extra metrics [%d]:\n", len(currentMetrics)) + for _, metric := range sortedKeys(currentMetrics) { + fmt.Printf("\t%s\n", metric) + } + if len(referenceMetrics) != 0 { + fmt.Printf("Not Supported metrics [%d]:\n", len(referenceMetrics)) + for _, metric := range sortedKeys(referenceMetrics) { + fmt.Printf("\t%s\n", metric) + } + assert.FailNowf(t, "Found not supported metrics", "Count: %d", len(referenceMetrics)) + } +} + +func sortedKeys(m map[string]string) []string { + keys := make([]string, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + return keys +} + +func toMap(t *testing.T, rawMetrics string) map[string]string { + result := make(map[string]string) + + scanner := bufio.NewScanner(strings.NewReader(rawMetrics)) + scanner.Split(bufio.ScanLines) + + for scanner.Scan() { + next := scanner.Text() + isComment := strings.HasPrefix(next, "#") + if isComment { + continue + } + next = cleanKeyOrValue(next) + if next != "" { + items := strings.Split(next, " ") + if len(items) > 1 { + result[items[0]] = items[1] + } else { + fmt.Println("WARN: ") + } + } + } + + return result +} + +func cleanKeyOrValue(s string) (res string) { + res = s + + itemsToIgnore := []string{ + "example-queries", + } + + for _, each := range itemsToIgnore { + if strings.Contains(s, each) { + return "" + } + } + + regexpsToRemove := []*regexp.Regexp{ + regexp.MustCompile(`[+-]?(\d*[.])?\d+(e[+-]?\d*)?`), + regexp.MustCompile(`\d*\.\d*\.\d*\.\d*:\d*`), + regexp.MustCompile(`go1.\d*.\d*`), + regexp.MustCompile(`filename=".*",`), + regexp.MustCompile(`hashsum=".*"`), + } + for _, each := range regexpsToRemove { + res = each.ReplaceAllString(res, "") + } + + stringsToRemove := []string{ + "PostgreSQL 11.15 (Debian 11.15-1.pgdg90+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit", + "PostgreSQL 11.16 (Debian 11.16-1.pgdg90+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit", + "collector=\"exporter\",", + "fastpath function call", + "idle in transaction (aborted)", + "idle in transaction", + "+Inf", + "0.0.1", + "collector=\"custom_query.mr\",", + "datname=\"pmm-managed\"", + "datname=\"pmm-agent\"", + } + for _, each := range stringsToRemove { + res = strings.ReplaceAll(res, each, "") + } + + return +} diff --git a/cmd/postgres_exporter/percona_exporter.go b/cmd/postgres_exporter/percona_exporter.go new file mode 100644 index 000000000..bf3749d24 --- /dev/null +++ b/cmd/postgres_exporter/percona_exporter.go @@ -0,0 +1,266 @@ +package main + +import ( + "context" + "crypto/sha256" + "fmt" + stdlog "log" + "net/http" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/alecthomas/kingpin/v2" + "github.com/blang/semver/v4" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/postgres_exporter/collector" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "golang.org/x/sync/semaphore" +) + +type MetricResolution string + +const ( + LR MetricResolution = "lr" + MR MetricResolution = "mr" + HR MetricResolution = "hr" +) + +var ( + collectCustomQueryLr = kingpin.Flag("collect.custom_query.lr", "Enable custom queries with low resolution directory.").Default("false").Envar("PG_EXPORTER_EXTEND_QUERY_LR").Bool() + collectCustomQueryMr = kingpin.Flag("collect.custom_query.mr", "Enable custom queries with medium resolution directory.").Default("false").Envar("PG_EXPORTER_EXTEND_QUERY_MR").Bool() + collectCustomQueryHr = kingpin.Flag("collect.custom_query.hr", "Enable custom queries with high resolution directory.").Default("false").Envar("PG_EXPORTER_EXTEND_QUERY_HR").Bool() + collectCustomQueryLrDirectory = kingpin.Flag("collect.custom_query.lr.directory", "Path to custom queries with low resolution directory.").Envar("PG_EXPORTER_EXTEND_QUERY_LR_PATH").String() + collectCustomQueryMrDirectory = kingpin.Flag("collect.custom_query.mr.directory", "Path to custom queries with medium resolution directory.").Envar("PG_EXPORTER_EXTEND_QUERY_MR_PATH").String() + collectCustomQueryHrDirectory = kingpin.Flag("collect.custom_query.hr.directory", "Path to custom queries with high resolution directory.").Envar("PG_EXPORTER_EXTEND_QUERY_HR_PATH").String() + + maxConnections = kingpin.Flag("max-connections", "Maximum number of connections to use").Default("5").Envar("PG_EXPORTER_MAX_CONNECTIONS").Int64() +) + +// Handler returns a http.Handler that serves metrics. Can be used instead of +// run for hooking up custom HTTP servers. +func Handler(logger log.Logger, dsns []string, connSema *semaphore.Weighted, globalCollectors map[string]prometheus.Collector) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + seconds, err := strconv.Atoi(r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds")) + // To support also older ones vmagents. + if err != nil { + seconds = 10 + } + + ctx, cancel := context.WithTimeout(r.Context(), time.Duration(seconds)*time.Second) + defer cancel() + + filters := r.URL.Query()["collect[]"] + level.Debug(logger).Log("msg", "Collect query", "filters", filters) + + var f Filters + if len(filters) == 0 { + f.EnableAllCollectors = true + } else { + for _, filter := range filters { + switch filter { + case "standard.process": + f.EnableProcessCollector = true + case "standard.go": + f.EnableGoCollector = true + case "version": + f.EnableVersionCollector = true + case "exporter": + f.EnableDefaultCollector = true + case "custom_query.hr": + f.EnableHRCollector = true + case "custom_query.mr": + f.EnableMRCollector = true + case "custom_query.lr": + f.EnableLRCollector = true + case "postgres": + f.EnablePostgresCollector = true + } + } + } + + registry := makeRegistry(ctx, dsns, connSema, globalCollectors, f) + + // Delegate http serving to Prometheus client library, which will call collector.Collect. + h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{ + ErrorHandling: promhttp.ContinueOnError, + ErrorLog: stdlog.New(log.NewStdlibAdapter(logger), "handler", 0), + }) + + h.ServeHTTP(w, r) + }) +} + +// Filters is a struct to enable or disable collectors. +type Filters struct { + EnableAllCollectors bool + EnableLRCollector bool + EnableMRCollector bool + EnableHRCollector bool + EnableDefaultCollector bool + EnableGoCollector bool + EnableVersionCollector bool + EnableProcessCollector bool + EnablePostgresCollector bool +} + +// makeRegistry creates a new prometheus registry with default and percona exporters. +func makeRegistry(ctx context.Context, dsns []string, connSema *semaphore.Weighted, globalCollectors map[string]prometheus.Collector, filters Filters) *prometheus.Registry { + registry := prometheus.NewRegistry() + + excludedDatabases := strings.Split(*excludeDatabases, ",") + logger.Log("msg", "Excluded databases", "databases", fmt.Sprintf("%v", excludedDatabases)) + + queriesPath := map[MetricResolution]string{ + HR: *collectCustomQueryHrDirectory, + MR: *collectCustomQueryMrDirectory, + LR: *collectCustomQueryLrDirectory, + } + + opts := []ExporterOpt{ + AutoDiscoverDatabases(*autoDiscoverDatabases), + ExcludeDatabases(excludedDatabases), + WithConnectionsSemaphore(connSema), + WithContext(ctx), + } + + if filters.EnableAllCollectors || filters.EnableDefaultCollector { + defaultExporter := NewExporter(dsns, append( + opts, + CollectorName("exporter"), + WithConstantLabels(*constantLabelsList), // This option depends on collectors name, so keep it after CollectorName option + DisableDefaultMetrics(*disableDefaultMetrics), + DisableSettingsMetrics(*disableSettingsMetrics), + IncludeDatabases(*includeDatabases), + )...) + registry.MustRegister(defaultExporter) + } + + if filters.EnableAllCollectors || filters.EnableHRCollector { + hrExporter := NewExporter(dsns, + append(opts, + CollectorName("custom_query.hr"), + WithConstantLabels(*constantLabelsList), // This option depends on collectors name, so keep it after CollectorName option + WithUserQueriesEnabled(HR), + WithEnabled(*collectCustomQueryHr), + DisableDefaultMetrics(true), + DisableSettingsMetrics(true), + WithUserQueriesPath(queriesPath), + )...) + registry.MustRegister(hrExporter) + + } + + if filters.EnableAllCollectors || filters.EnableMRCollector { + mrExporter := NewExporter(dsns, + append(opts, + CollectorName("custom_query.mr"), + WithConstantLabels(*constantLabelsList), // This option depends on collectors name, so keep it after CollectorName option + WithUserQueriesEnabled(MR), + WithEnabled(*collectCustomQueryMr), + DisableDefaultMetrics(true), + DisableSettingsMetrics(true), + WithUserQueriesPath(queriesPath), + )...) + registry.MustRegister(mrExporter) + } + + if filters.EnableAllCollectors || filters.EnableLRCollector { + lrExporter := NewExporter(dsns, + append(opts, + CollectorName("custom_query.lr"), + WithConstantLabels(*constantLabelsList), // This option depends on collectors name, so keep it after CollectorName option + WithUserQueriesEnabled(LR), + WithEnabled(*collectCustomQueryLr), + DisableDefaultMetrics(true), + DisableSettingsMetrics(true), + WithUserQueriesPath(queriesPath), + )...) + registry.MustRegister(lrExporter) + } + + if filters.EnableAllCollectors || filters.EnableGoCollector { + registry.MustRegister(globalCollectors["standard.go"]) + } + + if filters.EnableAllCollectors || filters.EnableProcessCollector { + registry.MustRegister(globalCollectors["standard.process"]) + } + + if filters.EnableAllCollectors || filters.EnableVersionCollector { + registry.MustRegister(globalCollectors["version"]) + } + + if filters.EnableAllCollectors || filters.EnablePostgresCollector { + // This chunk moved here from main.go + // TODO(@sysadmind): Remove this with multi-target support. We are removing multiple DSN support + dsn := "" + if len(dsns) > 0 { + dsn = dsns[0] + } + + pe, err := collector.NewPostgresCollector( + logger, + excludedDatabases, + dsn, + []string{}, + collector.WithContext(ctx), + collector.WithConnectionsSemaphore(connSema), + ) + if err != nil { + level.Error(logger).Log("msg", "Failed to create PostgresCollector", "err", err.Error()) + } else { + registry.MustRegister(pe) + } + } + + return registry +} + +func (e *Exporter) loadCustomQueries(res MetricResolution, version semver.Version, server *Server) { + if e.userQueriesPath[res] != "" { + fi, err := os.ReadDir(e.userQueriesPath[res]) + if err != nil { + level.Error(logger).Log("msg", fmt.Sprintf("failed read dir %q for custom query", e.userQueriesPath[res]), + "err", err) + return + } + level.Debug(logger).Log("msg", fmt.Sprintf("reading dir %q for custom query", e.userQueriesPath[res])) + + for _, v := range fi { + if v.IsDir() { + continue + } + + if filepath.Ext(v.Name()) == ".yml" || filepath.Ext(v.Name()) == ".yaml" { + path := filepath.Join(e.userQueriesPath[res], v.Name()) + e.addCustomQueriesFromFile(path, version, server) + } + } + } +} + +func (e *Exporter) addCustomQueriesFromFile(path string, version semver.Version, server *Server) { + // Calculate the hashsum of the useQueries + userQueriesData, err := os.ReadFile(path) + if err != nil { + level.Error(logger).Log("msg", "Failed to reload user queries:"+path, "err", err) + e.userQueriesError.WithLabelValues(path, "").Set(1) + return + } + + hashsumStr := fmt.Sprintf("%x", sha256.Sum256(userQueriesData)) + + if err := addQueries(userQueriesData, version, server); err != nil { + level.Error(logger).Log("msg", "Failed to reload user queries:"+path, "err", err) + e.userQueriesError.WithLabelValues(path, hashsumStr).Set(1) + return + } + + // Mark user queries as successfully loaded + e.userQueriesError.WithLabelValues(path, hashsumStr).Set(0) +} diff --git a/cmd/postgres_exporter/postgres_exporter.go b/cmd/postgres_exporter/postgres_exporter.go index fa34eecc5..3d890a16f 100644 --- a/cmd/postgres_exporter/postgres_exporter.go +++ b/cmd/postgres_exporter/postgres_exporter.go @@ -14,19 +14,21 @@ package main import ( - "crypto/sha256" + "context" "database/sql" "errors" "fmt" "math" - "os" "regexp" "strings" + "sync" + "sync/atomic" "time" "github.com/blang/semver/v4" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sync/semaphore" ) // ColumnUsage should be one of several enum values which describe how a @@ -176,6 +178,14 @@ var builtinMetricMaps = map[string]intermediateMetricMap{ true, 0, }, + "pg_lock_conflicts": { + map[string]ColumnMapping{ + "blocking_pid": {LABEL, "PID of blocking session", nil, nil}, + "count": {GAUGE, "Number of blocked sessions", nil, nil}, + }, + true, + 0, + }, "pg_stat_replication": { map[string]ColumnMapping{ "procpid": {DISCARD, "Process ID of a WAL sender process", nil, semver.MustParseRange("<9.2.0")}, @@ -248,12 +258,13 @@ var builtinMetricMaps = map[string]intermediateMetricMap{ }, "pg_stat_activity": { map[string]ColumnMapping{ - "datname": {LABEL, "Name of this database", nil, nil}, - "state": {LABEL, "connection state", nil, semver.MustParseRange(">=9.2.0")}, - "usename": {LABEL, "connection usename", nil, nil}, - "application_name": {LABEL, "connection application_name", nil, nil}, - "count": {GAUGE, "number of connections in this state", nil, nil}, - "max_tx_duration": {GAUGE, "max duration in seconds any active transaction has been running", nil, nil}, + "datname": {LABEL, "Name of this database", nil, nil}, + "state": {LABEL, "connection state", nil, semver.MustParseRange(">=9.2.0")}, + "usename": {LABEL, "Name of the user logged into this backend", nil, nil}, + "application_name": {LABEL, "Name of the application that is connected to this backend", nil, nil}, + "count": {GAUGE, "number of connections in this state", nil, nil}, + "max_tx_duration": {GAUGE, "max duration in seconds any active transaction has been running", nil, nil}, + "max_state_duration": {GAUGE, "max state change duration in seconds any active transaction has been", nil, nil}, }, true, 0, @@ -403,6 +414,11 @@ type cachedMetrics struct { // Exporter collects Postgres metrics. It implements prometheus.Collector. type Exporter struct { + collectorName string + userQueriesPath map[MetricResolution]string + resolutionEnabled MetricResolution + enabled bool + // Holds a reference to the build in column mappings. Currently this is for testing purposes // only, since it just points to the global. builtinMetricMaps map[string]intermediateMetricMap @@ -412,7 +428,6 @@ type Exporter struct { excludeDatabases []string includeDatabases []string dsn []string - userQueriesPath string constantLabels prometheus.Labels duration prometheus.Gauge error prometheus.Gauge @@ -422,7 +437,11 @@ type Exporter struct { // servers are used to allow re-using the DB connection between scrapes. // servers contains metrics map and query overrides. - servers *Servers + // servers *Servers + + connSema *semaphore.Weighted + ctx context.Context + masterDSN string } // ExporterOpt configures Exporter. @@ -435,6 +454,41 @@ func DisableDefaultMetrics(b bool) ExporterOpt { } } +// CollectorName configures collector name. +func CollectorName(name string) ExporterOpt { + return func(e *Exporter) { + e.collectorName = name + } +} + +// WithUserQueriesEnabled enables user's queries. +func WithUserQueriesEnabled(p MetricResolution) ExporterOpt { + return func(e *Exporter) { + e.resolutionEnabled = p + } +} + +// WithUserQueriesEnabled enables user's queries. +func WithEnabled(p bool) ExporterOpt { + return func(e *Exporter) { + e.enabled = p + } +} + +// WithContext sets context for the exporter. +func WithContext(ctx context.Context) ExporterOpt { + return func(e *Exporter) { + e.ctx = ctx + } +} + +// WithConnectionsSemaphore sets the semaphore for limiting the number of connections to the database instance. +func WithConnectionsSemaphore(sem *semaphore.Weighted) ExporterOpt { + return func(e *Exporter) { + e.connSema = sem + } +} + // DisableSettingsMetrics configures pg_settings export. func DisableSettingsMetrics(b bool) ExporterOpt { return func(e *Exporter) { @@ -466,7 +520,7 @@ func IncludeDatabases(s string) ExporterOpt { } // WithUserQueriesPath configures user's queries path. -func WithUserQueriesPath(p string) ExporterOpt { +func WithUserQueriesPath(p map[MetricResolution]string) ExporterOpt { return func(e *Exporter) { e.userQueriesPath = p } @@ -476,6 +530,11 @@ func WithUserQueriesPath(p string) ExporterOpt { func WithConstantLabels(s string) ExporterOpt { return func(e *Exporter) { e.constantLabels = parseConstLabels(s) + if e.collectorName != "" { + e.constantLabels["collector"] = e.collectorName + } else { + e.constantLabels["collector"] = "exporter" + } } } @@ -510,6 +569,8 @@ func NewExporter(dsn []string, opts ...ExporterOpt) *Exporter { e := &Exporter{ dsn: dsn, builtinMetricMaps: builtinMetricMaps, + enabled: true, + ctx: context.Background(), } for _, opt := range opts { @@ -517,11 +578,38 @@ func NewExporter(dsn []string, opts ...ExporterOpt) *Exporter { } e.setupInternalMetrics() - e.servers = NewServers(ServerWithLabels(e.constantLabels)) + // e.servers = NewServers(ServerWithLabels(e.constantLabels)) return e } +// GetServer returns a new Server instance for the provided DSN. +func (e *Exporter) GetServer(dsn string, opts ...ServerOpt) (*Server, error) { + var err error + errCount := 0 // start at zero because we increment before doing work + retries := 1 + var server *Server + for { + if errCount++; errCount > retries { + return nil, err + } + + server, err = NewServer(dsn, opts...) + if err != nil { + time.Sleep(time.Duration(errCount) * time.Second) + continue + } + + if err = server.Ping(); err != nil { + server.Close() + time.Sleep(time.Duration(errCount) * time.Second) + continue + } + break + } + return server, nil +} + func (e *Exporter) setupInternalMetrics() { e.duration = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, @@ -565,6 +653,9 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { // Collect implements prometheus.Collector. func (e *Exporter) Collect(ch chan<- prometheus.Metric) { + if !e.enabled { + return + } e.scrape(ch) ch <- e.duration @@ -609,46 +700,30 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, server *Server) } // Check if semantic version changed and recalculate maps if needed. - if semanticVersion.NE(server.lastMapVersion) || server.metricMap == nil { - level.Info(logger).Log("msg", "Semantic version changed", "server", server, "from", server.lastMapVersion, "to", semanticVersion) - server.mappingMtx.Lock() - - // Get Default Metrics only for master database - if !e.disableDefaultMetrics && server.master { - server.metricMap = makeDescMap(semanticVersion, server.labels, e.builtinMetricMaps) - server.queryOverrides = makeQueryOverrideMap(semanticVersion, queryOverrides) - } else { - server.metricMap = make(map[string]MetricMapNamespace) - server.queryOverrides = make(map[string]string) - } + // if semanticVersion.NE(server.lastMapVersion[e.resolutionEnabled]) || server.metricMap == nil { + // level.Info(logger).Log("msg", "Semantic version changed", "server", server, "from", server.lastMapVersion[e.resolutionEnabled], "to", semanticVersion) + server.mappingMtx.Lock() - server.lastMapVersion = semanticVersion - - if e.userQueriesPath != "" { - // Clear the metric while a reload is happening - e.userQueriesError.Reset() - - // Calculate the hashsum of the useQueries - userQueriesData, err := os.ReadFile(e.userQueriesPath) - if err != nil { - level.Error(logger).Log("msg", "Failed to reload user queries", "path", e.userQueriesPath, "err", err) - e.userQueriesError.WithLabelValues(e.userQueriesPath, "").Set(1) - } else { - hashsumStr := fmt.Sprintf("%x", sha256.Sum256(userQueriesData)) - - if err := addQueries(userQueriesData, semanticVersion, server); err != nil { - level.Error(logger).Log("msg", "Failed to reload user queries", "path", e.userQueriesPath, "err", err) - e.userQueriesError.WithLabelValues(e.userQueriesPath, hashsumStr).Set(1) - } else { - // Mark user queries as successfully loaded - e.userQueriesError.WithLabelValues(e.userQueriesPath, hashsumStr).Set(0) - } - } - } + // Get Default Metrics only for master database + if !e.disableDefaultMetrics && server.master { + server.metricMap = makeDescMap(semanticVersion, server.labels, e.builtinMetricMaps) + server.queryOverrides = makeQueryOverrideMap(semanticVersion, queryOverrides) + } else { + server.metricMap = make(map[string]MetricMapNamespace) + server.queryOverrides = make(map[string]string) + } + + // server.lastMapVersion[e.resolutionEnabled] = semanticVersion - server.mappingMtx.Unlock() + if e.userQueriesPath[HR] != "" || e.userQueriesPath[MR] != "" || e.userQueriesPath[LR] != "" { + // Clear the metric while reload + e.userQueriesError.Reset() } + e.loadCustomQueries(e.resolutionEnabled, semanticVersion, server) + + server.mappingMtx.Unlock() + // Output the version as a special metric only for master database versionDesc := prometheus.NewDesc(fmt.Sprintf("%s_%s", namespace, staticLabelName), "Version string as reported by postgres", []string{"version", "short_version"}, server.labels) @@ -672,29 +747,45 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) { dsns = e.discoverDatabaseDSNs() } - var errorsCount int - var connectionErrorsCount int + var errorsCount atomic.Int32 + var connectionErrorsCount atomic.Int32 + var wg sync.WaitGroup for _, dsn := range dsns { - if err := e.scrapeDSN(ch, dsn); err != nil { - errorsCount++ + dsn := dsn + wg.Add(1) + go func() { + defer wg.Done() + + if e.connSema != nil { + if err := e.connSema.Acquire(e.ctx, 1); err != nil { + level.Warn(logger).Log("msg", "Failed to acquire semaphore", "err", err) + return + } + defer e.connSema.Release(1) + } + if err := e.scrapeDSN(ch, dsn); err != nil { + errorsCount.Add(1) - level.Error(logger).Log("err", err) + level.Error(logger).Log("err", err) - if _, ok := err.(*ErrorConnectToServer); ok { - connectionErrorsCount++ + if _, ok := err.(*ErrorConnectToServer); ok { + connectionErrorsCount.Add(1) + } } - } + }() } + wg.Wait() + switch { - case connectionErrorsCount >= len(dsns): + case int(connectionErrorsCount.Load()) >= len(dsns): e.psqlUp.Set(0) default: e.psqlUp.Set(1) // Didn't fail, can mark connection as up for this scrape. } - switch errorsCount { + switch errorsCount.Load() { case 0: e.error.Set(0) default: diff --git a/cmd/postgres_exporter/postgres_exporter_integration_test.go b/cmd/postgres_exporter/postgres_exporter_integration_test.go index 7043c1e88..b24f76dda 100644 --- a/cmd/postgres_exporter/postgres_exporter_integration_test.go +++ b/cmd/postgres_exporter/postgres_exporter_integration_test.go @@ -156,7 +156,11 @@ func (s *IntegrationSuite) TestExtendQueriesDoesntCrash(c *C) { exporter := NewExporter( strings.Split(dsn, ","), - WithUserQueriesPath("../user_queries_test.yaml"), + WithUserQueriesPath(map[MetricResolution]string{ + HR: "../user_queries_test.yaml", + MR: "../user_queries_test.yaml", + LR: "../user_queries_test.yaml", + }), ) c.Assert(exporter, NotNil) diff --git a/cmd/postgres_exporter/probe.go b/cmd/postgres_exporter/probe.go index 5945e07b8..654b7d8bf 100644 --- a/cmd/postgres_exporter/probe.go +++ b/cmd/postgres_exporter/probe.go @@ -23,9 +23,10 @@ import ( "github.com/prometheus-community/postgres_exporter/config" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" + "golang.org/x/sync/semaphore" ) -func handleProbe(logger log.Logger, excludeDatabases []string) http.HandlerFunc { +func handleProbe(logger log.Logger, excludeDatabases []string, connSema *semaphore.Weighted) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() conf := c.GetConfig() @@ -69,21 +70,24 @@ func handleProbe(logger log.Logger, excludeDatabases []string) http.HandlerFunc DisableDefaultMetrics(*disableDefaultMetrics), DisableSettingsMetrics(*disableSettingsMetrics), AutoDiscoverDatabases(*autoDiscoverDatabases), - WithUserQueriesPath(*queriesPath), + // WithUserQueriesPath(*queriesPath), WithConstantLabels(*constantLabelsList), ExcludeDatabases(excludeDatabases), IncludeDatabases(*includeDatabases), + WithContext(ctx), + WithConnectionsSemaphore(connSema), } dsns := []string{dsn.GetConnectionString()} exporter := NewExporter(dsns, opts...) - defer func() { - exporter.servers.Close() - }() + + // defer func() { + // exporter.servers.Close() + // }() registry.MustRegister(exporter) // Run the probe - pc, err := collector.NewProbeCollector(tl, excludeDatabases, registry, dsn) + pc, err := collector.NewProbeCollector(ctx, tl, excludeDatabases, registry, dsn, connSema) if err != nil { level.Error(logger).Log("msg", "Error creating probe collector", "err", err) http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/cmd/postgres_exporter/queries.go b/cmd/postgres_exporter/queries.go index fa0b5c272..d90d2c258 100644 --- a/cmd/postgres_exporter/queries.go +++ b/cmd/postgres_exporter/queries.go @@ -14,6 +14,7 @@ package main import ( + "context" "errors" "fmt" @@ -46,6 +47,19 @@ type OverrideQuery struct { // Overriding queries for namespaces above. // TODO: validate this is a closed set in tests, and there are no overlaps var queryOverrides = map[string][]OverrideQuery{ + "pg_lock_conflicts": { + { + semver.MustParseRange(">0.0.0"), + `SELECT blockinga.pid AS blocking_pid, count(*) as count + FROM pg_catalog.pg_locks blockedl + JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid + JOIN pg_catalog.pg_locks blockingl ON(blockingl.transactionid=blockedl.transactionid + AND blockedl.pid != blockingl.pid) + JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid + WHERE NOT blockedl.granted + group by blocking_pid`, + }, + }, "pg_stat_replication": { { semver.MustParseRange(">=10.0.0"), @@ -82,6 +96,7 @@ var queryOverrides = map[string][]OverrideQuery{ ` SELECT slot_name, database, active, pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn) FROM pg_replication_slots + WHERE pg_is_in_recovery() = False `, }, { @@ -89,6 +104,7 @@ var queryOverrides = map[string][]OverrideQuery{ ` SELECT slot_name, database, active, pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) FROM pg_replication_slots + WHERE pg_is_in_recovery() = False `, }, }, @@ -115,7 +131,8 @@ var queryOverrides = map[string][]OverrideQuery{ tmp2.usename, tmp2.application_name, COALESCE(count,0) as count, - COALESCE(max_tx_duration,0) as max_tx_duration + COALESCE(max_tx_duration,0) as max_tx_duration, + COALESCE(max_state_duration, 0) AS max_state_duration FROM ( VALUES ('active'), @@ -133,7 +150,8 @@ var queryOverrides = map[string][]OverrideQuery{ usename, application_name, count(*) AS count, - MAX(EXTRACT(EPOCH FROM now() - xact_start))::float AS max_tx_duration + MAX(EXTRACT(EPOCH FROM now() - xact_start))::float AS max_tx_duration, + MAX(EXTRACT(EPOCH FROM now() - state_change))::float AS max_state_duration FROM pg_stat_activity GROUP BY datname,state,usename,application_name) AS tmp2 ON tmp.state = tmp2.state AND pg_database.datname = tmp2.datname `, @@ -147,7 +165,8 @@ var queryOverrides = map[string][]OverrideQuery{ usename, application_name, COALESCE(count(*),0) AS count, - COALESCE(MAX(EXTRACT(EPOCH FROM now() - xact_start))::float,0) AS max_tx_duration + COALESCE(MAX(EXTRACT(EPOCH FROM now() - xact_start))::float,0) AS max_tx_duration, + COALESCE(MAX(EXTRACT(EPOCH FROM now() - state_change))::float,0) AS max_state_duration FROM pg_stat_activity GROUP BY datname,usename,application_name `, }, @@ -263,8 +282,8 @@ func addQueries(content []byte, pgVersion semver.Version, server *Server) error return nil } -func queryDatabases(server *Server) ([]string, error) { - rows, err := server.db.Query("SELECT datname FROM pg_database WHERE datallowconn = true AND datistemplate = false AND datname != current_database()") +func queryDatabases(ctx context.Context, server *Server) ([]string, error) { + rows, err := server.db.QueryContext(ctx, "SELECT datname FROM pg_database WHERE datallowconn = true AND datistemplate = false AND datname != current_database() AND has_database_privilege(current_user, datname, 'connect')") if err != nil { return nil, fmt.Errorf("Error retrieving databases: %v", err) } diff --git a/cmd/postgres_exporter/server.go b/cmd/postgres_exporter/server.go index bcfee6812..574ce9f6e 100644 --- a/cmd/postgres_exporter/server.go +++ b/cmd/postgres_exporter/server.go @@ -54,6 +54,7 @@ func ServerWithLabels(labels prometheus.Labels) ServerOpt { for k, v := range labels { s.labels[k] = v } + s.labels["collector"] = "exporter" } } @@ -126,6 +127,10 @@ func (s *Server) Scrape(ch chan<- prometheus.Metric, disableSettingsMetrics bool errMap := queryNamespaceMappings(ch, s) if len(errMap) > 0 { err = fmt.Errorf("queryNamespaceMappings returned %d errors", len(errMap)) + level.Error(logger).Log("msg", "NAMESPACE ERRORS FOUND") + for namespace, err := range errMap { + level.Error(logger).Log("namespace", namespace, "msg", err) + } } return err @@ -169,6 +174,7 @@ func (s *Servers) GetServer(dsn string) (*Server, error) { s.servers[dsn] = server } if err = server.Ping(); err != nil { + server.Close() delete(s.servers, dsn) time.Sleep(time.Duration(errCount) * time.Second) continue diff --git a/cmd/postgres_exporter/tests/test-smoke b/cmd/postgres_exporter/tests/test-smoke index 4062e235b..acb20498e 100755 --- a/cmd/postgres_exporter/tests/test-smoke +++ b/cmd/postgres_exporter/tests/test-smoke @@ -134,13 +134,13 @@ smoketest_postgres() { echo "Templating failed" 1>&2 exit 1 fi - trap "docker-compose logs; docker-compose down ; docker-compose rm -v; exit 1" EXIT INT TERM - local compose_cmd="POSTGRES_PASSWORD=$POSTGRES_PASSWORD docker-compose up -d --force-recreate --build" + trap "docker compose logs; docker compose down ; docker compose rm -v; exit 1" EXIT INT TERM + local compose_cmd="POSTGRES_PASSWORD=$POSTGRES_PASSWORD docker compose up -d --force-recreate --build" echo "Compose Cmd: $compose_cmd" eval "$compose_cmd" - master_container=$(docker-compose ps -q pg-master) - slave_container=$(docker-compose ps -q pg-slave) + master_container=$(docker compose ps -q pg-master) + slave_container=$(docker compose ps -q pg-slave) master_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$master_container") slave_ip=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$slave_container") echo "Got master IP: $master_ip" @@ -153,7 +153,7 @@ smoketest_postgres() { --log.level=debug --web.listen-address=:$exporter_port & exporter_pid=$! # shellcheck disable=SC2064 - trap "docker-compose logs; docker-compose down ; docker-compose rm -v ; kill $exporter_pid; exit 1" EXIT INT TERM + trap "docker compose logs; docker compose down ; docker compose rm -v ; kill $exporter_pid; exit 1" EXIT INT TERM wait_for_exporter if ! wget -q -O - http://localhost:$exporter_port/metrics 1> "$METRICS_DIR/.metrics.replicated.$version.prom" ; then @@ -162,8 +162,8 @@ smoketest_postgres() { fi kill $exporter_pid - docker-compose down - docker-compose rm -v + docker compose down + docker compose rm -v trap - EXIT INT TERM cd "$old_pwd" || exit 1 diff --git a/collector/collector.go b/collector/collector.go index 121129871..31ad66340 100644 --- a/collector/collector.go +++ b/collector/collector.go @@ -24,6 +24,7 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sync/semaphore" ) var ( @@ -92,6 +93,9 @@ type PostgresCollector struct { logger log.Logger instance *instance + + connSema *semaphore.Weighted + ctx context.Context } type Option func(*PostgresCollector) error @@ -157,6 +161,22 @@ func NewPostgresCollector(logger log.Logger, excludeDatabases []string, dsn stri return p, nil } +// WithContext sets context for the collector. +func WithContext(ctx context.Context) Option { + return func(c *PostgresCollector) error { + c.ctx = ctx + return nil + } +} + +// WithConnectionsSemaphore sets the semaphore for limiting the number of connections to the database instance. +func WithConnectionsSemaphore(sem *semaphore.Weighted) Option { + return func(c *PostgresCollector) error { + c.connSema = sem + return nil + } +} + // Describe implements the prometheus.Collector interface. func (p PostgresCollector) Describe(ch chan<- *prometheus.Desc) { ch <- scrapeDurationDesc @@ -165,11 +185,17 @@ func (p PostgresCollector) Describe(ch chan<- *prometheus.Desc) { // Collect implements the prometheus.Collector interface. func (p PostgresCollector) Collect(ch chan<- prometheus.Metric) { - ctx := context.TODO() - // copy the instance so that concurrent scrapes have independent instances inst := p.instance.copy() + if p.connSema != nil { + if err := p.connSema.Acquire(p.ctx, 1); err != nil { + level.Warn(p.logger).Log("msg", "Failed to acquire semaphore", "err", err) + return + } + defer p.connSema.Release(1) + } + // Set up the database connection for the collector. err := inst.setup() if err != nil { @@ -182,7 +208,7 @@ func (p PostgresCollector) Collect(ch chan<- prometheus.Metric) { wg.Add(len(p.Collectors)) for name, c := range p.Collectors { go func(name string, c Collector) { - execute(ctx, name, c, inst, ch, p.logger) + execute(p.ctx, name, c, inst, ch, p.logger) wg.Done() }(name, c) } diff --git a/collector/instance.go b/collector/instance.go index a365697d6..b7a6e8b0d 100644 --- a/collector/instance.go +++ b/collector/instance.go @@ -17,12 +17,15 @@ import ( "database/sql" "fmt" "regexp" + "strings" "github.com/blang/semver/v4" + "github.com/lib/pq" ) type instance struct { dsn string + name string db *sql.DB version semver.Version } @@ -40,13 +43,18 @@ func newInstance(dsn string) (*instance, error) { } db.Close() + i.name, err = parseServerName(dsn) + if err != nil { + return nil, err + } return i, nil } // copy returns a copy of the instance. func (i *instance) copy() *instance { return &instance{ - dsn: i.dsn, + dsn: i.dsn, + name: i.name, } } @@ -104,3 +112,39 @@ func queryVersion(db *sql.DB) (semver.Version, error) { } return semver.Version{}, fmt.Errorf("could not parse version from %q", version) } + +func parseServerName(url string) (string, error) { + dsn, err := pq.ParseURL(url) + if err != nil { + dsn = url + } + + pairs := strings.Split(dsn, " ") + kv := make(map[string]string, len(pairs)) + for _, pair := range pairs { + splitted := strings.SplitN(pair, "=", 2) + if len(splitted) != 2 { + return "", fmt.Errorf("malformed dsn %q", dsn) + } + // Newer versions of pq.ParseURL quote values so trim them off if they exist + key := strings.Trim(splitted[0], "'\"") + value := strings.Trim(splitted[1], "'\"") + kv[key] = value + } + + var fingerprint string + + if host, ok := kv["host"]; ok { + fingerprint += host + } else { + fingerprint += "localhost" + } + + if port, ok := kv["port"]; ok { + fingerprint += ":" + port + } else { + fingerprint += ":5432" + } + + return fingerprint, nil +} diff --git a/collector/pg_database_wraparound.go b/collector/pg_database_wraparound.go index d46270637..e833dbdec 100644 --- a/collector/pg_database_wraparound.go +++ b/collector/pg_database_wraparound.go @@ -25,7 +25,7 @@ import ( const databaseWraparoundSubsystem = "database_wraparound" func init() { - registerCollector(databaseWraparoundSubsystem, defaultDisabled, NewPGDatabaseWraparoundCollector) + registerCollector(databaseWraparoundSubsystem, defaultEnabled, NewPGDatabaseWraparoundCollector) } type PGDatabaseWraparoundCollector struct { diff --git a/collector/pg_extensions.go b/collector/pg_extensions.go new file mode 100644 index 000000000..f7f1fd434 --- /dev/null +++ b/collector/pg_extensions.go @@ -0,0 +1,117 @@ +package collector + +import ( + "context" + "database/sql" + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + "strconv" +) + +func init() { + registerCollector("extensions", defaultEnabled, NewExtensionsCollector) +} + +var pgExtensions = map[string]*prometheus.Desc{ + "pg_available_extensions": prometheus.NewDesc( + "pg_available_extensions", + "Extensions that are available for installation", + []string{ + "name", + "default_version", + "installed_version", + }, + prometheus.Labels{}, + ), + "pg_extensions": prometheus.NewDesc( + "pg_extensions", + "Installed extensions", + []string{ + "name", + "relocatable", + "version", + }, + prometheus.Labels{}, + ), +} + +type ExtensionsCollector struct { + logger log.Logger +} + +func NewExtensionsCollector(collectorConfig collectorConfig) (Collector, error) { + return &ExtensionsCollector{logger: collectorConfig.logger}, nil +} + +func (e *ExtensionsCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error { + err := e.scrapeAvailableExtensions(ctx, instance.db, ch) + if err != nil { + return err + } + + err = e.scrapeInstalledExtensions(ctx, instance.db, ch) + if err != nil { + return err + } + + return nil +} + +func (e *ExtensionsCollector) scrapeInstalledExtensions(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error { + rowsExtensions, err := db.QueryContext(ctx, `SELECT extname, extrelocatable, extversion FROM pg_extension`) + + if err != nil { + return err + } + defer rowsExtensions.Close() + + for rowsExtensions.Next() { + var extname string + var extrelocatable bool + var extversion string + if err := rowsExtensions.Scan(&extname, &extrelocatable, &extversion); err != nil { + return err + } + + ch <- prometheus.MustNewConstMetric( + pgExtensions["pg_extensions"], + prometheus.GaugeValue, + 1, + extname, + strconv.FormatBool(extrelocatable), + extversion, + ) + } + + return nil +} + +func (e *ExtensionsCollector) scrapeAvailableExtensions(ctx context.Context, db *sql.DB, ch chan<- prometheus.Metric) error { + rows, err := db.QueryContext(ctx, `SELECT name, default_version, installed_version FROM pg_available_extensions`) + if err != nil { + return err + } + defer rows.Close() + + for rows.Next() { + var name sql.NullString + var defaultVersion sql.NullString + var installedVersion sql.NullString + if err := rows.Scan(&name, &defaultVersion, &installedVersion); err != nil { + return err + } + + ch <- prometheus.MustNewConstMetric( + pgExtensions["pg_available_extensions"], + prometheus.GaugeValue, + 1, + name.String, + defaultVersion.String, + installedVersion.String, + ) + } + + return nil +} + +var _ = (Collector)(&ExtensionsCollector{}) diff --git a/collector/pg_replication_slot.go b/collector/pg_replication_slot.go index c625fd4d5..5d1be02d1 100644 --- a/collector/pg_replication_slot.go +++ b/collector/pg_replication_slot.go @@ -43,7 +43,7 @@ var ( "slot_current_wal_lsn", ), "current wal lsn value", - []string{"slot_name"}, nil, + []string{"slot_name", "plugin", "slot_type"}, nil, ) pgReplicationSlotCurrentFlushDesc = prometheus.NewDesc( prometheus.BuildFQName( @@ -52,7 +52,7 @@ var ( "slot_confirmed_flush_lsn", ), "last lsn confirmed flushed to the replication slot", - []string{"slot_name"}, nil, + []string{"slot_name", "plugin", "slot_type"}, nil, ) pgReplicationSlotIsActiveDesc = prometheus.NewDesc( prometheus.BuildFQName( @@ -61,17 +61,19 @@ var ( "slot_is_active", ), "whether the replication slot is active or not", - []string{"slot_name"}, nil, + []string{"slot_name", "plugin", "slot_type"}, nil, ) pgReplicationSlotQuery = `SELECT slot_name, - CASE WHEN pg_is_in_recovery() THEN + plugin, + slot_type, + CASE WHEN pg_is_in_recovery() THEN pg_last_wal_receive_lsn() - '0/0' - ELSE - pg_current_wal_lsn() - '0/0' + ELSE + pg_current_wal_lsn() - '0/0' END AS current_wal_lsn, - COALESCE(confirmed_flush_lsn, '0/0') - '0/0', + COALESCE(confirmed_flush_lsn, '0/0') - '0/0' AS confirmed_flush_lsn, active FROM pg_replication_slots;` ) @@ -87,10 +89,12 @@ func (PGReplicationSlotCollector) Update(ctx context.Context, instance *instance for rows.Next() { var slotName sql.NullString + var plugin sql.NullString + var slotType sql.NullString var walLSN sql.NullFloat64 var flushLSN sql.NullFloat64 var isActive sql.NullBool - if err := rows.Scan(&slotName, &walLSN, &flushLSN, &isActive); err != nil { + if err := rows.Scan(&slotName, &plugin, &slotType, &walLSN, &flushLSN, &isActive); err != nil { return err } @@ -102,6 +106,14 @@ func (PGReplicationSlotCollector) Update(ctx context.Context, instance *instance if slotName.Valid { slotNameLabel = slotName.String } + pluginLabel := "unknown" + if plugin.Valid { + pluginLabel = plugin.String + } + slotTypeLabel := "unknown" + if slotType.Valid { + slotTypeLabel = slotType.String + } var walLSNMetric float64 if walLSN.Valid { @@ -109,7 +121,7 @@ func (PGReplicationSlotCollector) Update(ctx context.Context, instance *instance } ch <- prometheus.MustNewConstMetric( pgReplicationSlotCurrentWalDesc, - prometheus.GaugeValue, walLSNMetric, slotNameLabel, + prometheus.GaugeValue, walLSNMetric, slotNameLabel, pluginLabel, slotTypeLabel, ) if isActive.Valid && isActive.Bool { var flushLSNMetric float64 @@ -118,12 +130,12 @@ func (PGReplicationSlotCollector) Update(ctx context.Context, instance *instance } ch <- prometheus.MustNewConstMetric( pgReplicationSlotCurrentFlushDesc, - prometheus.GaugeValue, flushLSNMetric, slotNameLabel, + prometheus.GaugeValue, flushLSNMetric, slotNameLabel, pluginLabel, slotTypeLabel, ) } ch <- prometheus.MustNewConstMetric( pgReplicationSlotIsActiveDesc, - prometheus.GaugeValue, isActiveValue, slotNameLabel, + prometheus.GaugeValue, isActiveValue, slotNameLabel, pluginLabel, slotTypeLabel, ) } return rows.Err() diff --git a/collector/pg_replication_slot_test.go b/collector/pg_replication_slot_test.go index 7e91ea261..3b0005aba 100644 --- a/collector/pg_replication_slot_test.go +++ b/collector/pg_replication_slot_test.go @@ -31,9 +31,9 @@ func TestPgReplicationSlotCollectorActive(t *testing.T) { inst := &instance{db: db} - columns := []string{"slot_name", "current_wal_lsn", "confirmed_flush_lsn", "active"} + columns := []string{"slot_name", "plugin", "slot_type", "current_wal_lsn", "confirmed_flush_lsn", "active"} rows := sqlmock.NewRows(columns). - AddRow("test_slot", 5, 3, true) + AddRow("test_slot", "test_decoding", "physical", 5, 3, true) mock.ExpectQuery(sanitizeQuery(pgReplicationSlotQuery)).WillReturnRows(rows) ch := make(chan prometheus.Metric) @@ -47,9 +47,9 @@ func TestPgReplicationSlotCollectorActive(t *testing.T) { }() expected := []MetricResult{ - {labels: labelMap{"slot_name": "test_slot"}, value: 5, metricType: dto.MetricType_GAUGE}, - {labels: labelMap{"slot_name": "test_slot"}, value: 3, metricType: dto.MetricType_GAUGE}, - {labels: labelMap{"slot_name": "test_slot"}, value: 1, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "test_slot", "plugin": "test_decoding", "slot_type": "physical"}, value: 5, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "test_slot", "plugin": "test_decoding", "slot_type": "physical"}, value: 3, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "test_slot", "plugin": "test_decoding", "slot_type": "physical"}, value: 1, metricType: dto.MetricType_GAUGE}, } convey.Convey("Metrics comparison", t, func() { @@ -72,9 +72,9 @@ func TestPgReplicationSlotCollectorInActive(t *testing.T) { inst := &instance{db: db} - columns := []string{"slot_name", "current_wal_lsn", "confirmed_flush_lsn", "active"} + columns := []string{"slot_name", "plugin", "slot_type", "current_wal_lsn", "confirmed_flush_lsn", "active"} rows := sqlmock.NewRows(columns). - AddRow("test_slot", 6, 12, false) + AddRow("test_slot", "test_decoding", "physical", 6, 12, false) mock.ExpectQuery(sanitizeQuery(pgReplicationSlotQuery)).WillReturnRows(rows) ch := make(chan prometheus.Metric) @@ -88,8 +88,8 @@ func TestPgReplicationSlotCollectorInActive(t *testing.T) { }() expected := []MetricResult{ - {labels: labelMap{"slot_name": "test_slot"}, value: 6, metricType: dto.MetricType_GAUGE}, - {labels: labelMap{"slot_name": "test_slot"}, value: 0, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "test_slot", "plugin": "test_decoding", "slot_type": "physical"}, value: 6, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "test_slot", "plugin": "test_decoding", "slot_type": "physical"}, value: 0, metricType: dto.MetricType_GAUGE}, } convey.Convey("Metrics comparison", t, func() { @@ -113,9 +113,9 @@ func TestPgReplicationSlotCollectorActiveNil(t *testing.T) { inst := &instance{db: db} - columns := []string{"slot_name", "current_wal_lsn", "confirmed_flush_lsn", "active"} + columns := []string{"slot_name", "plugin", "slot_type", "current_wal_lsn", "confirmed_flush_lsn", "active"} rows := sqlmock.NewRows(columns). - AddRow("test_slot", 6, 12, nil) + AddRow("test_slot", "test_decoding", "physical", 6, 12, nil) mock.ExpectQuery(sanitizeQuery(pgReplicationSlotQuery)).WillReturnRows(rows) ch := make(chan prometheus.Metric) @@ -129,8 +129,8 @@ func TestPgReplicationSlotCollectorActiveNil(t *testing.T) { }() expected := []MetricResult{ - {labels: labelMap{"slot_name": "test_slot"}, value: 6, metricType: dto.MetricType_GAUGE}, - {labels: labelMap{"slot_name": "test_slot"}, value: 0, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "test_slot", "plugin": "test_decoding", "slot_type": "physical"}, value: 6, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "test_slot", "plugin": "test_decoding", "slot_type": "physical"}, value: 0, metricType: dto.MetricType_GAUGE}, } convey.Convey("Metrics comparison", t, func() { @@ -153,9 +153,9 @@ func TestPgReplicationSlotCollectorTestNilValues(t *testing.T) { inst := &instance{db: db} - columns := []string{"slot_name", "current_wal_lsn", "confirmed_flush_lsn", "active"} + columns := []string{"slot_name", "plugin", "slot_type", "current_wal_lsn", "confirmed_flush_lsn", "active"} rows := sqlmock.NewRows(columns). - AddRow(nil, nil, nil, true) + AddRow(nil, nil, nil, nil, nil, true) mock.ExpectQuery(sanitizeQuery(pgReplicationSlotQuery)).WillReturnRows(rows) ch := make(chan prometheus.Metric) @@ -169,9 +169,9 @@ func TestPgReplicationSlotCollectorTestNilValues(t *testing.T) { }() expected := []MetricResult{ - {labels: labelMap{"slot_name": "unknown"}, value: 0, metricType: dto.MetricType_GAUGE}, - {labels: labelMap{"slot_name": "unknown"}, value: 0, metricType: dto.MetricType_GAUGE}, - {labels: labelMap{"slot_name": "unknown"}, value: 1, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "unknown", "plugin": "unknown", "slot_type": "unknown"}, value: 0, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "unknown", "plugin": "unknown", "slot_type": "unknown"}, value: 0, metricType: dto.MetricType_GAUGE}, + {labels: labelMap{"slot_name": "unknown", "plugin": "unknown", "slot_type": "unknown"}, value: 1, metricType: dto.MetricType_GAUGE}, } convey.Convey("Metrics comparison", t, func() { diff --git a/collector/pg_stat_bgwriter.go b/collector/pg_stat_bgwriter.go index ec446d58c..0b73b4f44 100644 --- a/collector/pg_stat_bgwriter.go +++ b/collector/pg_stat_bgwriter.go @@ -16,7 +16,7 @@ package collector import ( "context" "database/sql" - + "github.com/blang/semver/v4" "github.com/prometheus/client_golang/prometheus" ) @@ -37,71 +37,140 @@ var ( statBGWriterCheckpointsTimedDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoints_timed_total"), "Number of scheduled checkpoints that have been performed", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterCheckpointsReqDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoints_req_total"), "Number of requested checkpoints that have been performed", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterCheckpointsReqTimeDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoint_write_time_total"), "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterCheckpointsSyncTimeDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoint_sync_time_total"), "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterBuffersCheckpointDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_checkpoint_total"), "Number of buffers written during checkpoints", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterBuffersCleanDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_clean_total"), "Number of buffers written by the background writer", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterMaxwrittenCleanDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "maxwritten_clean_total"), "Number of times the background writer stopped a cleaning scan because it had written too many buffers", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterBuffersBackendDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_backend_total"), "Number of buffers written directly by a backend", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterBuffersBackendFsyncDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_backend_fsync_total"), "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterBuffersAllocDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_alloc_total"), "Number of buffers allocated", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) statBGWriterStatsResetDesc = prometheus.NewDesc( prometheus.BuildFQName(namespace, bgWriterSubsystem, "stats_reset_total"), "Time at which these statistics were last reset", - []string{}, + []string{"collector", "server"}, prometheus.Labels{}, ) +) +var statBGWriter = map[string]*prometheus.Desc{ + "percona_checkpoints_timed": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoints_timed"), + "Number of scheduled checkpoints that have been performed", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_checkpoints_req": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoints_req"), + "Number of requested checkpoints that have been performed", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_checkpoint_write_time": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoint_write_time"), + "Total amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in milliseconds", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_checkpoint_sync_time": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "checkpoint_sync_time"), + "Total amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in milliseconds", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_buffers_checkpoint": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_checkpoint"), + "Number of buffers written during checkpoints", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_buffers_clean": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_clean"), + "Number of buffers written by the background writer", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_maxwritten_clean": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "maxwritten_clean"), + "Number of times the background writer stopped a cleaning scan because it had written too many buffers", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_buffers_backend": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_backend"), + "Number of buffers written directly by a backend", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_buffers_backend_fsync": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_backend_fsync"), + "Number of times a backend had to execute its own fsync call (normally the background writer handles those even when the backend does its own write)", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_buffers_alloc": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "buffers_alloc"), + "Number of buffers allocated", + []string{"collector", "server"}, + prometheus.Labels{}, + ), + "percona_stats_reset": prometheus.NewDesc( + prometheus.BuildFQName(namespace, bgWriterSubsystem, "stats_reset"), + "Time at which these statistics were last reset", + []string{"collector", "server"}, + prometheus.Labels{}, + ), +} - statBGWriterQuery = `SELECT +const statBGWriterQueryPrePG17 = `SELECT checkpoints_timed ,checkpoints_req ,checkpoint_write_time @@ -114,20 +183,56 @@ var ( ,buffers_alloc ,stats_reset FROM pg_stat_bgwriter;` -) -func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error { +const statBGWriterQueryPost17 = `SELECT + buffers_clean + ,maxwritten_clean + ,buffers_alloc + ,stats_reset + FROM pg_stat_bgwriter;` + +const statCheckpointerQuery = `SELECT + num_timed + ,num_requested + ,restartpoints_timed + ,restartpoints_req + ,restartpoints_done + ,write_time + ,sync_time + ,buffers_written + ,stats_reset + FROM pg_stat_checkpointer;` + +func (p PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, ch chan<- prometheus.Metric) error { db := instance.getDB() - row := db.QueryRowContext(ctx, - statBGWriterQuery) var cpt, cpr, bcp, bc, mwc, bb, bbf, ba sql.NullInt64 var cpwt, cpst sql.NullFloat64 var sr sql.NullTime - err := row.Scan(&cpt, &cpr, &cpwt, &cpst, &bcp, &bc, &mwc, &bb, &bbf, &ba, &sr) - if err != nil { - return err + if instance.version.GE(semver.MustParse("17.0.0")) { + row := db.QueryRowContext(ctx, + statBGWriterQueryPost17) + err := row.Scan(&bc, &mwc, &ba, &sr) + if err != nil { + return err + } + var rpt, rpr, rpd sql.NullInt64 + var csr sql.NullTime + // these variables are not used, but I left them here for reference + row = db.QueryRowContext(ctx, + statCheckpointerQuery) + err = row.Scan(&cpt, &cpr, &rpt, &rpr, &rpd, &cpwt, &cpst, &bcp, &csr) + if err != nil { + return err + } + } else { + row := db.QueryRowContext(ctx, + statBGWriterQueryPrePG17) + err := row.Scan(&cpt, &cpr, &cpwt, &cpst, &bcp, &bc, &mwc, &bb, &bbf, &ba, &sr) + if err != nil { + return err + } } cptMetric := 0.0 @@ -138,6 +243,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterCheckpointsTimedDesc, prometheus.CounterValue, cptMetric, + "exporter", + instance.name, ) cprMetric := 0.0 if cpr.Valid { @@ -147,6 +254,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterCheckpointsReqDesc, prometheus.CounterValue, cprMetric, + "exporter", + instance.name, ) cpwtMetric := 0.0 if cpwt.Valid { @@ -156,6 +265,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterCheckpointsReqTimeDesc, prometheus.CounterValue, cpwtMetric, + "exporter", + instance.name, ) cpstMetric := 0.0 if cpst.Valid { @@ -165,6 +276,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterCheckpointsSyncTimeDesc, prometheus.CounterValue, cpstMetric, + "exporter", + instance.name, ) bcpMetric := 0.0 if bcp.Valid { @@ -174,6 +287,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterBuffersCheckpointDesc, prometheus.CounterValue, bcpMetric, + "exporter", + instance.name, ) bcMetric := 0.0 if bc.Valid { @@ -183,6 +298,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterBuffersCleanDesc, prometheus.CounterValue, bcMetric, + "exporter", + instance.name, ) mwcMetric := 0.0 if mwc.Valid { @@ -192,6 +309,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterMaxwrittenCleanDesc, prometheus.CounterValue, mwcMetric, + "exporter", + instance.name, ) bbMetric := 0.0 if bb.Valid { @@ -201,6 +320,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterBuffersBackendDesc, prometheus.CounterValue, bbMetric, + "exporter", + instance.name, ) bbfMetric := 0.0 if bbf.Valid { @@ -210,6 +331,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterBuffersBackendFsyncDesc, prometheus.CounterValue, bbfMetric, + "exporter", + instance.name, ) baMetric := 0.0 if ba.Valid { @@ -219,6 +342,8 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterBuffersAllocDesc, prometheus.CounterValue, baMetric, + "exporter", + instance.name, ) srMetric := 0.0 if sr.Valid { @@ -228,7 +353,88 @@ func (PGStatBGWriterCollector) Update(ctx context.Context, instance *instance, c statBGWriterStatsResetDesc, prometheus.CounterValue, srMetric, + "exporter", + instance.name, ) + // TODO: analyze metrics below, why do we duplicate them? + + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_checkpoints_timed"], + prometheus.CounterValue, + cptMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_checkpoints_req"], + prometheus.CounterValue, + cprMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_checkpoint_write_time"], + prometheus.CounterValue, + cpwtMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_checkpoint_sync_time"], + prometheus.CounterValue, + cpstMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_buffers_checkpoint"], + prometheus.CounterValue, + bcpMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_buffers_clean"], + prometheus.CounterValue, + bcMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_maxwritten_clean"], + prometheus.CounterValue, + mwcMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_buffers_backend"], + prometheus.CounterValue, + bbMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_buffers_backend_fsync"], + prometheus.CounterValue, + bbfMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_buffers_alloc"], + prometheus.CounterValue, + baMetric, + "exporter", + instance.name, + ) + ch <- prometheus.MustNewConstMetric( + statBGWriter["percona_stats_reset"], + prometheus.CounterValue, + srMetric, + "exporter", + instance.name, + ) return nil } diff --git a/collector/pg_stat_bgwriter_test.go b/collector/pg_stat_bgwriter_test.go index 1c2cf98de..6d137b06f 100644 --- a/collector/pg_stat_bgwriter_test.go +++ b/collector/pg_stat_bgwriter_test.go @@ -30,7 +30,7 @@ func TestPGStatBGWriterCollector(t *testing.T) { } defer db.Close() - inst := &instance{db: db} + inst := &instance{db: db, name: "test"} columns := []string{ "checkpoints_timed", @@ -52,7 +52,7 @@ func TestPGStatBGWriterCollector(t *testing.T) { rows := sqlmock.NewRows(columns). AddRow(354, 4945, 289097744, 1242257, int64(3275602074), 89320867, 450139, 2034563757, 0, int64(2725688749), srT) - mock.ExpectQuery(sanitizeQuery(statBGWriterQuery)).WillReturnRows(rows) + mock.ExpectQuery(sanitizeQuery(statBGWriterQueryPrePG17)).WillReturnRows(rows) ch := make(chan prometheus.Metric) go func() { @@ -64,18 +64,19 @@ func TestPGStatBGWriterCollector(t *testing.T) { } }() + labels := labelMap{"collector": "exporter", "server": "test"} expected := []MetricResult{ - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 354}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 4945}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 289097744}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 1242257}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 3275602074}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 89320867}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 450139}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 2034563757}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 2725688749}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 1685059842}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 354}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 4945}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 289097744}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 1242257}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 3275602074}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 89320867}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 450139}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 2034563757}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 2725688749}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 1685059842}, } convey.Convey("Metrics comparison", t, func() { @@ -96,7 +97,7 @@ func TestPGStatBGWriterCollectorNullValues(t *testing.T) { } defer db.Close() - inst := &instance{db: db} + inst := &instance{db: db, name: "test"} columns := []string{ "checkpoints_timed", @@ -113,7 +114,7 @@ func TestPGStatBGWriterCollectorNullValues(t *testing.T) { rows := sqlmock.NewRows(columns). AddRow(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) - mock.ExpectQuery(sanitizeQuery(statBGWriterQuery)).WillReturnRows(rows) + mock.ExpectQuery(sanitizeQuery(statBGWriterQueryPrePG17)).WillReturnRows(rows) ch := make(chan prometheus.Metric) go func() { @@ -125,18 +126,19 @@ func TestPGStatBGWriterCollectorNullValues(t *testing.T) { } }() + labels := labelMap{"collector": "exporter", "server": "test"} expected := []MetricResult{ - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, - {labels: labelMap{}, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, + {labels: labels, metricType: dto.MetricType_COUNTER, value: 0}, } convey.Convey("Metrics comparison", t, func() { diff --git a/collector/pg_wal.go b/collector/pg_wal.go index afa8fcef6..a618b7961 100644 --- a/collector/pg_wal.go +++ b/collector/pg_wal.go @@ -22,7 +22,7 @@ import ( const walSubsystem = "wal" func init() { - registerCollector(walSubsystem, defaultEnabled, NewPGWALCollector) + registerCollector(walSubsystem, defaultDisabled, NewPGWALCollector) } type PGWALCollector struct { diff --git a/collector/probe.go b/collector/probe.go index 4c0f0419b..5ac46aab4 100644 --- a/collector/probe.go +++ b/collector/probe.go @@ -21,6 +21,7 @@ import ( "github.com/go-kit/log/level" "github.com/prometheus-community/postgres_exporter/config" "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sync/semaphore" ) type ProbeCollector struct { @@ -28,9 +29,11 @@ type ProbeCollector struct { collectors map[string]Collector logger log.Logger instance *instance + connSema *semaphore.Weighted + ctx context.Context } -func NewProbeCollector(logger log.Logger, excludeDatabases []string, registry *prometheus.Registry, dsn config.DSN) (*ProbeCollector, error) { +func NewProbeCollector(ctx context.Context, logger log.Logger, excludeDatabases []string, registry *prometheus.Registry, dsn config.DSN, connSema *semaphore.Weighted) (*ProbeCollector, error) { collectors := make(map[string]Collector) initiatedCollectorsMtx.Lock() defer initiatedCollectorsMtx.Unlock() @@ -68,6 +71,8 @@ func NewProbeCollector(logger log.Logger, excludeDatabases []string, registry *p collectors: collectors, logger: logger, instance: instance, + connSema: connSema, + ctx: ctx, }, nil } @@ -75,6 +80,12 @@ func (pc *ProbeCollector) Describe(ch chan<- *prometheus.Desc) { } func (pc *ProbeCollector) Collect(ch chan<- prometheus.Metric) { + if err := pc.connSema.Acquire(pc.ctx, 1); err != nil { + level.Warn(pc.logger).Log("msg", "Failed to acquire semaphore", "err", err) + return + } + defer pc.connSema.Release(1) + // Set up the database connection for the collector. err := pc.instance.setup() if err != nil { @@ -87,7 +98,7 @@ func (pc *ProbeCollector) Collect(ch chan<- prometheus.Metric) { wg.Add(len(pc.collectors)) for name, c := range pc.collectors { go func(name string, c Collector) { - execute(context.TODO(), name, c, pc.instance, ch, pc.logger) + execute(pc.ctx, name, c, pc.instance, ch, pc.logger) wg.Done() }(name, c) } diff --git a/docker-compose.md b/docker-compose.md new file mode 100644 index 000000000..d376b5662 --- /dev/null +++ b/docker-compose.md @@ -0,0 +1,24 @@ +In order to start PostgreSQL with SSL support, we need to change the file permissions +for the ssl cert and key. + +Please run these commands if you want to run `docker compose` locally. + +sudo chown 999:999 testdata/ssl/server/* +sudo chmod 0600 testdata/ssl/server/* + +Start the container: +``` +`docker compose` up +``` + +To be able to connect from pgsql you need to own the certs + +sudo chown ${USER}:${USER} testdata/ssl/client* +sudo chmod 0600 testdata/ssl/client/* + +Connect using psql + +``` +psql "host=127.0.0.1 port=5433 user=root password=root dbname=postgres sslmode=verify-ca sslcert=${PWD}/testdata/ssl/client/server.crt sslkey=${PWD}/testdata/ssl/client/server.key sslrootcert=${PWD}/testdata/ssl/client/CA.crt" +``` + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..f65936eda --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +--- +services: + postgresql: + image: ${POSTGRESQL_IMAGE:-postgres} + container_name: postgres_exporter_postgresql + ports: + - 127.0.0.1:5432:5432 + environment: + - POSTGRES_USER=root + - POSTGRES_PASSWORD=root + + postgresql-ssl: + image: ${POSTGRESQL_IMAGE:-postgres} + container_name: postgres_exporter_postgresql-ssl + command: > + -c ssl=on + -c ssl_cert_file=/ssl/server.crt + -c ssl_key_file=/ssl/server.key + -c ssl_ca_file=/ssl/CA.crt + -c log_min_messages=DEBUG4 + ports: + - 5433:5432 + environment: + - POSTGRES_USER=root + - POSTGRES_PASSWORD=root + volumes: + - ./testdata/ssl/server:/ssl diff --git a/example-queries-postgres.yml b/example-queries-postgres.yml new file mode 100644 index 000000000..077439931 --- /dev/null +++ b/example-queries-postgres.yml @@ -0,0 +1,11 @@ +## ###################################################### +## WARNING: This is an example. Do not edit this file. +## To create your own Custom Queries - create a new file +## ###################################################### +## Custom query example. +#pg_replication: +# query: "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) as lag" +# metrics: +# - lag: +# usage: "GAUGE" +# description: "Replication lag behind master in seconds" diff --git a/example.alerts.yml b/example.alerts.yml new file mode 100644 index 000000000..1b08a437f --- /dev/null +++ b/example.alerts.yml @@ -0,0 +1,57 @@ +--- +groups: + - name: PostgreSQL + rules: + - alert: PostgreSQLMaxConnectionsReached + expr: sum(pg_stat_activity_count) by (instance) > sum(pg_settings_max_connections) by (instance) + for: 1m + labels: + severity: email + annotations: + summary: "{{ $labels.instance }} has maxed out Postgres connections." + description: "{{ $labels.instance }} is exceeding the currently configured maximum Postgres connection limit (current value: {{ $value }}s). Services may be degraded - please take immediate action (you probably need to increase max_connections in the Docker image and re-deploy." + + - alert: PostgreSQLHighConnections + expr: sum(pg_stat_activity_count) by (instance) > sum(pg_settings_max_connections * 0.8) by (instance) + for: 10m + labels: + severity: email + annotations: + summary: "{{ $labels.instance }} is over 80% of max Postgres connections." + description: "{{ $labels.instance }} is exceeding 80% of the currently configured maximum Postgres connection limit (current value: {{ $value }}s). Please check utilization graphs and confirm if this is normal service growth, abuse or an otherwise temporary condition or if new resources need to be provisioned (or the limits increased, which is mostly likely)." + + - alert: PostgreSQLDown + expr: pg_up != 1 + for: 1m + labels: + severity: email + annotations: + summary: "PostgreSQL is not processing queries: {{ $labels.instance }}" + description: "{{ $labels.instance }} is rejecting query requests from the exporter, and thus probably not allowing DNS requests to work either. User services should not be effected provided at least 1 node is still alive." + + - alert: PostgreSQLSlowQueries + expr: avg(rate(pg_stat_activity_max_tx_duration{datname!~"template.*"}[2m])) by (datname) > 2 * 60 + for: 2m + labels: + severity: email + annotations: + summary: "PostgreSQL high number of slow on {{ $labels.cluster }} for database {{ $labels.datname }} " + description: "PostgreSQL high number of slow queries {{ $labels.cluster }} for database {{ $labels.datname }} with a value of {{ $value }} " + + - alert: PostgreSQLQPS + expr: avg(irate(pg_stat_database_xact_commit{datname!~"template.*"}[5m]) + irate(pg_stat_database_xact_rollback{datname!~"template.*"}[5m])) by (datname) > 10000 + for: 5m + labels: + severity: email + annotations: + summary: "PostgreSQL high number of queries per second {{ $labels.cluster }} for database {{ $labels.datname }}" + description: "PostgreSQL high number of queries per second on {{ $labels.cluster }} for database {{ $labels.datname }} with a value of {{ $value }}" + + - alert: PostgreSQLCacheHitRatio + expr: avg(rate(pg_stat_database_blks_hit{datname!~"template.*"}[5m]) / (rate(pg_stat_database_blks_hit{datname!~"template.*"}[5m]) + rate(pg_stat_database_blks_read{datname!~"template.*"}[5m]))) by (datname) < 0.98 + for: 5m + labels: + severity: email + annotations: + summary: "PostgreSQL low cache hit rate on {{ $labels.cluster }} for database {{ $labels.datname }}" + description: "PostgreSQL low on cache hit rate on {{ $labels.cluster }} for database {{ $labels.datname }} with a value of {{ $value }}" diff --git a/go.mod b/go.mod index 4ddfbfbe5..78b0b3218 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,24 @@ module github.com/prometheus-community/postgres_exporter -go 1.19 +go 1.22 require ( - github.com/DATA-DOG/go-sqlmock v1.5.0 - github.com/alecthomas/kingpin/v2 v2.3.2 + github.com/DATA-DOG/go-sqlmock v1.5.2 + github.com/alecthomas/kingpin/v2 v2.4.0 github.com/blang/semver/v4 v4.0.0 github.com/go-kit/log v0.2.1 github.com/lib/pq v1.10.9 - github.com/prometheus/client_golang v1.17.0 - github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 - github.com/prometheus/common v0.44.0 - github.com/prometheus/exporter-toolkit v0.10.0 + github.com/montanaflynn/stats v0.7.1 + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.60.1 + github.com/prometheus/exporter-toolkit v0.13.1 github.com/smartystreets/goconvey v1.8.1 + github.com/stretchr/testify v1.10.0 + github.com/tklauser/go-sysconf v0.3.14 + golang.org/x/sync v0.11.0 + golang.org/x/sys v0.30.0 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 @@ -21,27 +27,29 @@ require ( require ( github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mdlayher/socket v0.4.1 // indirect + github.com/mdlayher/vsock v1.2.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/smarty/assertions v1.15.0 // indirect + github.com/tklauser/numcpus v0.8.0 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect ) diff --git a/go.sum b/go.sum index 3a163d16b..cfbc9dfbe 100644 --- a/go.sum +++ b/go.sum @@ -1,38 +1,37 @@ -github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= -github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +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/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -40,25 +39,35 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= +github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/exporter-toolkit v0.10.0 h1:yOAzZTi4M22ZzVxD+fhy1URTuNRj/36uQJJ5S8IPza8= -github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/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_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/exporter-toolkit v0.13.1 h1:Evsh0gWQo2bdOHlnz9+0Nm7/OFfIwhE2Ws4A2jIlR04= +github.com/prometheus/exporter-toolkit v0.13.1/go.mod h1:ujdv2YIOxtdFxxqtloLpbqmxd5J0Le6IITUvIRSWjj0= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= @@ -68,35 +77,28 @@ github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sS github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= +github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= +github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= +github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/percona_tests/Makefile b/percona_tests/Makefile new file mode 100644 index 000000000..7cfb3c767 --- /dev/null +++ b/percona_tests/Makefile @@ -0,0 +1,49 @@ +######################### +### tests + +# measures avg scrape time and compares old vs new exporters +test-performance: + go test -v -run '^TestPerformance$$' -args -doRun=true + +extraMetrics = false +multipleLabels = false +dumpMetrics = false +endpoint = '' + +test-metrics: + go test -v -run '^TestMissingMetrics$$' -args -doRun=true + +test-labels: + go test -v -run '^TestMissingLabels$$' -args -doRun=true + +test-resolutions-duplicates: + go test -v -run '^TestResolutionsMetricDuplicates$$' -args -doRun=true + +test-resolutions: + go test -v -run '^TestResolutions$$' -args -doRun=true + +dump-metrics: + go test -v -run '^TestDumpMetrics$$' -args -doRun=true -extraMetrics=$(extraMetrics) -multipleLabels=$(multipleLabels) -endpoint=$(endpoint) -dumpMetrics=true + +test-consistency: test-metrics test-resolutions test-resolutions-duplicates + +######################### +### env preparation + +# download exporter from provided feature build's client binary url +prepare-exporter-from-fb: + go test -v -run '^TestPrepareUpdatedExporter$\' -args -doRun=true -url=$(url) + +prepare-exporter-from-repo: + make -C ../ build && cp ../postgres_exporter assets/postgres_exporter + +prepare-base-exporter: + tar -xf assets/postgres_exporter_percona.tar.gz -C assets/ + +start-postgres-db: + docker compose up -d --force-recreate --renew-anon-volumes --remove-orphans + +stop-postgres-db: + docker compose down + +prepare-env-from-repo: prepare-exporter-from-repo prepare-base-exporter start-postgres-db diff --git a/percona_tests/assets/postgres_exporter.yml b/percona_tests/assets/postgres_exporter.yml new file mode 100644 index 000000000..7bcbbcbce --- /dev/null +++ b/percona_tests/assets/postgres_exporter.yml @@ -0,0 +1 @@ +auth_modules: \ No newline at end of file diff --git a/percona_tests/assets/postgres_exporter_percona.tar.xz b/percona_tests/assets/postgres_exporter_percona.tar.xz new file mode 100644 index 000000000..b60296b5e Binary files /dev/null and b/percona_tests/assets/postgres_exporter_percona.tar.xz differ diff --git a/percona_tests/assets/test.new-flags.txt b/percona_tests/assets/test.new-flags.txt new file mode 100644 index 000000000..d591889b2 --- /dev/null +++ b/percona_tests/assets/test.new-flags.txt @@ -0,0 +1,7 @@ +--auto-discover-databases +--collect.custom_query.hr +--collect.custom_query.lr +--collect.custom_query.mr +--exclude-databases=template0,template1,postgres,cloudsqladmin,pmm-managed-dev,azure_maintenance,rdsadmin +--log.level=warn +--config.file=assets/postgres_exporter.yml \ No newline at end of file diff --git a/percona_tests/assets/test.old-flags.txt b/percona_tests/assets/test.old-flags.txt new file mode 100644 index 000000000..00b84c100 --- /dev/null +++ b/percona_tests/assets/test.old-flags.txt @@ -0,0 +1,6 @@ +--auto-discover-databases +--collect.custom_query.hr +--collect.custom_query.lr +--collect.custom_query.mr +--exclude-databases=template0,template1,postgres,cloudsqladmin,pmm-managed-dev,azure_maintenance,rdsadmin +--log.level=warn \ No newline at end of file diff --git a/percona_tests/custom-queries/high-resolution/example-queries-postgres.yml b/percona_tests/custom-queries/high-resolution/example-queries-postgres.yml new file mode 100644 index 000000000..077439931 --- /dev/null +++ b/percona_tests/custom-queries/high-resolution/example-queries-postgres.yml @@ -0,0 +1,11 @@ +## ###################################################### +## WARNING: This is an example. Do not edit this file. +## To create your own Custom Queries - create a new file +## ###################################################### +## Custom query example. +#pg_replication: +# query: "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) as lag" +# metrics: +# - lag: +# usage: "GAUGE" +# description: "Replication lag behind master in seconds" diff --git a/percona_tests/custom-queries/high-resolution/queries-postgres-uptime.yml b/percona_tests/custom-queries/high-resolution/queries-postgres-uptime.yml new file mode 100644 index 000000000..eccd86a55 --- /dev/null +++ b/percona_tests/custom-queries/high-resolution/queries-postgres-uptime.yml @@ -0,0 +1,7 @@ +pg_postmaster_uptime: + query: "select extract(epoch from current_timestamp - pg_postmaster_start_time()) as seconds" + master: true + metrics: + - seconds: + usage: "GAUGE" + description: "Service uptime" diff --git a/percona_tests/custom-queries/low-resolution/example-queries-postgres.yml b/percona_tests/custom-queries/low-resolution/example-queries-postgres.yml new file mode 100644 index 000000000..077439931 --- /dev/null +++ b/percona_tests/custom-queries/low-resolution/example-queries-postgres.yml @@ -0,0 +1,11 @@ +## ###################################################### +## WARNING: This is an example. Do not edit this file. +## To create your own Custom Queries - create a new file +## ###################################################### +## Custom query example. +#pg_replication: +# query: "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) as lag" +# metrics: +# - lag: +# usage: "GAUGE" +# description: "Replication lag behind master in seconds" diff --git a/percona_tests/custom-queries/medium-resolution/example-queries-postgres.yml b/percona_tests/custom-queries/medium-resolution/example-queries-postgres.yml new file mode 100644 index 000000000..077439931 --- /dev/null +++ b/percona_tests/custom-queries/medium-resolution/example-queries-postgres.yml @@ -0,0 +1,11 @@ +## ###################################################### +## WARNING: This is an example. Do not edit this file. +## To create your own Custom Queries - create a new file +## ###################################################### +## Custom query example. +#pg_replication: +# query: "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) as lag" +# metrics: +# - lag: +# usage: "GAUGE" +# description: "Replication lag behind master in seconds" diff --git a/percona_tests/custom-queries/medium-resolution/queries.yaml b/percona_tests/custom-queries/medium-resolution/queries.yaml new file mode 100644 index 000000000..b28a4f7a2 --- /dev/null +++ b/percona_tests/custom-queries/medium-resolution/queries.yaml @@ -0,0 +1,231 @@ +#### Queries are commented due to PMM-8859 +pg_replication: + query: "SELECT CASE WHEN NOT pg_is_in_recovery() THEN 0 ELSE GREATEST (0, EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))) END AS lag" + master: true + metrics: + - lag: + usage: "GAUGE" + description: "Replication lag behind master in seconds" + +pg_postmaster: + query: "SELECT pg_postmaster_start_time as start_time_seconds from pg_postmaster_start_time()" + master: true + metrics: + - start_time_seconds: + usage: "GAUGE" + description: "Time at which postmaster started" + +pg_stat_user_tables: + query: | + SELECT + current_database() datname, + schemaname, + relname, + seq_scan, + seq_tup_read, + idx_scan, + idx_tup_fetch, + n_tup_ins, + n_tup_upd, + n_tup_del, + n_tup_hot_upd, + n_live_tup, + n_dead_tup, + n_mod_since_analyze, + COALESCE(last_vacuum, '1970-01-01Z') as last_vacuum, + COALESCE(last_autovacuum, '1970-01-01Z') as last_autovacuum, + COALESCE(last_analyze, '1970-01-01Z') as last_analyze, + COALESCE(last_autoanalyze, '1970-01-01Z') as last_autoanalyze, + vacuum_count, + autovacuum_count, + analyze_count, + autoanalyze_count + FROM + pg_stat_user_tables + metrics: + - datname: + usage: "LABEL" + description: "Name of current database" + - schemaname: + usage: "LABEL" + description: "Name of the schema that this table is in" + - relname: + usage: "LABEL" + description: "Name of this table" + - seq_scan: + usage: "COUNTER" + description: "Number of sequential scans initiated on this table" + - seq_tup_read: + usage: "COUNTER" + description: "Number of live rows fetched by sequential scans" + - idx_scan: + usage: "COUNTER" + description: "Number of index scans initiated on this table" + - idx_tup_fetch: + usage: "COUNTER" + description: "Number of live rows fetched by index scans" + - n_tup_ins: + usage: "COUNTER" + description: "Number of rows inserted" + - n_tup_upd: + usage: "COUNTER" + description: "Number of rows updated" + - n_tup_del: + usage: "COUNTER" + description: "Number of rows deleted" + - n_tup_hot_upd: + usage: "COUNTER" + description: "Number of rows HOT updated (i.e., with no separate index update required)" + - n_live_tup: + usage: "GAUGE" + description: "Estimated number of live rows" + - n_dead_tup: + usage: "GAUGE" + description: "Estimated number of dead rows" + - n_mod_since_analyze: + usage: "GAUGE" + description: "Estimated number of rows changed since last analyze" + - last_vacuum: + usage: "GAUGE" + description: "Last time at which this table was manually vacuumed (not counting VACUUM FULL)" + - last_autovacuum: + usage: "GAUGE" + description: "Last time at which this table was vacuumed by the autovacuum daemon" + - last_analyze: + usage: "GAUGE" + description: "Last time at which this table was manually analyzed" + - last_autoanalyze: + usage: "GAUGE" + description: "Last time at which this table was analyzed by the autovacuum daemon" + - vacuum_count: + usage: "COUNTER" + description: "Number of times this table has been manually vacuumed (not counting VACUUM FULL)" + - autovacuum_count: + usage: "COUNTER" + description: "Number of times this table has been vacuumed by the autovacuum daemon" + - analyze_count: + usage: "COUNTER" + description: "Number of times this table has been manually analyzed" + - autoanalyze_count: + usage: "COUNTER" + description: "Number of times this table has been analyzed by the autovacuum daemon" + +pg_statio_user_tables: + query: "SELECT current_database() datname, schemaname, relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit, toast_blks_read, toast_blks_hit, tidx_blks_read, tidx_blks_hit FROM pg_statio_user_tables" + metrics: + - datname: + usage: "LABEL" + description: "Name of current database" + - schemaname: + usage: "LABEL" + description: "Name of the schema that this table is in" + - relname: + usage: "LABEL" + description: "Name of this table" + - heap_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from this table" + - heap_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in this table" + - idx_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from all indexes on this table" + - idx_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in all indexes on this table" + - toast_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from this table's TOAST table (if any)" + - toast_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in this table's TOAST table (if any)" + - tidx_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from this table's TOAST table indexes (if any)" + - tidx_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in this table's TOAST table indexes (if any)" + +pg_database: + query: "SELECT pg_database.datname, pg_database_size(pg_database.datname) as size_bytes FROM pg_database" + master: true + cache_seconds: 30 + metrics: + - datname: + usage: "LABEL" + description: "Name of the database" + - size_bytes: + usage: "GAUGE" + description: "Disk space used by the database" +#### +#pg_stat_statements: +# query: "SELECT t2.rolname, t3.datname, queryid, calls, total_time / 1000 as total_time_seconds, min_time / 1000 as min_time_seconds, max_time / 1000 as max_time_seconds, mean_time / 1000 as mean_time_seconds, stddev_time / 1000 as stddev_time_seconds, rows, shared_blks_hit, shared_blks_read, shared_blks_dirtied, shared_blks_written, local_blks_hit, local_blks_read, local_blks_dirtied, local_blks_written, temp_blks_read, temp_blks_written, blk_read_time / 1000 as blk_read_time_seconds, blk_write_time / 1000 as blk_write_time_seconds FROM pg_stat_statements t1 JOIN pg_roles t2 ON (t1.userid=t2.oid) JOIN pg_database t3 ON (t1.dbid=t3.oid) WHERE t2.rolname != 'rdsadmin'" +# master: true +# metrics: +# - rolname: +# usage: "LABEL" +# description: "Name of user" +# - datname: +# usage: "LABEL" +# description: "Name of database" +# - queryid: +# usage: "LABEL" +# description: "Query ID" +# - calls: +# usage: "COUNTER" +# description: "Number of times executed" +# - total_time_seconds: +# usage: "COUNTER" +# description: "Total time spent in the statement, in milliseconds" +# - min_time_seconds: +# usage: "GAUGE" +# description: "Minimum time spent in the statement, in milliseconds" +# - max_time_seconds: +# usage: "GAUGE" +# description: "Maximum time spent in the statement, in milliseconds" +# - mean_time_seconds: +# usage: "GAUGE" +# description: "Mean time spent in the statement, in milliseconds" +# - stddev_time_seconds: +# usage: "GAUGE" +# description: "Population standard deviation of time spent in the statement, in milliseconds" +# - rows: +# usage: "COUNTER" +# description: "Total number of rows retrieved or affected by the statement" +# - shared_blks_hit: +# usage: "COUNTER" +# description: "Total number of shared block cache hits by the statement" +# - shared_blks_read: +# usage: "COUNTER" +# description: "Total number of shared blocks read by the statement" +# - shared_blks_dirtied: +# usage: "COUNTER" +# description: "Total number of shared blocks dirtied by the statement" +# - shared_blks_written: +# usage: "COUNTER" +# description: "Total number of shared blocks written by the statement" +# - local_blks_hit: +# usage: "COUNTER" +# description: "Total number of local block cache hits by the statement" +# - local_blks_read: +# usage: "COUNTER" +# description: "Total number of local blocks read by the statement" +# - local_blks_dirtied: +# usage: "COUNTER" +# description: "Total number of local blocks dirtied by the statement" +# - local_blks_written: +# usage: "COUNTER" +# description: "Total number of local blocks written by the statement" +# - temp_blks_read: +# usage: "COUNTER" +# description: "Total number of temp blocks read by the statement" +# - temp_blks_written: +# usage: "COUNTER" +# description: "Total number of temp blocks written by the statement" +# - blk_read_time_seconds: +# usage: "COUNTER" +# description: "Total time the statement spent reading blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)" +# - blk_write_time_seconds: +# usage: "COUNTER" +# description: "Total time the statement spent writing blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)" diff --git a/percona_tests/docker-compose.yml b/percona_tests/docker-compose.yml new file mode 100644 index 000000000..a7c28fc2a --- /dev/null +++ b/percona_tests/docker-compose.yml @@ -0,0 +1,45 @@ +--- +version: '3.7' + +services: + postgres: + image: ${POSTGRES_IMAGE:-postgres:11} + container_name: postgres-test-srv + command: > + -c shared_preload_libraries='${PG_PRELOADED_LIBS:-pg_stat_statements}' + -c track_activity_query_size=2048 + -c pg_stat_statements.max=10000 + -c pg_stat_monitor.pgsm_query_max_len=10000 + -c pg_stat_statements.track=all + -c pg_stat_statements.save=off + -c track_io_timing=on + ports: + - "127.0.0.1:5432:5432" + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + volumes: + - postgres-test-srv-vol:/docker-entrypoint-initdb.d/ + networks: + - postgres-test-srv-net + + golang: + image: golang:1.21 + container_name: golang-test + command: > + tail -f ./assets/test.new-flags.txt + volumes: + - ../:/usr/src/myapp + - go-modules:/go/pkg/mod # Put modules cache into a separate volume + working_dir: /usr/src/myapp/percona_tests + depends_on: + - postgres + networks: + - postgres-test-srv-net + +volumes: + go-modules: # Define the volume + postgres-test-srv-vol: + +networks: + postgres-test-srv-net: \ No newline at end of file diff --git a/percona_tests/env_prepare_test.go b/percona_tests/env_prepare_test.go new file mode 100644 index 000000000..5df1f26a4 --- /dev/null +++ b/percona_tests/env_prepare_test.go @@ -0,0 +1,89 @@ +package percona_tests + +import ( + "archive/tar" + "compress/gzip" + "io" + "log" + "net/http" + "os" + "os/exec" + "strings" + "testing" +) + +// TestPrepareExporters extracts exporter from client binary's tar.gz +func TestPrepareUpdatedExporter(t *testing.T) { + if doRun == nil || !*doRun { + t.Skip("For manual runs only through make") + return + } + + if url == nil || *url == "" { + t.Error("URL not defined") + return + } + + prepareExporter(*url, updatedExporterFileName) +} + +func extractExporter(gzipStream io.Reader, fileName string) { + uncompressedStream, err := gzip.NewReader(gzipStream) + if err != nil { + log.Fatal("ExtractTarGz: NewReader failed") + } + + tarReader := tar.NewReader(uncompressedStream) + + exporterFound := false + for !exporterFound { + header, err := tarReader.Next() + + if err == io.EOF { + break + } + + if err != nil { + log.Fatalf("ExtractTarGz: Next() failed: %s", err.Error()) + } + + switch header.Typeflag { + case tar.TypeDir: + continue + case tar.TypeReg: + if strings.HasSuffix(header.Name, "postgres_exporter") { + outFile, err := os.Create(fileName) + if err != nil { + log.Fatalf("ExtractTarGz: Create() failed: %s", err.Error()) + } + defer outFile.Close() + if _, err := io.Copy(outFile, tarReader); err != nil { + log.Fatalf("ExtractTarGz: Copy() failed: %s", err.Error()) + } + + exporterFound = true + } + default: + log.Fatalf( + "ExtractTarGz: uknown type: %d in %s", + header.Typeflag, + header.Name) + } + } +} + +func prepareExporter(url, fileName string) { + resp, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + defer resp.Body.Close() + + extractExporter(resp.Body, fileName) + + err = exec.Command("chmod", "+x", fileName).Run() + if err != nil { + log.Fatal(err) + } +} diff --git a/percona_tests/metrics_test.go b/percona_tests/metrics_test.go new file mode 100644 index 000000000..d59d30516 --- /dev/null +++ b/percona_tests/metrics_test.go @@ -0,0 +1,606 @@ +package percona_tests + +import ( + "flag" + "fmt" + "os" + "sort" + "strings" + "testing" + + "github.com/pkg/errors" +) + +var dumpMetricsFlag = flag.Bool("dumpMetrics", false, "") +var printExtraMetrics = flag.Bool("extraMetrics", false, "") +var printMultipleLabels = flag.Bool("multipleLabels", false, "") +var endpointFlag = flag.String("endpoint", "", "") + +const highResolutionEndpoint = "metrics?collect%5B%5D=custom_query.hr&collect%5B%5D=exporter&collect%5B%5D=standard.go&collect%5B%5D=standard.process" +const medResolutionEndpoint = "metrics?collect%5B%5D=custom_query.mr" +const lowResolutionEndpoint = "metrics?collect%5B%5D=custom_query.lr" + +// that metric is disabled by default in new exporters, so will trigger test +// however we don't use it at all in our dashboards, so for now - safe to skip it +var skipMetricNames = []string{"go_memstats_gc_cpu_fraction", "go_info"} + +type Metric struct { + name string + labelsRawStr string + labelsWithValues []string +} + +type MetricsCollection struct { + RawMetricStr string + RawMetricStrArr []string + MetricNamesWithLabels []string + MetricsData []Metric + LabelsByMetric map[string][]string +} + +func TestMissingMetrics(t *testing.T) { + if !getBool(doRun) { + t.Skip("For manual runs only through make") + return + } + + endpoint := "metrics?collect[]=exporter&collect[]=postgres&collect[]=custom_query.mr" + newMetrics, err := getMetricsFrom(updatedExporterFileName, updatedExporterArgs, endpoint) + if err != nil { + t.Error(err) + return + } + + oldMetrics, err := getMetricsFrom(oldExporterFileName, oldExporterArgs, endpoint) + if err != nil { + t.Error(err) + return + } + + err = os.WriteFile(updatedExporterMetrics, []byte(newMetrics), os.ModePerm) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(oldExporterMetrics, []byte(oldMetrics), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + oldMetricsCollection := parseMetricsCollection(oldMetrics) + newMetricsCollection := parseMetricsCollection(newMetrics) + + if ok, msg := testForMissingMetrics(oldMetricsCollection, newMetricsCollection); !ok { + t.Error(msg) + } +} + +func TestMissingLabels(t *testing.T) { + if !getBool(doRun) { + t.Skip("For manual runs only through make") + return + } + + newMetrics, err := getMetrics(updatedExporterFileName, updatedExporterArgs) + if err != nil { + t.Error(err) + return + } + + oldMetrics, err := getMetrics(oldExporterFileName, oldExporterArgs) + if err != nil { + t.Error(err) + return + } + + err = os.WriteFile(updatedExporterMetrics+"-labels", []byte(newMetrics), os.ModePerm) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(oldExporterMetrics+"-labels", []byte(oldMetrics), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + oldMetricsCollection := parseMetricsCollection(oldMetrics) + newMetricsCollection := parseMetricsCollection(newMetrics) + + if ok, msg := testForMissingMetricsLabels(oldMetricsCollection, newMetricsCollection); !ok { + t.Error(msg) + } +} + +func TestDumpMetrics(t *testing.T) { + if !getBool(doRun) { + t.Skip("For manual runs only through make") + return + } + + var ep string + switch *endpointFlag { + case "hr": + ep = highResolutionEndpoint + case "mr": + ep = medResolutionEndpoint + case "lr": + ep = lowResolutionEndpoint + default: + ep = "metrics" + } + + newMetrics, err := getMetricsFrom(updatedExporterFileName, updatedExporterArgs, ep) + if err != nil { + t.Error(err) + return + } + + oldMetrics, err := getMetricsFrom(oldExporterFileName, oldExporterArgs, ep) + if err != nil { + t.Error(err) + return + } + + oldMetricsCollection := parseMetricsCollection(oldMetrics) + newMetricsCollection := parseMetricsCollection(newMetrics) + + dumpMetricsInfo(oldMetricsCollection, newMetricsCollection) +} + +func TestResolutionsMetricDuplicates(t *testing.T) { + if !getBool(doRun) { + t.Skip("For manual runs only through make") + return + } + + hrMetrics, err := getMetricsFrom(updatedExporterFileName, updatedExporterArgs, highResolutionEndpoint) + if err != nil { + t.Error(err) + return + } + + mrMetrics, err := getMetricsFrom(updatedExporterFileName, updatedExporterArgs, medResolutionEndpoint) + if err != nil { + t.Error(err) + return + } + + lrMetrics, err := getMetricsFrom(updatedExporterFileName, updatedExporterArgs, lowResolutionEndpoint) + if err != nil { + t.Error(err) + return + } + + hrMetricsColl := parseMetricsCollection(hrMetrics) + mrMetricsColl := parseMetricsCollection(mrMetrics) + lrMetricsColl := parseMetricsCollection(lrMetrics) + + ms := make(map[string][]string) + addMetrics(ms, hrMetricsColl.MetricNamesWithLabels, "HR") + addMetrics(ms, mrMetricsColl.MetricNamesWithLabels, "MR") + addMetrics(ms, lrMetricsColl.MetricNamesWithLabels, "LR") + + count := 0 + msg := "" + for metric, resolutions := range ms { + if len(resolutions) > 1 { + count++ + msg += fmt.Sprintf("'%s' is duplicated in %s\n", metric, resolutions) + } + } + + if count > 0 { + t.Errorf("Found %d duplicated metrics:\n%s", count, msg) + } +} + +func addMetrics(ms map[string][]string, metrics []string, resolution string) { + for _, m := range metrics { + if m == "" || strings.HasPrefix(m, "# ") { + continue + } + + ms[m] = append(ms[m], resolution) + } +} + +func TestResolutions(t *testing.T) { + if !getBool(doRun) { + t.Skip("For manual runs only through make") + return + } + + t.Run("TestLowResolution", func(t *testing.T) { + testResolution(t, lowResolutionEndpoint, "Low") + }) + + t.Run("TestMediumResolution", func(t *testing.T) { + testResolution(t, medResolutionEndpoint, "Medium") + }) + + t.Run("TestHighResolution", func(t *testing.T) { + testResolution(t, highResolutionEndpoint, "High") + }) +} + +func testResolution(t *testing.T, resolutionEp, resolutionName string) { + newMetrics, err := getMetricsFrom(updatedExporterFileName, updatedExporterArgs, resolutionEp) + if err != nil { + t.Error(err) + return + } + + oldMetrics, err := getMetricsFrom(oldExporterFileName, oldExporterArgs, resolutionEp) + if err != nil { + t.Error(err) + return + } + + err = os.WriteFile(fmt.Sprintf("%s-%s", updatedExporterMetrics, resolutionName), []byte(newMetrics), os.ModePerm) + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(fmt.Sprintf("%s-%s", oldExporterMetrics, resolutionName), []byte(oldMetrics), os.ModePerm) + if err != nil { + t.Fatal(err) + } + + oldMetricsCollection := parseMetricsCollection(oldMetrics) + newMetricsCollection := parseMetricsCollection(newMetrics) + + missingCount := 0 + missingMetrics := "" + missingLabelsCount := 0 + missingLabels := "" + for _, oldMetric := range oldMetricsCollection.MetricsData { + // skip empty lines, comments and redundant metrics + if oldMetric.name == "" || strings.HasPrefix(oldMetric.name, "# ") { + continue + } + if skipMetric(oldMetric.name) { + continue + } + + metricFound := false + labelsMatch := false + for _, newMetric := range newMetricsCollection.MetricsData { + if newMetric.name != oldMetric.name { + continue + } + + metricFound = true + + if newMetric.labelsRawStr == oldMetric.labelsRawStr { + labelsMatch = true + break + } + + if arrIsSubsetOf(oldMetric.labelsWithValues, newMetric.labelsWithValues) { + labelsMatch = true + break + } + } + + if !metricFound { + missingCount++ + missingMetrics += fmt.Sprintf("%s\n", oldMetric) + } else if !labelsMatch { + missingLabelsCount++ + missingLabels += fmt.Sprintf("%s\n", oldMetric) + } + } + + if missingCount > 0 { + t.Errorf("%d metric(s) are missing in new exporter for %s resolution:\n%s", missingCount, resolutionName, missingMetrics) + } + + if missingLabelsCount > 0 { + t.Errorf("%d metrics's labels missing in new exporter for %s resolution:\n%s", missingLabelsCount, resolutionName, missingLabels) + } + + extraCount := 0 + extraMetrics := "" + for _, metric := range newMetricsCollection.MetricNamesWithLabels { + if metric == "" || strings.HasPrefix(metric, "# ") { + continue + } + + if !contains(oldMetricsCollection.MetricNamesWithLabels, metric) { + extraCount++ + extraMetrics += fmt.Sprintf("%s\n", metric) + } + } + if extraCount > 0 { + fmt.Printf("[WARN] %d metrics are redundant in new exporter for %s resolution\n%s", extraCount, resolutionName, extraMetrics) + } +} + +func skipMetric(oldMetricName string) bool { + skip := false + for _, name := range skipMetricNames { + if name == oldMetricName { + skip = true + } + } + return skip +} + +func dumpMetricsInfo(oldMetricsCollection, newMetricsCollection MetricsCollection) { + if getBool(dumpMetricsFlag) { + dumpMetrics(oldMetricsCollection, newMetricsCollection) + } + + if getBool(printExtraMetrics) { + dumpExtraMetrics(newMetricsCollection, oldMetricsCollection) + } + + if getBool(printMultipleLabels) { + dumpMetricsWithMultipleLabelSets(newMetricsCollection) + } +} + +func testForMissingMetricsLabels(oldMetricsCollection, newMetricsCollection MetricsCollection) (bool, string) { + missingMetricLabels := make(map[string]string) + missingMetricLabelsNames := make([]string, 0) + for metric, labels := range oldMetricsCollection.LabelsByMetric { + // skip version info label mismatch + if metric == "postgres_exporter_build_info" || metric == "go_info" { + continue + } + + if _, ok := newMetricsCollection.LabelsByMetric[metric]; ok { + newLabels := newMetricsCollection.LabelsByMetric[metric] + if !arrIsSubsetOf(labels, newLabels) { + missingMetricLabels[metric] = fmt.Sprintf(" expected: %s\n actual: %s", labels, newLabels) + missingMetricLabelsNames = append(missingMetricLabelsNames, metric) + } + } + } + sort.Strings(missingMetricLabelsNames) + + if len(missingMetricLabelsNames) > 0 { + ll := make([]string, 0) + for _, metric := range missingMetricLabelsNames { + labels := missingMetricLabels[metric] + ll = append(ll, metric+"\n"+labels) + } + + return false, fmt.Sprintf("Missing metric's labels (%d metrics):\n%s", len(missingMetricLabelsNames), strings.Join(ll, "\n")) + } + + return true, "" +} + +func testForMissingMetrics(oldMetricsCollection, newMetricsCollection MetricsCollection) (bool, string) { + missingMetrics := make([]string, 0) + for metricName := range oldMetricsCollection.LabelsByMetric { + if skipMetric(metricName) { + continue + } + + if _, ok := newMetricsCollection.LabelsByMetric[metricName]; !ok { + missingMetrics = append(missingMetrics, metricName) + } + } + sort.Strings(missingMetrics) + if len(missingMetrics) > 0 { + return false, fmt.Sprintf("Missing metrics (%d items):\n%s", len(missingMetrics), strings.Join(missingMetrics, "\n")) + } + + return true, "" +} + +func dumpMetricsWithMultipleLabelSets(newMetricsCollection MetricsCollection) { + metricsWithMultipleLabels := make(map[string][]string) + for metricName, newMetricLabels := range newMetricsCollection.LabelsByMetric { + if len(newMetricLabels) > 1 { + found := false + for i := 0; !found && i < len(newMetricLabels); i++ { + lbl := newMetricLabels[i] + + for j := 0; j < len(newMetricLabels); j++ { + if i == j { + continue + } + + lbl1 := newMetricLabels[j] + if lbl == "" || lbl1 == "" { + continue + } + + if strings.Contains(lbl, lbl1) || strings.Contains(lbl1, lbl) { + found = true + break + } + } + } + if found { + metricsWithMultipleLabels[metricName] = newMetricLabels + } + } + } + + if len(metricsWithMultipleLabels) > 0 { + ss := make([]string, 0, len(metricsWithMultipleLabels)) + for k, v := range metricsWithMultipleLabels { + ss = append(ss, fmt.Sprintf("%s\n %s", k, strings.Join(v, "\n "))) + } + fmt.Printf("Some metrics were collected multiple times with extra labels (%d items):\n %s\n\n", len(metricsWithMultipleLabels), strings.Join(ss, "\n ")) + } +} + +func dumpExtraMetrics(newMetricsCollection, oldMetricsCollection MetricsCollection) { + extraMetrics := make([]string, 0) + for metricName := range newMetricsCollection.LabelsByMetric { + if _, ok := oldMetricsCollection.LabelsByMetric[metricName]; !ok { + extraMetrics = append(extraMetrics, metricName) + } + } + sort.Strings(extraMetrics) + + if len(extraMetrics) > 0 { + fmt.Printf("Extra metrics (%d items):\n %s\n\n", len(extraMetrics), strings.Join(extraMetrics, "\n ")) + } +} + +func parseMetricsCollection(metricRaw string) MetricsCollection { + rawMetricsArr := strings.Split(metricRaw, "\n") + metricNamesArr := getMetricNames(rawMetricsArr) + metrics := parseMetrics(metricNamesArr) + labelsByMetrics := groupByMetrics(metrics) + + return MetricsCollection{ + MetricNamesWithLabels: metricNamesArr, + MetricsData: metrics, + RawMetricStr: metricRaw, + RawMetricStrArr: rawMetricsArr, + LabelsByMetric: labelsByMetrics, + } +} + +func arrIsSubsetOf(smaller, larger []string) bool { + if len(smaller) == 0 { + return len(larger) == 0 + } + + for _, x := range smaller { + if !contains(larger, x) { + return false + } + } + + return true +} + +func contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + + return false +} + +// groupByMetrics returns labels grouped by metric +func groupByMetrics(metrics []Metric) map[string][]string { + mtr := make(map[string][]string) + + for i := 0; i < len(metrics); i++ { + metric := metrics[i] + if _, ok := mtr[metric.name]; ok { + labels := mtr[metric.name] + labels = append(labels, metric.labelsRawStr) + mtr[metric.name] = labels + } else { + mtr[metric.name] = []string{metric.labelsRawStr} + } + } + + return mtr +} + +func parseMetrics(metrics []string) []Metric { + metricsLength := len(metrics) + metricsData := make([]Metric, 0, metricsLength) + for i := 0; i < metricsLength; i++ { + metricRawStr := metrics[i] + if metricRawStr == "" || strings.HasPrefix(metricRawStr, "# ") { + continue + } + + var mName, mLabels string + var labelsArr []string + if strings.Contains(metricRawStr, "{") { + mName = metricRawStr[:strings.Index(metricRawStr, "{")] + mLabels = metricRawStr[strings.Index(metricRawStr, "{")+1 : len(metricRawStr)-1] + if mLabels != "" { + labelsArr = strings.Split(mLabels, ",") + } + } else { + mName = metricRawStr + } + + metric := Metric{ + name: mName, + labelsRawStr: mLabels, + labelsWithValues: labelsArr, + } + + metricsData = append(metricsData, metric) + } + + return metricsData +} + +func dumpMetrics(oldMetrics, newMetrics MetricsCollection) { + f, _ := os.Create("assets/metrics.old.txt") + for _, s := range oldMetrics.RawMetricStrArr { + f.WriteString(s) + f.WriteString("\n") + } + f.Close() + + f, _ = os.Create("assets/metrics.new.txt") + for _, s := range newMetrics.RawMetricStrArr { + f.WriteString(s) + f.WriteString("\n") + } + f.Close() + + f, _ = os.Create("assets/metrics.names.old.txt") + for _, s := range oldMetrics.MetricNamesWithLabels { + f.WriteString(s) + f.WriteString("\n") + } + f.Close() + f, _ = os.Create("assets/metrics.names.new.txt") + for _, s := range newMetrics.MetricNamesWithLabels { + f.WriteString(s) + f.WriteString("\n") + } + f.Close() +} + +func getMetricNames(metrics []string) []string { + length := len(metrics) + ret := make([]string, length) + for i := 0; i < length; i++ { + str := metrics[i] + if str == "" || strings.HasPrefix(str, "# ") { + ret[i] = str + continue + } + + idx := strings.LastIndex(str, " ") + if idx >= 0 { + str1 := str[:idx] + ret[i] = str1 + } else { + ret[i] = str + } + } + + return ret +} + +func getMetrics(fileName, argsFile string) (string, error) { + return getMetricsFrom(fileName, argsFile, "metrics") +} + +func getMetricsFrom(fileName, argsFile, endpoint string) (string, error) { + cmd, port, collectOutput, err := launchExporter(fileName, argsFile) + if err != nil { + return "", errors.Wrap(err, "Failed to launch exporter") + } + + metrics, err := tryGetMetricsFrom(port, endpoint) + if err != nil { + return "", errors.Wrap(err, "Failed to get metrics") + } + + err = stopExporter(cmd, collectOutput) + if err != nil { + return "", errors.Wrap(err, "Failed to stop exporter") + } + + return metrics, nil +} diff --git a/percona_tests/performance_test.go b/percona_tests/performance_test.go new file mode 100644 index 000000000..ffc23b741 --- /dev/null +++ b/percona_tests/performance_test.go @@ -0,0 +1,219 @@ +package percona_tests + +import ( + "flag" + "fmt" + "os" + "strconv" + "strings" + "testing" + "time" + + "github.com/montanaflynn/stats" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/tklauser/go-sysconf" +) + +const ( + repeatCount = 5 + scrapesCount = 50 +) + +var doRun = flag.Bool("doRun", false, "") +var url = flag.String("url", "", "") + +type StatsData struct { + meanMs float64 + stdDevMs float64 + stdDevPerc float64 + + meanHwm float64 + stdDevHwmBytes float64 + stdDevHwmPerc float64 + + meanData float64 + stdDevDataBytes float64 + stdDevDataPerc float64 +} + +func TestPerformance(t *testing.T) { + // put postgres_exporter and postgres_exporter_percona files in 'percona' folder + // or use TestPrepareExporters to download exporters from feature build + if !getBool(doRun) { + t.Skip("For manual runs only through make") + return + } + + var updated, original *StatsData + t.Run("upstream exporter", func(t *testing.T) { + updated = doTestStats(t, repeatCount, scrapesCount, updatedExporterFileName, updatedExporterArgs) + }) + + t.Run("percona exporter", func(t *testing.T) { + original = doTestStats(t, repeatCount, scrapesCount, oldExporterFileName, oldExporterArgs) + }) + + printStats(original, updated) +} + +func calculatePerc(base, updated float64) float64 { + diff := base - updated + diffPerc := float64(100) / base * diff + diffPerc = diffPerc * -1 + + return diffPerc +} + +func doTestStats(t *testing.T, cnt, size int, fileName, argsFile string) *StatsData { + var durations []float64 + var hwms []float64 + var datas []float64 + + for i := 0; i < cnt; i++ { + d, hwm, data, err := doTest(size, fileName, argsFile) + if !assert.NoError(t, err) { + return nil + } + + durations = append(durations, float64(d)) + hwms = append(hwms, float64(hwm)) + datas = append(datas, float64(data)) + } + + mean, _ := stats.Mean(durations) + stdDev, _ := stats.StandardDeviation(durations) + stdDev = float64(100) / mean * stdDev + + clockTicks, err := sysconf.Sysconf(sysconf.SC_CLK_TCK) + if err != nil { + panic(err) + } + + mean = mean * float64(1000) / float64(clockTicks) / float64(size) + stdDevMs := stdDev / float64(100) * mean + + meanHwm, _ := stats.Mean(hwms) + stdDevHwm, _ := stats.StandardDeviation(hwms) + stdDevHwmPerc := float64(100) / meanHwm * stdDevHwm + + meanData, _ := stats.Mean(datas) + stdDevData, _ := stats.StandardDeviation(datas) + stdDevDataPerc := float64(100) / meanData * stdDevData + + st := StatsData{ + meanMs: mean, + stdDevMs: stdDevMs, + stdDevPerc: stdDev, + + meanHwm: meanHwm, + stdDevHwmBytes: stdDevHwm, + stdDevHwmPerc: stdDevHwmPerc, + + meanData: meanData, + stdDevDataBytes: stdDevData, + stdDevDataPerc: stdDevDataPerc, + } + + //fmt.Printf("loop %dx%d: sample time: %.2fms [deviation ±%.2fms, %.1f%%]\n", cnt, scrapesCount, st.meanMs, st.stdDevMs, st.stdDevPerc) + fmt.Printf("running %d scrapes %d times\n", size, cnt) + fmt.Printf("CPU\t%.1fms [±%.1fms, %.1f%%]\n", st.meanMs, st.stdDevMs, st.stdDevPerc) + fmt.Printf("HWM\t%.1fkB [±%.1f kB, %.1f%%]\n", st.meanHwm, st.stdDevHwmBytes, st.stdDevHwmPerc) + fmt.Printf("Data\t%.1fkB [±%.1f kB, %.1f%%]\n", st.meanData, st.stdDevDataBytes, st.stdDevDataPerc) + + return &st +} + +func doTest(iterations int, fileName, argsFile string) (cpu, hwm, data int64, _ error) { + cmd, port, collectOutput, err := launchExporter(fileName, argsFile) + if err != nil { + return 0, 0, 0, err + } + + total1 := getCPUTime(cmd.Process.Pid) + + for i := 0; i < iterations; i++ { + _, err = tryGetMetrics(port) + if err != nil { + return 0, 0, 0, errors.Wrapf(err, "Failed to perform test iteration %d.%s", i, collectOutput()) + } + + time.Sleep(1 * time.Millisecond) + } + + total2 := getCPUTime(cmd.Process.Pid) + + hwm, data = getCPUMem(cmd.Process.Pid) + + err = stopExporter(cmd, collectOutput) + if err != nil { + return 0, 0, 0, err + } + + return total2 - total1, hwm, data, nil +} + +func getCPUMem(pid int) (hwm, data int64) { + contents, err := os.ReadFile(fmt.Sprintf("/proc/%d/status", pid)) + if err != nil { + return 0, 0 + } + + lines := strings.Split(string(contents), "\n") + + for _, v := range lines { + if strings.HasPrefix(v, "VmHWM") { + val := strings.ReplaceAll(strings.ReplaceAll(strings.Split(v, ":\t")[1], " kB", ""), " ", "") + hwm, _ = strconv.ParseInt(val, 10, 64) + continue + } + if strings.HasPrefix(v, "VmData") { + val := strings.ReplaceAll(strings.ReplaceAll(strings.Split(v, ":\t")[1], " kB", ""), " ", "") + data, _ = strconv.ParseInt(val, 10, 64) + continue + } + } + + return hwm, data +} + +func getCPUTime(pid int) (total int64) { + contents, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid)) + if err != nil { + return + } + lines := strings.Split(string(contents), "\n") + for _, line := range lines { + fields := strings.Fields(line) + numFields := len(fields) + if numFields > 3 { + i, err := strconv.ParseInt(fields[13], 10, 64) + if err != nil { + panic(err) + } + + totalTime := i + + i, err = strconv.ParseInt(fields[14], 10, 64) + if err != nil { + panic(err) + } + + totalTime += i + + total = totalTime + + return + } + } + return +} + +func printStats(original, updated *StatsData) { + fmt.Println() + fmt.Println(" \told\tnew\tdiff") + fmt.Printf("CPU, ms \t%.1f\t%.1f\t%+.0f%%\n", original.meanMs, updated.meanMs, calculatePerc(original.meanMs, updated.meanMs)) + fmt.Printf("HWM, kB \t%.1f\t%.1f\t%+.0f%%\n", original.meanHwm, updated.meanHwm, calculatePerc(original.meanHwm, updated.meanHwm)) + fmt.Printf("DATA, kB\t%.1f\t%.1f\t%+.0f%%\n", original.meanData, updated.meanData, calculatePerc(original.meanData, updated.meanData)) + fmt.Println() +} diff --git a/percona_tests/readme.md b/percona_tests/readme.md new file mode 100644 index 000000000..d9e536e14 --- /dev/null +++ b/percona_tests/readme.md @@ -0,0 +1,40 @@ +## integration tests for exporter update + +### Fast start: + +run + + make prepare-env-from-repo + +then run any of the ```make test-*``` + +### A bit of details: + +1. unpack original exporter + + + make prepare-base-exporter + +2.a. download updated exporter from specific feature build + + make prepare-exporter-from-fb url="" + +2.b. or use current repo as updated exporter + + make prepare-exporter-from-repo + +3. start test postgres_server + + + make start-postgres-db + +4. run basic performance comparison test + + + make test-performance + +5. run metrics list compatibility test + + + make test-metrics + diff --git a/percona_tests/utils_test.go b/percona_tests/utils_test.go new file mode 100644 index 000000000..360e4ea71 --- /dev/null +++ b/percona_tests/utils_test.go @@ -0,0 +1,208 @@ +package percona_tests + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net" + "net/http" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +const ( + postgresHost = "postgres" + postgresPort = 5432 + postgresUser = "postgres" + postgresPassword = "postgres" + + portRangeStart = 20000 // exporter web interface listening port + portRangeEnd = 20100 // exporter web interface listening port + + exporterWaitTimeoutMs = 3000 // time to wait for exporter process start + + updatedExporterFileName = "/usr/src/myapp/percona_tests/assets/postgres_exporter" + oldExporterFileName = "/usr/src/myapp/percona_tests/assets/postgres_exporter_percona" + updatedExporterArgs = "/usr/src/myapp/percona_tests/assets/test.new-flags.txt" + oldExporterArgs = "/usr/src/myapp/percona_tests/assets/test.old-flags.txt" + updatedExporterMetrics = "/usr/src/myapp/percona_tests/assets/metrics.new" + oldExporterMetrics = "/usr/src/myapp/percona_tests/assets/metrics.old" +) + +func getBool(val *bool) bool { + return val != nil && *val +} + +func launchExporter(fileName string, argsFile string) (cmd *exec.Cmd, port int, collectOutput func() string, _ error) { + lines, err := os.ReadFile(argsFile) + if err != nil { + return nil, 0, nil, errors.Wrapf(err, "Unable to read exporter args file") + } + + port = -1 + for i := portRangeStart; i < portRangeEnd; i++ { + if checkPort(i) { + port = i + break + } + } + + if port == -1 { + return nil, 0, nil, errors.Wrapf(err, "Failed to find free port in range [%d..%d]", portRangeStart, portRangeEnd) + } + + linesStr := string(lines) + linesStr += fmt.Sprintf("\n--web.listen-address=127.0.0.1:%d", port) + + absolutePath, _ := filepath.Abs("custom-queries") + linesStr += fmt.Sprintf("\n--collect.custom_query.hr.directory=%s/high-resolution", absolutePath) + linesStr += fmt.Sprintf("\n--collect.custom_query.mr.directory=%s/medium-resolution", absolutePath) + linesStr += fmt.Sprintf("\n--collect.custom_query.lr.directory=%s/low-resolution", absolutePath) + + linesArr := strings.Split(linesStr, "\n") + + dsn := fmt.Sprintf("DATA_SOURCE_NAME=postgresql://%s:%s@%s:%d/postgres?sslmode=disable", postgresUser, postgresPassword, postgresHost, postgresPort) + + cmd = exec.Command(fileName, linesArr...) + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, dsn) + + var outBuffer, errorBuffer bytes.Buffer + cmd.Stdout = &outBuffer + cmd.Stderr = &errorBuffer + + collectOutput = func() string { + result := "" + outStr := outBuffer.String() + if outStr == "" { + result = "Process stdOut was empty. " + } else { + result = fmt.Sprintf("Process stdOut:\n%s\n", outStr) + } + errStr := errorBuffer.String() + if errStr == "" { + result += "Process stdErr was empty." + } else { + result += fmt.Sprintf("Process stdErr:\n%s\n", errStr) + } + + return result + } + + err = cmd.Start() + if err != nil { + return nil, 0, nil, errors.Wrapf(err, "Failed to start exporter.%s", collectOutput()) + } + + err = waitForExporter(port) + if err != nil { + return nil, 0, nil, errors.Wrapf(err, "Failed to wait for exporter.%s", collectOutput()) + } + + return cmd, port, collectOutput, nil +} + +func stopExporter(cmd *exec.Cmd, collectOutput func() string) error { + err := cmd.Process.Signal(unix.SIGINT) + if err != nil { + return errors.Wrapf(err, "Failed to send SIGINT to exporter process.%s\n", collectOutput()) + } + + err = cmd.Wait() + if err != nil && err.Error() != "signal: interrupt" { + return errors.Wrapf(err, "Failed to wait for exporter process termination.%s\n", collectOutput()) + } + + fmt.Println(collectOutput()) + + return nil +} +func tryGetMetrics(port int) (string, error) { + return tryGetMetricsFrom(port, "metrics") +} + +func tryGetMetricsFrom(port int, endpoint string) (string, error) { + uri := fmt.Sprintf("http://127.0.0.1:%d/%s", port, endpoint) + client := new(http.Client) + + request, err := http.NewRequest("GET", uri, nil) + if err != nil { + return "", err + } + request.Header.Add("Accept-Encoding", "gzip") + + response, err := client.Do(request) + + if err != nil { + return "", fmt.Errorf("failed to get response from exporters web interface: %w", err) + } + + if response.StatusCode != http.StatusOK { + return "", fmt.Errorf("failed to get response from exporters web interface: %w", err) + } + + // Check that the server actually sent compressed data + var reader io.ReadCloser + enc := response.Header.Get("Content-Encoding") + switch enc { + case "gzip": + reader, err = gzip.NewReader(response.Body) + if err != nil { + return "", fmt.Errorf("failed to create gzip reader: %w", err) + } + defer reader.Close() + default: + reader = response.Body + } + + buf := new(strings.Builder) + _, err = io.Copy(buf, reader) + if err != nil { + return "", err + } + + rr := buf.String() + if rr == "" { + return "", fmt.Errorf("failed to read response") + } + + err = response.Body.Close() + if err != nil { + return "", fmt.Errorf("failed to close response: %w", err) + } + + return rr, nil +} + +func checkPort(port int) bool { + ln, err := net.Listen("tcp", ":"+fmt.Sprint(port)) + if err != nil { + return false + } + + _ = ln.Close() + return true +} + +func waitForExporter(port int) error { + watchdog := exporterWaitTimeoutMs + + _, e := tryGetMetrics(port) + for ; e != nil && watchdog > 0; watchdog-- { + time.Sleep(1 * time.Millisecond) + _, e = tryGetMetrics(port) + } + + if watchdog == 0 { + return fmt.Errorf("failed to wait for exporter (on port %d)", port) + } + + return nil +} diff --git a/queries-lr.yaml b/queries-lr.yaml new file mode 100644 index 000000000..64ffdf824 --- /dev/null +++ b/queries-lr.yaml @@ -0,0 +1,131 @@ +pg_stat_user_tables: + query: | + SELECT + current_database() datname, + schemaname, + relname, + seq_scan, + seq_tup_read, + idx_scan, + idx_tup_fetch, + n_tup_ins, + n_tup_upd, + n_tup_del, + n_tup_hot_upd, + n_live_tup, + n_dead_tup, + n_mod_since_analyze, + COALESCE(last_vacuum, '1970-01-01Z') as last_vacuum, + COALESCE(last_autovacuum, '1970-01-01Z') as last_autovacuum, + COALESCE(last_analyze, '1970-01-01Z') as last_analyze, + COALESCE(last_autoanalyze, '1970-01-01Z') as last_autoanalyze, + vacuum_count, + autovacuum_count, + analyze_count, + autoanalyze_count + FROM + pg_stat_user_tables + metrics: + - datname: + usage: "LABEL" + description: "Name of current database" + - schemaname: + usage: "LABEL" + description: "Name of the schema that this table is in" + - relname: + usage: "LABEL" + description: "Name of this table" + - seq_scan: + usage: "COUNTER" + description: "Number of sequential scans initiated on this table" + - seq_tup_read: + usage: "COUNTER" + description: "Number of live rows fetched by sequential scans" + - idx_scan: + usage: "COUNTER" + description: "Number of index scans initiated on this table" + - idx_tup_fetch: + usage: "COUNTER" + description: "Number of live rows fetched by index scans" + - n_tup_ins: + usage: "COUNTER" + description: "Number of rows inserted" + - n_tup_upd: + usage: "COUNTER" + description: "Number of rows updated" + - n_tup_del: + usage: "COUNTER" + description: "Number of rows deleted" + - n_tup_hot_upd: + usage: "COUNTER" + description: "Number of rows HOT updated (i.e., with no separate index update required)" + - n_live_tup: + usage: "GAUGE" + description: "Estimated number of live rows" + - n_dead_tup: + usage: "GAUGE" + description: "Estimated number of dead rows" + - n_mod_since_analyze: + usage: "GAUGE" + description: "Estimated number of rows changed since last analyze" + - last_vacuum: + usage: "GAUGE" + description: "Last time at which this table was manually vacuumed (not counting VACUUM FULL)" + - last_autovacuum: + usage: "GAUGE" + description: "Last time at which this table was vacuumed by the autovacuum daemon" + - last_analyze: + usage: "GAUGE" + description: "Last time at which this table was manually analyzed" + - last_autoanalyze: + usage: "GAUGE" + description: "Last time at which this table was analyzed by the autovacuum daemon" + - vacuum_count: + usage: "COUNTER" + description: "Number of times this table has been manually vacuumed (not counting VACUUM FULL)" + - autovacuum_count: + usage: "COUNTER" + description: "Number of times this table has been vacuumed by the autovacuum daemon" + - analyze_count: + usage: "COUNTER" + description: "Number of times this table has been manually analyzed" + - autoanalyze_count: + usage: "COUNTER" + description: "Number of times this table has been analyzed by the autovacuum daemon" + +pg_statio_user_tables: + query: "SELECT current_database() datname, schemaname, relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit, toast_blks_read, toast_blks_hit, tidx_blks_read, tidx_blks_hit FROM pg_statio_user_tables" + metrics: + - datname: + usage: "LABEL" + description: "Name of current database" + - schemaname: + usage: "LABEL" + description: "Name of the schema that this table is in" + - relname: + usage: "LABEL" + description: "Name of this table" + - heap_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from this table" + - heap_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in this table" + - idx_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from all indexes on this table" + - idx_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in all indexes on this table" + - toast_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from this table's TOAST table (if any)" + - toast_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in this table's TOAST table (if any)" + - tidx_blks_read: + usage: "COUNTER" + description: "Number of disk blocks read from this table's TOAST table indexes (if any)" + - tidx_blks_hit: + usage: "COUNTER" + description: "Number of buffer hits in this table's TOAST table indexes (if any)" diff --git a/queries-mr.yaml b/queries-mr.yaml new file mode 100644 index 000000000..700e74b65 --- /dev/null +++ b/queries-mr.yaml @@ -0,0 +1,99 @@ +#### Queries are commented due to PMM-8859 +pg_replication: + query: "SELECT CASE WHEN NOT pg_is_in_recovery() THEN 0 ELSE GREATEST (0, EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))) END AS lag" + master: true + metrics: + - lag: + usage: "GAUGE" + description: "Replication lag behind master in seconds" + +pg_postmaster: + query: "SELECT pg_postmaster_start_time as start_time_seconds from pg_postmaster_start_time()" + master: true + metrics: + - start_time_seconds: + usage: "GAUGE" + description: "Time at which postmaster started" + +pg_database: + query: "SELECT pg_database.datname, pg_database_size(pg_database.datname) as size_bytes FROM pg_database" + master: true + cache_seconds: 30 + metrics: + - datname: + usage: "LABEL" + description: "Name of the database" + - size_bytes: + usage: "GAUGE" + description: "Disk space used by the database" +#### +#pg_stat_statements: +# query: "SELECT t2.rolname, t3.datname, queryid, calls, total_time / 1000 as total_time_seconds, min_time / 1000 as min_time_seconds, max_time / 1000 as max_time_seconds, mean_time / 1000 as mean_time_seconds, stddev_time / 1000 as stddev_time_seconds, rows, shared_blks_hit, shared_blks_read, shared_blks_dirtied, shared_blks_written, local_blks_hit, local_blks_read, local_blks_dirtied, local_blks_written, temp_blks_read, temp_blks_written, blk_read_time / 1000 as blk_read_time_seconds, blk_write_time / 1000 as blk_write_time_seconds FROM pg_stat_statements t1 JOIN pg_roles t2 ON (t1.userid=t2.oid) JOIN pg_database t3 ON (t1.dbid=t3.oid) WHERE t2.rolname != 'rdsadmin'" +# master: true +# metrics: +# - rolname: +# usage: "LABEL" +# description: "Name of user" +# - datname: +# usage: "LABEL" +# description: "Name of database" +# - queryid: +# usage: "LABEL" +# description: "Query ID" +# - calls: +# usage: "COUNTER" +# description: "Number of times executed" +# - total_time_seconds: +# usage: "COUNTER" +# description: "Total time spent in the statement, in milliseconds" +# - min_time_seconds: +# usage: "GAUGE" +# description: "Minimum time spent in the statement, in milliseconds" +# - max_time_seconds: +# usage: "GAUGE" +# description: "Maximum time spent in the statement, in milliseconds" +# - mean_time_seconds: +# usage: "GAUGE" +# description: "Mean time spent in the statement, in milliseconds" +# - stddev_time_seconds: +# usage: "GAUGE" +# description: "Population standard deviation of time spent in the statement, in milliseconds" +# - rows: +# usage: "COUNTER" +# description: "Total number of rows retrieved or affected by the statement" +# - shared_blks_hit: +# usage: "COUNTER" +# description: "Total number of shared block cache hits by the statement" +# - shared_blks_read: +# usage: "COUNTER" +# description: "Total number of shared blocks read by the statement" +# - shared_blks_dirtied: +# usage: "COUNTER" +# description: "Total number of shared blocks dirtied by the statement" +# - shared_blks_written: +# usage: "COUNTER" +# description: "Total number of shared blocks written by the statement" +# - local_blks_hit: +# usage: "COUNTER" +# description: "Total number of local block cache hits by the statement" +# - local_blks_read: +# usage: "COUNTER" +# description: "Total number of local blocks read by the statement" +# - local_blks_dirtied: +# usage: "COUNTER" +# description: "Total number of local blocks dirtied by the statement" +# - local_blks_written: +# usage: "COUNTER" +# description: "Total number of local blocks written by the statement" +# - temp_blks_read: +# usage: "COUNTER" +# description: "Total number of temp blocks read by the statement" +# - temp_blks_written: +# usage: "COUNTER" +# description: "Total number of temp blocks written by the statement" +# - blk_read_time_seconds: +# usage: "COUNTER" +# description: "Total time the statement spent reading blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)" +# - blk_write_time_seconds: +# usage: "COUNTER" +# description: "Total time the statement spent writing blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)" diff --git a/queries-postgres-uptime.yml b/queries-postgres-uptime.yml new file mode 100644 index 000000000..eccd86a55 --- /dev/null +++ b/queries-postgres-uptime.yml @@ -0,0 +1,7 @@ +pg_postmaster_uptime: + query: "select extract(epoch from current_timestamp - pg_postmaster_start_time()) as seconds" + master: true + metrics: + - seconds: + usage: "GAUGE" + description: "Service uptime" diff --git a/queries.yaml b/queries.yaml deleted file mode 100644 index 189ce0866..000000000 --- a/queries.yaml +++ /dev/null @@ -1,2 +0,0 @@ -# Adding queries to this file is deprecated -# Example queries have been transformed into collectors. \ No newline at end of file diff --git a/testdata/ssl/client/CA.crt b/testdata/ssl/client/CA.crt new file mode 100644 index 000000000..0781d3697 --- /dev/null +++ b/testdata/ssl/client/CA.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE2jCCAsKgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJDQTAe +Fw0yMTA5MjkxMzUzMjZaFw0yMzAzMjkxNDAzMjRaMA0xCzAJBgNVBAMTAkNBMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAy3AfoZtrIsDx+qzJAaNcbSv7 +s6+gVhw/RYbAT2nJ8w8uRxhjhhkY+0KI16m8TeuJvSS082RQbVTnw7g3viqmSz+P +rc5okrfpjDTT0ArM63SrYsKd53t3JUT0hX/mOGoetQD3pSQDsg/f/mNA0Ezosb6q +0iO3yIlLDzQ3igMMCBLsPYMYSfIv8+iKOiaWXmjH0sOszNNIvMKXi/u9E1LumjDl +R1zpi05YrWscj1yplBgBVYH5aBxy9V8jU3NR6jPWuAVmOUOjeCS7zSS3Oc31qNpW +t9/PosydAaOfkGVYYXytwHk0Xc7h25SSN6kS/KTxJb6oP9ASGoMXxUk9T0q6xtUZ +gvY8GDGQmUH8+xUazd64jQxEjq3RzIThASgAtG6I1VuH1lWxSRq73cWx4XtDmR4i +Acfv4y4s4LN564zcKjeLGTulJebXdDqnGyZWA6+LqkNMKKR5T9aHNFghSiol34pz +icCe6Z4pt/nkoRTlPv30+cwcqgZF27QP31ozaif/lzxq686T40mdxEneRA0Wpr2P +Zxpj1OdSZ7oqIX6/MFcHR4LLwv2VnLgZ4uBOPVeXBnQ/4LoOsBah09r0fyjvuhSJ +dTqP4+VDBXQG+6l7buU0a1Wl5mehRes6CHMFlq2f0fOvvkW/NoB4RkIOnFdP+g7E +RwefiIR+Y8PEYQPIjc8CAwEAAaNFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB +/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAVtr/8ICsWeABZqEp9Mzp1Mprk6MA0GCSqG +SIb3DQEBCwUAA4ICAQCdSOYDXmpNdZcX7Vmn05p0szxBM8/PrtL9xwSlsnCWomLj +KE8L1lP9G8qda80RFNp4lEXvF21Iflmc2Xf2wDkQj2//qk678labV2sZapje/JqJ +UCxGbFAVV3V3HGs5lvSgC0mhGZkavGijI5LYgJkQ6C5bxwGA0AUeCmi2DTnWVeYb +LHQyo+Nku/Ko6pVgJ3N7CbxJG6kd7A7i/rZzkXhpz5e8SSWLIDUIRtbytZ/tyU/Z +oUgzDf13pUrt6I40VTFeUQKtaUkmiBNpC3ZhkuO+alGSJeDfa/KSn/CnvkJ398nF +VUmi4ihLSwvC0vSO9VRmYBMwo+JEjLFT9+n5B1uUfzs27snJQ5q40zMKrfTfKYaw +K/sXsVdrIfEjyClM9C4PWhPbSycc4HtVpLPJKCP05l4G+aO7HwfqV+SYbZd3ii+E +yAcoH7UGQw92JCNK2JXhKE1vzZtuzcZNedd1cqYDo/vKCeBrPhR9qVVVOta9gFps +OEWzdLL2YSunMnoFvy34OumeSzzAL5MMughbHfO+fmUwI9vtdKINtRyE9A7j8X3p +H+Mm+avMEErcBbZ7u6LgI2aPfZfQbwoy8fv0VG5JN6bAKAh0n2QBGG99JC8OzI5q +q6Ash0DqwDNzWkM7IQkECeXQ5PASkah2alBg7mewlS8d6R6NzQ3ILzCB6qCRgA== +-----END CERTIFICATE----- diff --git a/testdata/ssl/client/server.crt b/testdata/ssl/client/server.crt new file mode 100644 index 000000000..814a44dcc --- /dev/null +++ b/testdata/ssl/client/server.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGTCCAgGgAwIBAgIQGIGv8QdtH0oxH27TNeil7TANBgkqhkiG9w0BAQsFADAN +MQswCQYDVQQDEwJDQTAeFw0yMTA5MjkxMzU2NTFaFw0yMzAzMjkxNDAzMjNaMBEx +DzANBgNVBAMTBnNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALrWoFyRmJvQnVoczotp39PJnwzMwfOM4o7611sSp/X/0jwa7SoW5nCFn5CCskgR +cCIbmlV16Mf/5WJXNhWHdzHpsS7t24fQIUFjHmsFpd1VQ/S/7vVUIOXLNwl0ZJpl +la3DGKqx9AAP26cyuI34wa09JnA3PF9BkaFDImE5VjujlIt/S4QJXbnBZOnwuO5D +qDJKeldX801GFf9Wvvn9SxGFoIlIPoTKZLhaT0RVHlc8Hoxwglxk/tIVVLChfqed +jSnqOnUmgLN5B7my+4CjXuup7+4MU5qIgvYcmZNwuI++lB5E6uUmX4BDJmquDM4Y +y4ldm0QspKDtHcSC20Pgow8CAwEAAaNxMG8wDgYDVR0PAQH/BAQDAgO4MB0GA1Ud +JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQU65mWMudTWDMs1JjR +aYtoeuu3RWUwHwYDVR0jBBgwFoAUBW2v/wgKxZ4AFmoSn0zOnUymuTowDQYJKoZI +hvcNAQELBQADggIBALlss5WJKauFOv0gomk8yR5o2xweMfNeftQj9NNhjhyy0fkM +I1C6a+pYry2f3gSqc+4haGmhCRVFSoRh8o2A9bsgyKeJ6DfRKeiopiZqBE8XRy+s +LolxWX8v7bOr81rhJgcsvfdgjSxq3ErBSWxB3MFVOq/4vyc96PeZ/74feVfvvgrD +RpE2IRDWygJUMpbtwF64+sE0vRJNwdCwhtA4DX+KQRLfhEhu67Pjc5LvH33kSdl8 +J/uj666dWSaqSpAd6qY3EOq9FfAPYRNauzV3M9NHH0BZZPSqZZp0ovJ2PaLHWk/z +fErEPMgc7qlCK9tJ2uDh3RdyshOULx1DFK7xNZ7tdrBSbZvGptS5CUAzAmBN2E06 +EnyaWftqsKmSOi9ydz6tngQTuovGi8RPZGdsT03rtrBJ/hDXiM79nlDDd0ofTjb4 +o6eRoS+qQZst87SOMWROi0J8ZilrPNz0aBoY4OWjNKZbyqgADlnatkwH+rPM+13f +sDDaNvFG4bFBAFXaaBFMMWet9GVeh9eNrBMF+80p5GmfIhqeXELAijHabuhqBcKD +tlZdSicjsb2h71xVgv8yCoH9zoOkW7SHWGIOXpvPUUiWJz869yBnUOf8cd69IoUT +BWGHKi74uExIdT82A69xYvWsqnRATHXcJoS0j+NNVOWxTI0XdhS7Sbl3xRe2 +-----END CERTIFICATE----- diff --git a/testdata/ssl/client/server.key b/testdata/ssl/client/server.key new file mode 100644 index 000000000..4dbf348f5 --- /dev/null +++ b/testdata/ssl/client/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAutagXJGYm9CdWhzOi2nf08mfDMzB84zijvrXWxKn9f/SPBrt +KhbmcIWfkIKySBFwIhuaVXXox//lYlc2FYd3MemxLu3bh9AhQWMeawWl3VVD9L/u +9VQg5cs3CXRkmmWVrcMYqrH0AA/bpzK4jfjBrT0mcDc8X0GRoUMiYTlWO6OUi39L +hAlducFk6fC47kOoMkp6V1fzTUYV/1a++f1LEYWgiUg+hMpkuFpPRFUeVzwejHCC +XGT+0hVUsKF+p52NKeo6dSaAs3kHubL7gKNe66nv7gxTmoiC9hyZk3C4j76UHkTq +5SZfgEMmaq4MzhjLiV2bRCykoO0dxILbQ+CjDwIDAQABAoIBAQCg479V1162Fo/Z +kGLgNLy00LNwv0XpJ5HVE/atC0Stlq0AayN9khjAHqEIPTOu0a1hAaoGG7Hnv9lU +tMrzASNITPfx9IuNyVFJ0EPaXxO0o/8P3NO2WMq3dyYesycKuZ2J8y3jl7gI8Z7x +vMCmKOcG+liGW1pWoMz6NCh/1nMGiN0OAwrY5MuO+K0lGxz2umI9fKTX3BSvd1SK +pvQQK7tRj6Dqntz5j/OTZknFyoV2QNdw5Ng1ImODdgJmazZASLX4B2vETkZoyFrW +gwfGL0Er88WgRvUbFmZMAaLnzDrW9XJssUF34cqITDzh/O9tLVjXj+PvanF6+gp9 +P1I0f6GBAoGBAMXfwcLFN+wwaOWlCQQBy/Ngtlp1uinT6kCxJ0e/IzcUQw9TNxY9 +heiiZBvkwKShA3emrkYNY2CxGuKGDjqJndMgthVmBNpYWw44cpYqQkIsKd+4wqyb +a1oemNbcEBTweqYepMasSRVYnqtM8+9bPeOn3JVC35rLSm3erf5pXDDPAoGBAPG4 ++yeI+s1tXYp1/8etUn3WCJ8cMnQlU2CyuSwWWZ2Ncpp0b6Xm2eEIWWbhp2mzN4q+ +F80ivnYBwyxPwXIuEiIoBn0pinyvqxHv+wgZfEFYWPVuSEWG9PsR4K0DYXrgkAJK +9s4Bste3JDXPp8qeBcSnOWY2N+savMuZV9RgUnnBAoGAfitapRKTwepsOGGvCfsL +TLhSDgQbHCifqXhMD5d0oN4ulEr/SRMZm2hQZOjLXS29xEFnxgsrXrAO8HmCARlW +pRSqhaJzXbYQ+VRM3Cs97Gu0l457swu2u9PeqMHRD0j3K41Gi9e3EgFbyuZadDi9 +kberExF8+nq9jqj6UMplmkkCgYA5DCoiE371eokoA19BVdNxJVFVk8cIiEKcQLHZ +CNFPkLFqaG5tHgVvyZOn5zumg4hpMyHU5Q1ENnhEffIuq1bWPtIBOguYD7F1A0kg +iTs9BMfB7Kwb1JT+qCJ5UqHv6Q2zrNOAnQADTxK5rG9yL0c3OSwfxk3+K4pBFsiW +s8DjQQKBgHXDhkTgAujyurvYURLRzlAFQJ4hc8Shqpl5xXKj9vh0KmxySZIYBlBf +VoFtZML/aPSwjPVNLDeIp9DCxGDxB5pEY2cBJucovlqTYSdI0qwnhoHEqHGTm2Vk +Fo6kyaAnbb8/N7VRES0wHKc5yzaTD0m6BBl2pLm5saQvpjslP6aw +-----END RSA PRIVATE KEY----- diff --git a/testdata/ssl/server/CA.crt b/testdata/ssl/server/CA.crt new file mode 100644 index 000000000..0781d3697 --- /dev/null +++ b/testdata/ssl/server/CA.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE2jCCAsKgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJDQTAe +Fw0yMTA5MjkxMzUzMjZaFw0yMzAzMjkxNDAzMjRaMA0xCzAJBgNVBAMTAkNBMIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAy3AfoZtrIsDx+qzJAaNcbSv7 +s6+gVhw/RYbAT2nJ8w8uRxhjhhkY+0KI16m8TeuJvSS082RQbVTnw7g3viqmSz+P +rc5okrfpjDTT0ArM63SrYsKd53t3JUT0hX/mOGoetQD3pSQDsg/f/mNA0Ezosb6q +0iO3yIlLDzQ3igMMCBLsPYMYSfIv8+iKOiaWXmjH0sOszNNIvMKXi/u9E1LumjDl +R1zpi05YrWscj1yplBgBVYH5aBxy9V8jU3NR6jPWuAVmOUOjeCS7zSS3Oc31qNpW +t9/PosydAaOfkGVYYXytwHk0Xc7h25SSN6kS/KTxJb6oP9ASGoMXxUk9T0q6xtUZ +gvY8GDGQmUH8+xUazd64jQxEjq3RzIThASgAtG6I1VuH1lWxSRq73cWx4XtDmR4i +Acfv4y4s4LN564zcKjeLGTulJebXdDqnGyZWA6+LqkNMKKR5T9aHNFghSiol34pz +icCe6Z4pt/nkoRTlPv30+cwcqgZF27QP31ozaif/lzxq686T40mdxEneRA0Wpr2P +Zxpj1OdSZ7oqIX6/MFcHR4LLwv2VnLgZ4uBOPVeXBnQ/4LoOsBah09r0fyjvuhSJ +dTqP4+VDBXQG+6l7buU0a1Wl5mehRes6CHMFlq2f0fOvvkW/NoB4RkIOnFdP+g7E +RwefiIR+Y8PEYQPIjc8CAwEAAaNFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB +/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAVtr/8ICsWeABZqEp9Mzp1Mprk6MA0GCSqG +SIb3DQEBCwUAA4ICAQCdSOYDXmpNdZcX7Vmn05p0szxBM8/PrtL9xwSlsnCWomLj +KE8L1lP9G8qda80RFNp4lEXvF21Iflmc2Xf2wDkQj2//qk678labV2sZapje/JqJ +UCxGbFAVV3V3HGs5lvSgC0mhGZkavGijI5LYgJkQ6C5bxwGA0AUeCmi2DTnWVeYb +LHQyo+Nku/Ko6pVgJ3N7CbxJG6kd7A7i/rZzkXhpz5e8SSWLIDUIRtbytZ/tyU/Z +oUgzDf13pUrt6I40VTFeUQKtaUkmiBNpC3ZhkuO+alGSJeDfa/KSn/CnvkJ398nF +VUmi4ihLSwvC0vSO9VRmYBMwo+JEjLFT9+n5B1uUfzs27snJQ5q40zMKrfTfKYaw +K/sXsVdrIfEjyClM9C4PWhPbSycc4HtVpLPJKCP05l4G+aO7HwfqV+SYbZd3ii+E +yAcoH7UGQw92JCNK2JXhKE1vzZtuzcZNedd1cqYDo/vKCeBrPhR9qVVVOta9gFps +OEWzdLL2YSunMnoFvy34OumeSzzAL5MMughbHfO+fmUwI9vtdKINtRyE9A7j8X3p +H+Mm+avMEErcBbZ7u6LgI2aPfZfQbwoy8fv0VG5JN6bAKAh0n2QBGG99JC8OzI5q +q6Ash0DqwDNzWkM7IQkECeXQ5PASkah2alBg7mewlS8d6R6NzQ3ILzCB6qCRgA== +-----END CERTIFICATE----- diff --git a/testdata/ssl/server/server.crt b/testdata/ssl/server/server.crt new file mode 100644 index 000000000..814a44dcc --- /dev/null +++ b/testdata/ssl/server/server.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEGTCCAgGgAwIBAgIQGIGv8QdtH0oxH27TNeil7TANBgkqhkiG9w0BAQsFADAN +MQswCQYDVQQDEwJDQTAeFw0yMTA5MjkxMzU2NTFaFw0yMzAzMjkxNDAzMjNaMBEx +DzANBgNVBAMTBnNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALrWoFyRmJvQnVoczotp39PJnwzMwfOM4o7611sSp/X/0jwa7SoW5nCFn5CCskgR +cCIbmlV16Mf/5WJXNhWHdzHpsS7t24fQIUFjHmsFpd1VQ/S/7vVUIOXLNwl0ZJpl +la3DGKqx9AAP26cyuI34wa09JnA3PF9BkaFDImE5VjujlIt/S4QJXbnBZOnwuO5D +qDJKeldX801GFf9Wvvn9SxGFoIlIPoTKZLhaT0RVHlc8Hoxwglxk/tIVVLChfqed +jSnqOnUmgLN5B7my+4CjXuup7+4MU5qIgvYcmZNwuI++lB5E6uUmX4BDJmquDM4Y +y4ldm0QspKDtHcSC20Pgow8CAwEAAaNxMG8wDgYDVR0PAQH/BAQDAgO4MB0GA1Ud +JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQU65mWMudTWDMs1JjR +aYtoeuu3RWUwHwYDVR0jBBgwFoAUBW2v/wgKxZ4AFmoSn0zOnUymuTowDQYJKoZI +hvcNAQELBQADggIBALlss5WJKauFOv0gomk8yR5o2xweMfNeftQj9NNhjhyy0fkM +I1C6a+pYry2f3gSqc+4haGmhCRVFSoRh8o2A9bsgyKeJ6DfRKeiopiZqBE8XRy+s +LolxWX8v7bOr81rhJgcsvfdgjSxq3ErBSWxB3MFVOq/4vyc96PeZ/74feVfvvgrD +RpE2IRDWygJUMpbtwF64+sE0vRJNwdCwhtA4DX+KQRLfhEhu67Pjc5LvH33kSdl8 +J/uj666dWSaqSpAd6qY3EOq9FfAPYRNauzV3M9NHH0BZZPSqZZp0ovJ2PaLHWk/z +fErEPMgc7qlCK9tJ2uDh3RdyshOULx1DFK7xNZ7tdrBSbZvGptS5CUAzAmBN2E06 +EnyaWftqsKmSOi9ydz6tngQTuovGi8RPZGdsT03rtrBJ/hDXiM79nlDDd0ofTjb4 +o6eRoS+qQZst87SOMWROi0J8ZilrPNz0aBoY4OWjNKZbyqgADlnatkwH+rPM+13f +sDDaNvFG4bFBAFXaaBFMMWet9GVeh9eNrBMF+80p5GmfIhqeXELAijHabuhqBcKD +tlZdSicjsb2h71xVgv8yCoH9zoOkW7SHWGIOXpvPUUiWJz869yBnUOf8cd69IoUT +BWGHKi74uExIdT82A69xYvWsqnRATHXcJoS0j+NNVOWxTI0XdhS7Sbl3xRe2 +-----END CERTIFICATE----- diff --git a/testdata/ssl/server/server.key b/testdata/ssl/server/server.key new file mode 100644 index 000000000..4dbf348f5 --- /dev/null +++ b/testdata/ssl/server/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAutagXJGYm9CdWhzOi2nf08mfDMzB84zijvrXWxKn9f/SPBrt +KhbmcIWfkIKySBFwIhuaVXXox//lYlc2FYd3MemxLu3bh9AhQWMeawWl3VVD9L/u +9VQg5cs3CXRkmmWVrcMYqrH0AA/bpzK4jfjBrT0mcDc8X0GRoUMiYTlWO6OUi39L +hAlducFk6fC47kOoMkp6V1fzTUYV/1a++f1LEYWgiUg+hMpkuFpPRFUeVzwejHCC +XGT+0hVUsKF+p52NKeo6dSaAs3kHubL7gKNe66nv7gxTmoiC9hyZk3C4j76UHkTq +5SZfgEMmaq4MzhjLiV2bRCykoO0dxILbQ+CjDwIDAQABAoIBAQCg479V1162Fo/Z +kGLgNLy00LNwv0XpJ5HVE/atC0Stlq0AayN9khjAHqEIPTOu0a1hAaoGG7Hnv9lU +tMrzASNITPfx9IuNyVFJ0EPaXxO0o/8P3NO2WMq3dyYesycKuZ2J8y3jl7gI8Z7x +vMCmKOcG+liGW1pWoMz6NCh/1nMGiN0OAwrY5MuO+K0lGxz2umI9fKTX3BSvd1SK +pvQQK7tRj6Dqntz5j/OTZknFyoV2QNdw5Ng1ImODdgJmazZASLX4B2vETkZoyFrW +gwfGL0Er88WgRvUbFmZMAaLnzDrW9XJssUF34cqITDzh/O9tLVjXj+PvanF6+gp9 +P1I0f6GBAoGBAMXfwcLFN+wwaOWlCQQBy/Ngtlp1uinT6kCxJ0e/IzcUQw9TNxY9 +heiiZBvkwKShA3emrkYNY2CxGuKGDjqJndMgthVmBNpYWw44cpYqQkIsKd+4wqyb +a1oemNbcEBTweqYepMasSRVYnqtM8+9bPeOn3JVC35rLSm3erf5pXDDPAoGBAPG4 ++yeI+s1tXYp1/8etUn3WCJ8cMnQlU2CyuSwWWZ2Ncpp0b6Xm2eEIWWbhp2mzN4q+ +F80ivnYBwyxPwXIuEiIoBn0pinyvqxHv+wgZfEFYWPVuSEWG9PsR4K0DYXrgkAJK +9s4Bste3JDXPp8qeBcSnOWY2N+savMuZV9RgUnnBAoGAfitapRKTwepsOGGvCfsL +TLhSDgQbHCifqXhMD5d0oN4ulEr/SRMZm2hQZOjLXS29xEFnxgsrXrAO8HmCARlW +pRSqhaJzXbYQ+VRM3Cs97Gu0l457swu2u9PeqMHRD0j3K41Gi9e3EgFbyuZadDi9 +kberExF8+nq9jqj6UMplmkkCgYA5DCoiE371eokoA19BVdNxJVFVk8cIiEKcQLHZ +CNFPkLFqaG5tHgVvyZOn5zumg4hpMyHU5Q1ENnhEffIuq1bWPtIBOguYD7F1A0kg +iTs9BMfB7Kwb1JT+qCJ5UqHv6Q2zrNOAnQADTxK5rG9yL0c3OSwfxk3+K4pBFsiW +s8DjQQKBgHXDhkTgAujyurvYURLRzlAFQJ4hc8Shqpl5xXKj9vh0KmxySZIYBlBf +VoFtZML/aPSwjPVNLDeIp9DCxGDxB5pEY2cBJucovlqTYSdI0qwnhoHEqHGTm2Vk +Fo6kyaAnbb8/N7VRES0wHKc5yzaTD0m6BBl2pLm5saQvpjslP6aw +-----END RSA PRIVATE KEY----- diff --git a/tools/go.mod b/tools/go.mod new file mode 100644 index 000000000..f5ad1b908 --- /dev/null +++ b/tools/go.mod @@ -0,0 +1,221 @@ +module github.com/percona/postgres_exporter/tools + +go 1.22.1 + +toolchain go1.23.2 + +require ( + github.com/golangci/golangci-lint v1.63.4 + github.com/prometheus/promu v0.17.0 + github.com/reviewdog/reviewdog v0.20.3 + honnef.co/go/tools v0.5.1 +) + +require ( + 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect + 4d63.com/gochecknoglobals v0.2.1 // indirect + code.gitea.io/sdk/gitea v0.19.0 // indirect + github.com/4meepo/tagalign v1.4.1 // indirect + github.com/Abirdcfly/dupword v0.1.3 // indirect + github.com/Antonboom/errname v1.0.0 // indirect + github.com/Antonboom/nilnil v1.0.1 // indirect + github.com/Antonboom/testifylint v1.5.2 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect + github.com/Crocmagnon/fatcontext v0.5.3 // indirect + github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect + github.com/alecthomas/go-check-sumtype v0.3.1 // indirect + github.com/alecthomas/kingpin/v2 v2.4.0 // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/alexkohler/nakedret/v2 v2.0.5 // indirect + github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alingse/asasalint v0.0.11 // indirect + github.com/alingse/nilnesserr v0.1.1 // indirect + github.com/ashanbrown/forbidigo v1.6.0 // indirect + github.com/ashanbrown/makezero v1.2.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bkielbasa/cyclop v1.2.3 // indirect + github.com/blizzy78/varnamelen v0.8.0 // indirect + github.com/bombsimon/wsl/v4 v4.5.0 // indirect + github.com/breml/bidichk v0.3.2 // indirect + github.com/breml/errchkjson v0.4.0 // indirect + github.com/butuzov/ireturn v0.3.1 // indirect + github.com/butuzov/mirror v1.3.0 // indirect + github.com/catenacyber/perfsprint v0.7.1 // indirect + github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/charithe/durationcheck v0.0.10 // indirect + github.com/chavacava/garif v0.1.0 // indirect + github.com/ckaznocha/intrange v0.3.0 // indirect + github.com/curioswitch/go-reassign v0.3.0 // indirect + github.com/daixiang0/gci v0.13.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidmz/go-pageant v1.0.2 // indirect + github.com/denis-tingaikin/go-header v0.5.0 // indirect + github.com/ettle/strcase v0.2.0 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fatih/structtag v1.2.0 // indirect + github.com/firefart/nonamedreturns v1.0.5 // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/fzipp/gocyclo v0.6.0 // indirect + github.com/ghostiam/protogetter v0.3.8 // indirect + github.com/go-critic/go-critic v0.11.5 // indirect + github.com/go-fed/httpsig v1.1.0 // indirect + github.com/go-toolsmith/astcast v1.1.0 // indirect + github.com/go-toolsmith/astcopy v1.1.0 // indirect + github.com/go-toolsmith/astequal v1.2.0 // indirect + github.com/go-toolsmith/astfmt v1.1.0 // indirect + github.com/go-toolsmith/astp v1.1.0 // indirect + github.com/go-toolsmith/strparse v1.1.0 // indirect + github.com/go-toolsmith/typep v1.1.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gofrs/flock v0.12.1 // indirect + github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect + github.com/golangci/go-printf-func-name v0.1.0 // indirect + github.com/golangci/gofmt v0.0.0-20241223200906-057b0627d9b9 // indirect + github.com/golangci/misspell v0.6.0 // indirect + github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/revgrep v0.5.3 // indirect + github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-github/v25 v25.1.3 // indirect + github.com/google/go-github/v64 v64.0.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/gordonklaus/ineffassign v0.1.0 // indirect + github.com/gostaticanalysis/analysisutil v0.7.1 // indirect + github.com/gostaticanalysis/comment v1.4.2 // indirect + github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect + github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/haya14busa/go-actions-toolkit v0.0.0-20200105081403-ca0307860f01 // indirect + github.com/haya14busa/go-sarif v0.0.0-20240630170108-a3ba8d79599f // indirect + github.com/hexops/gotextdiff v1.0.3 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jgautheron/goconst v1.7.1 // indirect + github.com/jingyugao/rowserrcheck v1.1.1 // indirect + github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/julz/importas v0.2.0 // indirect + github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect + github.com/kisielk/errcheck v1.8.0 // indirect + github.com/kkHAIKE/contextcheck v1.1.5 // indirect + github.com/kulti/thelper v0.6.3 // indirect + github.com/kunwardeep/paralleltest v1.0.10 // indirect + github.com/kyoh86/exportloopref v0.1.11 // indirect + github.com/lasiar/canonicalheader v1.1.2 // indirect + github.com/ldez/exptostd v0.3.1 // indirect + github.com/ldez/gomoddirectives v0.6.0 // indirect + github.com/ldez/grignotin v0.7.0 // indirect + github.com/ldez/tagliatelle v0.7.1 // indirect + github.com/ldez/usetesting v0.4.2 // indirect + github.com/leonklingele/grouper v1.1.2 // indirect + github.com/macabu/inamedparam v0.1.3 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/maratori/testableexamples v1.0.0 // indirect + github.com/maratori/testpackage v1.1.1 // indirect + github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mattn/go-shellwords v1.0.12 // indirect + github.com/mgechev/revive v1.5.1 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moricho/tparallel v0.3.2 // indirect + github.com/nakabonne/nestif v0.3.1 // indirect + github.com/nishanths/exhaustive v0.12.0 // indirect + github.com/nishanths/predeclared v0.2.2 // indirect + github.com/nunnatsa/ginkgolinter v0.18.4 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/polyfloyd/go-errorlint v1.7.0 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.52.3 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/quasilyte/gogrep v0.5.0 // indirect + github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect + github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect + github.com/raeperd/recvcheck v0.2.0 // indirect + github.com/reva2/bitbucket-insights-api v1.0.0 // indirect + github.com/reviewdog/errorformat v0.0.0-20240608101709-1d3280ed6bd4 // indirect + github.com/reviewdog/go-bitbucket v0.0.0-20201024094602-708c3f6a7de0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/ryancurrah/gomodguard v1.3.5 // indirect + github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect + github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/sashamelentyev/interfacebloat v1.1.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect + github.com/securego/gosec/v2 v2.21.4 // indirect + github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sivchari/containedctx v1.0.3 // indirect + github.com/sivchari/tenv v1.12.1 // indirect + github.com/sonatard/noctx v0.1.0 // indirect + github.com/sourcegraph/go-diff v0.7.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/cobra v1.8.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.12.0 // indirect + github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect + github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.10.0 // indirect + github.com/subosito/gotenv v1.4.1 // indirect + github.com/tdakkota/asciicheck v0.3.0 // indirect + github.com/tetafro/godot v1.4.20 // indirect + github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 // indirect + github.com/timonwong/loggercheck v0.10.1 // indirect + github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect + github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect + github.com/ultraware/funlen v0.2.0 // indirect + github.com/ultraware/whitespace v0.2.0 // indirect + github.com/uudashr/gocognit v1.2.0 // indirect + github.com/uudashr/iface v1.3.0 // indirect + github.com/xanzy/go-gitlab v0.114.0 // indirect + github.com/xen0n/gosmopolitan v1.2.2 // indirect + github.com/xhit/go-str2duration/v2 v2.1.0 // indirect + github.com/yagipy/maintidx v1.0.0 // indirect + github.com/yeya24/promlinter v0.3.0 // indirect + github.com/ykadowak/zerologlint v0.1.5 // indirect + gitlab.com/bosi/decorder v0.4.2 // indirect + go-simpler.org/musttag v0.13.0 // indirect + go-simpler.org/sloglint v0.7.2 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/build v0.0.0-20240906172953-ad8de1aafeaf // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect + golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.28.0 // indirect + google.golang.org/protobuf v1.35.2 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + mvdan.cc/gofumpt v0.7.0 // indirect + mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect +) diff --git a/tools/go.sum b/tools/go.sum new file mode 100644 index 000000000..5cea68146 --- /dev/null +++ b/tools/go.sum @@ -0,0 +1,964 @@ +4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= +4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= +4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= +4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= +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 v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +code.gitea.io/sdk/gitea v0.19.0 h1:8I6s1s4RHgzxiPHhOQdgim1RWIRcr0LVMbHBjBFXq4Y= +code.gitea.io/sdk/gitea v0.19.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/4meepo/tagalign v1.4.1 h1:GYTu2FaPGOGb/xJalcqHeD4il5BiCywyEYZOA55P6J4= +github.com/4meepo/tagalign v1.4.1/go.mod h1:2H9Yu6sZ67hmuraFgfZkNcg5Py9Ch/Om9l2K/2W1qS4= +github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= +github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= +github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= +github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= +github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs= +github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0= +github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= +github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Crocmagnon/fatcontext v0.5.3 h1:zCh/wjc9oyeF+Gmp+V60wetm8ph2tlsxocgg/J0hOps= +github.com/Crocmagnon/fatcontext v0.5.3/go.mod h1:XoCQYY1J+XTfyv74qLXvNw4xFunr3L1wkopIIKG7wGM= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= +github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= +github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= +github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= +github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= +github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= +github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= +github.com/alingse/nilnesserr v0.1.1 h1:7cYuJewpy9jFNMEA72Q1+3Nm3zKHzg+Q28D5f2bBFUA= +github.com/alingse/nilnesserr v0.1.1/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= +github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= +github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= +github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= +github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= +github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= +github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= +github.com/bombsimon/wsl/v4 v4.5.0 h1:iZRsEvDdyhd2La0FVi5k6tYehpOR/R7qIUjmKk7N74A= +github.com/bombsimon/wsl/v4 v4.5.0/go.mod h1:NOQ3aLF4nD7N5YPXMruR6ZXDOAqLoM0GEpLwTdvmOSc= +github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= +github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= +github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= +github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= +github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= +github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= +github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= +github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= +github.com/catenacyber/perfsprint v0.7.1 h1:PGW5G/Kxn+YrN04cRAZKC+ZuvlVwolYMrIyyTJ/rMmc= +github.com/catenacyber/perfsprint v0.7.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= +github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= +github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= +github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= +github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= +github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo= +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/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= +github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= +github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= +github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= +github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE= +github.com/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= +github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= +github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= +github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= +github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/ghostiam/protogetter v0.3.8 h1:LYcXbYvybUyTIxN2Mj9h6rHrDZBDwZloPoKctWrFyJY= +github.com/ghostiam/protogetter v0.3.8/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= +github.com/go-critic/go-critic v0.11.5 h1:TkDTOn5v7EEngMxu8KbuFqFR43USaaH8XRJLz1jhVYA= +github.com/go-critic/go-critic v0.11.5/go.mod h1:wu6U7ny9PiaHaZHcvMDmdysMqvDem162Rh3zWTrqk8M= +github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= +github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= +github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= +github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= +github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= +github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= +github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= +github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= +github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= +github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= +github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= +github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= +github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= +github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= +github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= +github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= +github.com/golangci/gofmt v0.0.0-20241223200906-057b0627d9b9 h1:t5wybL6RtO83VwoMOb7U/Peqe3gGKQlPIC66wXmnkvM= +github.com/golangci/gofmt v0.0.0-20241223200906-057b0627d9b9/go.mod h1:Ag3L7sh7E28qAp/5xnpMMTuGYqxLZoSaEHZDkZB1RgU= +github.com/golangci/golangci-lint v1.63.4 h1:bJQFQ3hSfUto597dkL7ipDzOxsGEpiWdLiZ359OWOBI= +github.com/golangci/golangci-lint v1.63.4/go.mod h1:Hx0B7Lg5/NXbaOHem8+KU+ZUIzMI6zNj/7tFwdnn10I= +github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= +github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= +github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= +github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/revgrep v0.5.3 h1:3tL7c1XBMtWHHqVpS5ChmiAAoe4PF/d5+ULzV9sLAzs= +github.com/golangci/revgrep v0.5.3/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= +github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/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-github/v25 v25.1.3 h1:Ht4YIQgUh4l4lc80fvGnw60khXysXvlgPxPP8uJG3EA= +github.com/google/go-github/v25 v25.1.3/go.mod h1:6z5pC69qHtrPJ0sXPsj4BLnd82b+r6sLB7qcBoRZqpw= +github.com/google/go-github/v64 v64.0.0 h1:4G61sozmY3eiPAjjoOHponXDBONm+utovTKbyUb2Qdg= +github.com/google/go-github/v64 v64.0.0/go.mod h1:xB3vqMQNdHzilXBiO2I+M7iEFtHf+DP/omBOv6tQzVo= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= +github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= +github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= +github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= +github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= +github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= +github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= +github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= +github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= +github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/haya14busa/go-actions-toolkit v0.0.0-20200105081403-ca0307860f01 h1:HiJF8Mek+I7PY0Bm+SuhkwaAZSZP83sw6rrTMrgZ0io= +github.com/haya14busa/go-actions-toolkit v0.0.0-20200105081403-ca0307860f01/go.mod h1:1DWDZmeYf0LX30zscWb7K9rUMeirNeBMd5Dum+seUhc= +github.com/haya14busa/go-checkstyle v0.0.0-20170303121022-5e9d09f51fa1/go.mod h1:RsN5RGgVYeXpcXNtWyztD5VIe7VNSEqpJvF2iEH7QvI= +github.com/haya14busa/go-sarif v0.0.0-20210102043135-e2c5fed2fa3d/go.mod h1:1Hkn3JseGMB/hv1ywzkapVQDWV3bFgp6POZobZmR/5g= +github.com/haya14busa/go-sarif v0.0.0-20240630170108-a3ba8d79599f h1:IrBUFBhHflcoA53Wp5TEK15bAgad0bgzY0FzW2CV5Oc= +github.com/haya14busa/go-sarif v0.0.0-20240630170108-a3ba8d79599f/go.mod h1:1Hkn3JseGMB/hv1ywzkapVQDWV3bFgp6POZobZmR/5g= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= +github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= +github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= +github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= +github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= +github.com/karamaru-alpha/copyloopvar v1.1.0 h1:x7gNyKcC2vRBO1H2Mks5u1VxQtYvFiym7fCjIP8RPos= +github.com/karamaru-alpha/copyloopvar v1.1.0/go.mod h1:u7CIfztblY0jZLOQZgH3oYsJzpC2A7S6u/lfgSXHy0k= +github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= +github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg= +github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= +github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= +github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= +github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= +github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= +github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= +github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= +github.com/ldez/exptostd v0.3.1 h1:90yWWoAKMFHeovTK8uzBms9Ppp8Du/xQ20DRO26Ymrw= +github.com/ldez/exptostd v0.3.1/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= +github.com/ldez/gomoddirectives v0.6.0 h1:Jyf1ZdTeiIB4dd+2n4qw+g4aI9IJ6JyfOZ8BityWvnA= +github.com/ldez/gomoddirectives v0.6.0/go.mod h1:TuwOGYoPAoENDWQpe8DMqEm5nIfjrxZXmxX/CExWyZ4= +github.com/ldez/grignotin v0.7.0 h1:vh0dI32WhHaq6LLPZ38g7WxXuZ1+RzyrJ7iPG9JMa8c= +github.com/ldez/grignotin v0.7.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= +github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= +github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= +github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= +github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= +github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= +github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= +github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= +github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= +github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= +github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mgechev/revive v1.5.1 h1:hE+QPeq0/wIzJwOphdVyUJ82njdd8Khp4fUIHGZHW3M= +github.com/mgechev/revive v1.5.1/go.mod h1:lC9AhkJIBs5zwx8wkudyHrU+IJkrEKmpCmGMnIJPk4o= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= +github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= +github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= +github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= +github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= +github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= +github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= +github.com/nunnatsa/ginkgolinter v0.18.4 h1:zmX4KUR+6fk/vhUFt8DOP6KwznekhkmVSzzVJve2vyM= +github.com/nunnatsa/ginkgolinter v0.18.4/go.mod h1:AMEane4QQ6JwFz5GgjI5xLUM9S/CylO+UyM97fN2iBI= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= +github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= +github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= +github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polyfloyd/go-errorlint v1.7.0 h1:Zp6lzCK4hpBDj8y8a237YK4EPrMXQWvOe3nGoH4pFrU= +github.com/polyfloyd/go-errorlint v1.7.0/go.mod h1:dGWKu85mGHnegQ2SWpEybFityCg3j7ZbwsVUxAOk9gY= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA= +github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/promu v0.17.0 h1:lrYuxTON9hImNM3lS0CgjJKqsV3WereHQoqrMMuyFmI= +github.com/prometheus/promu v0.17.0/go.mod h1:H4qXHbrvfowu3bY33DuI9fkO69nBbEF8tWu6arhhPoA= +github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= +github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= +github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= +github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/raeperd/recvcheck v0.2.0 h1:GnU+NsbiCqdC2XX5+vMZzP+jAJC5fht7rcVTAhX74UI= +github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU= +github.com/reva2/bitbucket-insights-api v1.0.0 h1:lpQ/Q7OmnG04w/EM77piOwZBxP41PeTlbytXxVrnplA= +github.com/reva2/bitbucket-insights-api v1.0.0/go.mod h1:pLs+ki3MKUntrPryxaGIvpRLiEtBhwfJ/uvxQIMfqHU= +github.com/reviewdog/errorformat v0.0.0-20240608101709-1d3280ed6bd4 h1:wFzV+/KigR9v01F8+cK/QyaMg6NgyfOOZaSquborhpY= +github.com/reviewdog/errorformat v0.0.0-20240608101709-1d3280ed6bd4/go.mod h1:AqhrP0G7F9YRROF10JQwdd4cNO8bdm6bY6KzcOc3Cp8= +github.com/reviewdog/go-bitbucket v0.0.0-20201024094602-708c3f6a7de0 h1:XZ60Bp2UqwaJ6fDQExoFVrgs4nIzwBCy9ct6GCj9hH8= +github.com/reviewdog/go-bitbucket v0.0.0-20201024094602-708c3f6a7de0/go.mod h1:5JbWAMFyq9hbISZawRyIe7QTcLaptvCIvmZnYo+1VvA= +github.com/reviewdog/reviewdog v0.20.3 h1:yl4+OD29caj6YWSwKNt0QxAG8RGMXC91XXkHogUgPvA= +github.com/reviewdog/reviewdog v0.20.3/go.mod h1:YAHHBArqeZv7Nf3YXwXvAlgSyjxTA4kkx3b6r1ubsq4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= +github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= +github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= +github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= +github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= +github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= +github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= +github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= +github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/securego/gosec/v2 v2.21.4 h1:Le8MSj0PDmOnHJgUATjD96PaXRvCpKC+DGJvwyy0Mlk= +github.com/securego/gosec/v2 v2.21.4/go.mod h1:Jtb/MwRQfRxCXyCm1rfM1BEiiiTfUOdyzzAhlr6lUTA= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= +github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= +github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= +github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= +github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= +github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= +github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= +github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= +github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= +github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/tdakkota/asciicheck v0.3.0 h1:LqDGgZdholxZMaJgpM6b0U9CFIjDCbFdUF00bDnBKOQ= +github.com/tdakkota/asciicheck v0.3.0/go.mod h1:KoJKXuX/Z/lt6XzLo8WMBfQGzak0SrAKZlvRr4tg8Ac= +github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= +github.com/tetafro/godot v1.4.20 h1:z/p8Ek55UdNvzt4TFn2zx2KscpW4rWqcnUrdmvWJj7E= +github.com/tetafro/godot v1.4.20/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 h1:y4mJRFlM6fUyPhoXuFg/Yu02fg/nIPFMOY8tOqppoFg= +github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= +github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= +github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= +github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= +github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= +github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= +github.com/ultraware/funlen v0.2.0/go.mod h1:ZE0q4TsJ8T1SQcjmkhN/w+MceuatI6pBFSxxyteHIJA= +github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSWoFa+g= +github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= +github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= +github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= +github.com/uudashr/iface v1.3.0 h1:zwPch0fs9tdh9BmL5kcgSpvnObV+yHjO4JjVBl8IA10= +github.com/uudashr/iface v1.3.0/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= +github.com/xanzy/go-gitlab v0.114.0 h1:0wQr/KBckwrZPfEMjRqpUz0HmsKKON9UhCYv9KDy19M= +github.com/xanzy/go-gitlab v0.114.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY= +github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= +github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= +github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= +github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= +github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4= +github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= +github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= +gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= +go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= +go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= +go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= +go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= +go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY= +go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/build v0.0.0-20240906172953-ad8de1aafeaf h1:BjXx92AIelK/HhKsuUVXaX7oajHWMgd05QxyEdWtDnQ= +golang.org/x/build v0.0.0-20240906172953-ad8de1aafeaf/go.mod h1:REK5Eq7a7rVIDfpJbDPLb7RaLtMm/HUpaYn1uvkJfow= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f h1:WTyX8eCCyfdqiPYkRGm0MqElSfYFH3yR1+rl/mct9sA= +golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +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= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +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.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.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= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +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.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= +honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= +mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= +mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= +mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= +mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 000000000..66ff267b3 --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,13 @@ +// postgres_exporter + +//go:build tools +// +build tools + +package tools + +import ( + _ "github.com/golangci/golangci-lint/cmd/golangci-lint" + _ "github.com/prometheus/promu" + _ "github.com/reviewdog/reviewdog/cmd/reviewdog" + _ "honnef.co/go/tools/cmd/staticcheck" +)