You've already forked postgres_exporter
mirror of
https://github.com/prometheus-community/postgres_exporter.git
synced 2026-10-23 12:08:57 +03:00
main: adopt exporter-toolkit bootstrap (#1428)
This commit is contained in:
committed by
GitHub
parent
322d6e60ec
commit
02d6977a2f
@@ -32,8 +32,11 @@ the `-file` flags at a mounted secret.
|
||||
* [CHANGE] Wrap non-negative 64-bit counters at `2^53` to preserve single-unit precision by @gnanirahulnutakki in https://github.com/prometheus-community/postgres_exporter/pull/1351
|
||||
* [CHANGE] stat_replication: add `pid` label to disambiguate replication connections that otherwise share identical labels by @sysadmind in https://github.com/prometheus-community/postgres_exporter/pull/1353
|
||||
* [CHANGE] stat_activity_autovacuum: add `datname` and `schemaname` labels to disambiguate autovacuum workers that otherwise share a `relname` by @spicysharkco in https://github.com/prometheus-community/postgres_exporter/pull/1419
|
||||
* [CHANGE] Deprecate `PG_EXPORTER_WEB_TELEMETRY_PATH` for removal in v0.22.0; use `--web.telemetry-path` instead, by @ArthurSens in https://github.com/prometheus-community/postgres_exporter/pull/1428. Until removal, the environment variable continues to set the metrics path when the flag is unset and logs a startup warning. Other `PG_EXPORTER_*` variables retain their existing behavior.
|
||||
* [BUGFIX] Enforce concurrent scrape limits through `--web.max-requests` (default `40`), independently for the metrics and `/probe` endpoints, by @ArthurSens in https://github.com/prometheus-community/postgres_exporter/pull/1428. Previously, both endpoints allowed unlimited concurrent scrapes. After upgrading, requests exceeding the limit receive HTTP 503; multi-target deployments share one limit across all `/probe` targets. Set `--web.max-requests=0` to preserve the previous unlimited behavior.
|
||||
* [BUGFIX] Fix `long_running_transactions` to count only transactions older than a configurable threshold, by @ArthurSens in https://github.com/prometheus-community/postgres_exporter/pull/1379, based on the contribution by @moreinhardt in https://github.com/prometheus-community/postgres_exporter/pull/1210
|
||||
* [BUGFIX] Fix the `wal` collector failing on every scrape on Amazon Aurora PostgreSQL versions that don't support `pg_ls_waldir()` by @megative in https://github.com/prometheus-community/postgres_exporter/pull/1312
|
||||
* [FEATURE] Add `--web.disable-exporter-metrics` to exclude Go, process, and `postgres_exporter_build_info` metrics while retaining PostgreSQL scrape-status and configuration-reload metrics, by @ArthurSens in https://github.com/prometheus-community/postgres_exporter/pull/1428, based on @nicolastakashi's work in https://github.com/prometheus-community/postgres_exporter/pull/1368.
|
||||
* [FEATURE] Export `pg_settings.pending_restart` as `pg_settings_pending_restart{name}` from the `settings` collector by @MarcWort in https://github.com/prometheus-community/postgres_exporter/pull/1396
|
||||
* [FEATURE] Add `aurora_replica_status` collector for Amazon Aurora PostgreSQL by @megative in https://github.com/prometheus-community/postgres_exporter/pull/1311
|
||||
* [FEATURE] Add `aurora_global_db_status` collector for Amazon Aurora PostgreSQL by @megative in https://github.com/prometheus-community/postgres_exporter/pull/1410
|
||||
|
||||
10
README.md
10
README.md
@@ -218,6 +218,12 @@ This will build the docker image as `prometheuscommunity/postgres_exporter:${bra
|
||||
* `web.telemetry-path`
|
||||
Path under which to expose metrics. Default is `/metrics`.
|
||||
|
||||
* `web.max-requests`
|
||||
Maximum number of parallel scrape requests per endpoint (`/metrics` and `/probe` have independent limits). Excess requests receive HTTP 503. Use `0` to disable. Default is `40`.
|
||||
|
||||
* `web.disable-exporter-metrics`
|
||||
Exclude Go, process, and `postgres_exporter_build_info` metrics. PostgreSQL scrape-status and configuration-reload metrics remain available. Default is `false`.
|
||||
|
||||
* `disable-default-metrics`
|
||||
Use only metrics supplied from `queries.yaml` via `--extend.query-path`. Default is `false`.
|
||||
|
||||
@@ -313,8 +319,8 @@ warning at startup when one of them is set.
|
||||
and will avoid exhausting the pool of connections of the database.
|
||||
Value of `0` or less than `1ms` is considered invalid and will report an error.
|
||||
|
||||
* `PG_EXPORTER_WEB_TELEMETRY_PATH`
|
||||
Path under which to expose metrics. Default is `/metrics`.
|
||||
* `PG_EXPORTER_WEB_TELEMETRY_PATH` (DEPRECATED)
|
||||
Path under which to expose metrics when `--web.telemetry-path` is unset. Default is `/metrics`. This environment variable will be removed in postgres_exporter v0.22.0. Use `--web.telemetry-path` instead; an explicit flag takes precedence.
|
||||
|
||||
* `PG_EXPORTER_DISABLE_DEFAULT_METRICS`
|
||||
Use only metrics supplied from `queries.yaml`. Value can be `true` or `false`. Default is `false`.
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
@@ -34,16 +35,12 @@ import (
|
||||
versioncollector "github.com/prometheus/client_golang/prometheus/collectors/version"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/prometheus/common/promslog"
|
||||
"github.com/prometheus/common/promslog/flag"
|
||||
"github.com/prometheus/common/version"
|
||||
"github.com/prometheus/exporter-toolkit/bootstrap"
|
||||
"github.com/prometheus/exporter-toolkit/web"
|
||||
"github.com/prometheus/exporter-toolkit/web/kingpinflag"
|
||||
)
|
||||
|
||||
var (
|
||||
configFile = kingpin.Flag("config.file", "Postgres exporter configuration file.").Default("postgres_exporter.yml").String()
|
||||
webConfig = kingpinflag.AddFlags(kingpin.CommandLine, ":9187")
|
||||
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()
|
||||
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()
|
||||
autoDiscoverDatabasesMaxConcurrency = kingpin.Flag("auto-discover-databases.max-concurrency", "Maximum number of discovered databases to scrape concurrently in a single scrape.").Default(fmt.Sprintf("%d", config.DefaultAutoDiscoverDatabasesMaxConcurrency)).Int()
|
||||
@@ -73,6 +70,15 @@ var (
|
||||
// The name of the exporter.
|
||||
const exporterName = "postgres_exporter"
|
||||
|
||||
// webTelemetryPathEnvar is deprecated and will be removed in v0.22.0.
|
||||
// Use --web.telemetry-path instead.
|
||||
const webTelemetryPathEnvar = "PG_EXPORTER_WEB_TELEMETRY_PATH"
|
||||
|
||||
// Bootstrap parses flags and builds the handler before starting the listener.
|
||||
// Returning errDumpMaps from the handler factory stops startup before database
|
||||
// initialization, so main can dump the maps and exit successfully.
|
||||
var errDumpMaps = errors.New("dumpmaps requested")
|
||||
|
||||
type collectorFlagSet map[string]*bool
|
||||
|
||||
type pgStatStatementsFlags struct {
|
||||
@@ -131,23 +137,67 @@ func newPGStatStatementsFlags() pgStatStatementsFlags {
|
||||
}
|
||||
|
||||
func main() {
|
||||
kingpin.Version(version.Print(exporterName))
|
||||
promslogConfig := &promslog.Config{}
|
||||
flag.AddFlags(kingpin.CommandLine, promslogConfig)
|
||||
kingpin.HelpFlag.Short('h')
|
||||
kingpin.Parse()
|
||||
logger = promslog.New(promslogConfig)
|
||||
server := &exporterServer{}
|
||||
runner := bootstrap.New(bootstrap.Config{
|
||||
App: kingpin.CommandLine,
|
||||
Name: exporterName,
|
||||
Description: "Prometheus PostgreSQL server Exporter",
|
||||
DefaultAddress: ":9187",
|
||||
LandingConfig: web.LandingConfig{
|
||||
Name: "Postgres Exporter",
|
||||
},
|
||||
MetricsHandlerFactory: server.newMetricsHandler,
|
||||
})
|
||||
// This flag previously belonged to postgres_exporter and read this env var.
|
||||
// Bootstrap registers it without an env binding. Restore that binding until
|
||||
// v0.22.0, preserving explicit CLI flags' precedence.
|
||||
kingpin.CommandLine.GetFlag("web.telemetry-path").Envar(webTelemetryPathEnvar)
|
||||
|
||||
if *onlyDumpMaps {
|
||||
err := runner.Run()
|
||||
server.close()
|
||||
if errors.Is(err, errDumpMaps) {
|
||||
exporter.DumpMaps()
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
if runner.Logger != nil {
|
||||
runner.Logger.Error("Error running exporter", "err", err)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
type exporterServer struct {
|
||||
runtime *collector.Runtime
|
||||
stopReload func()
|
||||
}
|
||||
|
||||
func (s *exporterServer) close() {
|
||||
if s.stopReload != nil {
|
||||
s.stopReload()
|
||||
}
|
||||
if s.runtime != nil {
|
||||
if err := s.runtime.Close(); err != nil {
|
||||
logger.Error("Failed to close runtime", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// newMetricsHandler wires up the exporter and registers postgres_exporter's
|
||||
// endpoints once the toolkit has parsed flags.
|
||||
func (s *exporterServer) newMetricsHandler(b *bootstrap.Bootstrap) (http.Handler, error) {
|
||||
logger = b.Logger
|
||||
|
||||
if *onlyDumpMaps {
|
||||
return nil, errDumpMaps
|
||||
}
|
||||
|
||||
registry := prometheus.NewRegistry()
|
||||
authHandler, err := config.NewHandler(registry)
|
||||
if err != nil {
|
||||
logger.Error("Failed to create config handler", "err", err)
|
||||
os.Exit(1)
|
||||
return nil, fmt.Errorf("failed to create config handler: %w", err)
|
||||
}
|
||||
|
||||
if err := authHandler.ReloadAuthConfig(*configFile, logger); err != nil {
|
||||
@@ -157,6 +207,10 @@ func main() {
|
||||
|
||||
warnDeprecatedDataSourceEnvVars()
|
||||
|
||||
if os.Getenv(webTelemetryPathEnvar) != "" {
|
||||
logger.Warn(webTelemetryPathEnvar + " is DEPRECATED, use --web.telemetry-path instead")
|
||||
}
|
||||
|
||||
dsns, err := getDataSources(dataSourceOpts{
|
||||
URI: *datasourceURI,
|
||||
URIFile: *datasourceURIFile,
|
||||
@@ -164,14 +218,12 @@ func main() {
|
||||
PassFile: *datasourcePassFile,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("Failed reading data sources", "err", err.Error())
|
||||
os.Exit(1)
|
||||
return nil, fmt.Errorf("failed reading data sources: %w", err)
|
||||
}
|
||||
|
||||
cfg, err := buildConfig(dsns)
|
||||
if err != nil {
|
||||
logger.Error("Failed building config", "err", err)
|
||||
os.Exit(1)
|
||||
return nil, fmt.Errorf("failed building config: %w", err)
|
||||
}
|
||||
logger.Info("Excluded databases", "databases", fmt.Sprintf("%v", cfg.ExcludeDatabases))
|
||||
|
||||
@@ -189,65 +241,47 @@ func main() {
|
||||
|
||||
validatedConfig, err := cfg.Validate()
|
||||
if err != nil {
|
||||
logger.Error("Invalid config", "err", err)
|
||||
os.Exit(1)
|
||||
return nil, fmt.Errorf("invalid config: %w", err)
|
||||
}
|
||||
|
||||
pgRuntime, err := collector.NewRuntime(validatedConfig, logger)
|
||||
runtime, err := collector.NewRuntime(validatedConfig, logger)
|
||||
if err != nil {
|
||||
logger.Error("Failed to create runtime", "err", err)
|
||||
os.Exit(1)
|
||||
return nil, fmt.Errorf("failed to create runtime: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := pgRuntime.Close(); err != nil {
|
||||
logger.Error("Failed to close runtime", "err", err)
|
||||
}
|
||||
}()
|
||||
s.runtime = runtime
|
||||
|
||||
registry.MustRegister(
|
||||
prometheuscollectors.NewGoCollector(),
|
||||
prometheuscollectors.NewProcessCollector(prometheuscollectors.ProcessCollectorOpts{}),
|
||||
versioncollector.NewCollector(exporterName),
|
||||
)
|
||||
for _, collector := range pgRuntime.Collectors() {
|
||||
if !b.DisableExporterMetrics {
|
||||
registry.MustRegister(
|
||||
versioncollector.NewCollector(exporterName),
|
||||
prometheuscollectors.NewGoCollector(),
|
||||
prometheuscollectors.NewProcessCollector(prometheuscollectors.ProcessCollectorOpts{}),
|
||||
)
|
||||
}
|
||||
for _, collector := range runtime.Collectors() {
|
||||
registry.MustRegister(collector)
|
||||
}
|
||||
|
||||
http.Handle(*metricsPath, promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))
|
||||
b.Handle("/probe", b.MaxRequestsHandler(handleProbe(logger, authHandler, cfg)))
|
||||
b.Handle("/debug/", http.DefaultServeMux)
|
||||
|
||||
if *metricsPath != "/" && *metricsPath != "" {
|
||||
landingConfig := web.LandingConfig{
|
||||
Name: "Postgres Exporter",
|
||||
Description: "Prometheus PostgreSQL server Exporter",
|
||||
Version: version.Info(),
|
||||
Links: []web.LandingLinks{
|
||||
{
|
||||
Address: *metricsPath,
|
||||
Text: "Metrics",
|
||||
},
|
||||
},
|
||||
}
|
||||
landingPage, err := web.NewLandingPage(landingConfig)
|
||||
if err != nil {
|
||||
logger.Error("error creating landing page", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
http.Handle("/", landingPage)
|
||||
}
|
||||
metricsHandler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
|
||||
|
||||
http.HandleFunc("/probe", handleProbe(logger, authHandler, cfg))
|
||||
http.HandleFunc("/-/reload", handleReload(authHandler, *configFile))
|
||||
b.HandleFunc("/-/reload", handleReload(authHandler, *configFile))
|
||||
|
||||
reloadSignals := make(chan os.Signal, 1)
|
||||
reloadDone := make(chan struct{})
|
||||
signal.Notify(reloadSignals, syscall.SIGHUP)
|
||||
defer signal.Stop(reloadSignals)
|
||||
go handleReloadSignal(reloadSignals, authHandler, *configFile, logger)
|
||||
|
||||
srv := &http.Server{}
|
||||
if err := web.ListenAndServe(srv, webConfig, logger); err != nil {
|
||||
logger.Error("Error running HTTP server", "err", err)
|
||||
os.Exit(1)
|
||||
go func() {
|
||||
defer close(reloadDone)
|
||||
handleReloadSignal(reloadSignals, authHandler, *configFile, logger)
|
||||
}()
|
||||
s.stopReload = func() {
|
||||
signal.Stop(reloadSignals)
|
||||
close(reloadSignals)
|
||||
<-reloadDone
|
||||
}
|
||||
|
||||
return metricsHandler, nil
|
||||
}
|
||||
|
||||
func buildConfig(dsns []string) (config.Config, error) {
|
||||
|
||||
@@ -104,7 +104,6 @@ Flags specific to this exporter:
|
||||
|
||||
| Flag | Purpose |
|
||||
|---|---|
|
||||
| `--web.telemetry-path` | Metrics path. Default `/metrics`. |
|
||||
| `--config.file` | Path to the [config file](#config-file). Default `postgres_exporter.yml`. |
|
||||
| `--collection-timeout` | Per-scrape timeout. Default `1m`. See [Connecting](connecting.md#connection-timeout). |
|
||||
| `--wrap-large-counters` | Wrap 64-bit counters at 2^53 to avoid floating point rounding. Default `true`. |
|
||||
@@ -115,6 +114,9 @@ The exporter's HTTP server is provided by [exporter-toolkit](https://github.com/
|
||||
|
||||
| Flag | Purpose |
|
||||
|---|---|
|
||||
| `--web.telemetry-path` | Metrics path. Default `/metrics`. |
|
||||
| `--web.max-requests` | Maximum concurrent scrapes per endpoint, independently for the metrics path and `/probe`. Default `40`; excess requests receive HTTP 503. Set `0` for no limit. Reload and debug endpoints are not limited. |
|
||||
| `--web.disable-exporter-metrics` | Exclude Go, process, and `postgres_exporter_build_info` metrics. PostgreSQL scrape-status and config-reload metrics remain available. Default `false`. |
|
||||
| `--web.listen-address` | Address to serve on. Default `:9187`. Repeatable, to listen on several addresses (e.g. `--web.listen-address=:9187 --web.listen-address=[::1]:9187`). |
|
||||
| `--web.config.file` | Enables TLS and/or basic auth on the exporter's own HTTP server. File format: [web-configuration.md](https://github.com/prometheus/exporter-toolkit/blob/master/docs/web-configuration.md). See also [Secrets](secrets.md#exporter-http-endpoint). |
|
||||
| `--web.systemd-socket` | Use systemd socket activation instead of binding a port. Linux only — the flag doesn't exist on other platforms. |
|
||||
@@ -126,7 +128,7 @@ Logging flags come from the shared [`prometheus/common`](https://github.com/prom
|
||||
| `--log.level` | Logging verbosity: `debug`, `info` (default), `warn`, or `error`. |
|
||||
| `--log.format` | Log output format: `logfmt` (default) or `json`. |
|
||||
|
||||
Most flags also have an environment-variable equivalent (e.g. `PG_EXPORTER_WEB_TELEMETRY_PATH`, `PG_EXPORTER_COLLECTION_TIMEOUT`); a CLI flag, if set, always wins over the corresponding environment variable. The full list is in the [main README](../README.md#flags).
|
||||
`PG_EXPORTER_WEB_TELEMETRY_PATH` is deprecated; use `--web.telemetry-path` instead. It continues to work during deprecation and will be removed in postgres_exporter v0.22.0. Many flags also have an environment-variable equivalent (e.g. `PG_EXPORTER_COLLECTION_TIMEOUT`); a CLI flag, if set, always wins over the corresponding environment variable. The full list is in the [main README](../README.md#flags).
|
||||
|
||||
## Config file
|
||||
|
||||
|
||||
Reference in New Issue
Block a user