|
14 | 14 | package main |
15 | 15 |
|
16 | 16 | import ( |
| 17 | + "errors" |
17 | 18 | "fmt" |
| 19 | + "net" |
18 | 20 | "net/http" |
19 | 21 | "os" |
20 | 22 | "strings" |
|
46 | 48 | 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() |
47 | 49 | queriesPath = kingpin.Flag("extend.query-path", "Path to custom queries to run. (DEPRECATED)").Default("").Envar("PG_EXPORTER_EXTEND_QUERY_PATH").String() |
48 | 50 | onlyDumpMaps = kingpin.Flag("dumpmaps", "Do not run, simply dump the maps.").Bool() |
| 51 | + onlyHealthCheck = kingpin.Flag("healthcheck", "Do not run, just return if up and running.").Bool() |
49 | 52 | constantLabelsList = kingpin.Flag("constantLabels", "A list of label=value separated by comma(,). (DEPRECATED)").Default("").Envar("PG_EXPORTER_CONSTANT_LABELS").String() |
50 | 53 | excludeDatabases = kingpin.Flag("exclude-databases", "A list of databases to remove when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_EXCLUDE_DATABASES").String() |
51 | 54 | includeDatabases = kingpin.Flag("include-databases", "A list of databases to include when autoDiscoverDatabases is enabled (DEPRECATED)").Default("").Envar("PG_EXPORTER_INCLUDE_DATABASES").String() |
@@ -81,6 +84,18 @@ func main() { |
81 | 84 | return |
82 | 85 | } |
83 | 86 |
|
| 87 | + if *onlyHealthCheck { |
| 88 | + healthy, err := runHealthCheck(webConfig) |
| 89 | + if err != nil { |
| 90 | + level.Error(logger).Log("msg", "error running health check", "err", err) |
| 91 | + } |
| 92 | + if healthy { |
| 93 | + level.Info(logger).Log("msg", "health ok") |
| 94 | + os.Exit(0) |
| 95 | + } |
| 96 | + os.Exit(1) |
| 97 | + } |
| 98 | + |
84 | 99 | if err := c.ReloadConfig(*configFile, logger); err != nil { |
85 | 100 | // This is not fatal, but it means that auth must be provided for every dsn. |
86 | 101 | level.Warn(logger).Log("msg", "Error loading config", "err", err) |
@@ -122,29 +137,38 @@ func main() { |
122 | 137 | exporter.servers.Close() |
123 | 138 | }() |
124 | 139 |
|
125 | | - prometheus.MustRegister(version.NewCollector(exporterName)) |
| 140 | + reg := prometheus.NewRegistry() |
126 | 141 |
|
127 | | - prometheus.MustRegister(exporter) |
| 142 | + reg.MustRegister( |
| 143 | + version.NewCollector(exporterName), |
| 144 | + exporter, |
| 145 | + ) |
128 | 146 |
|
129 | 147 | // TODO(@sysadmind): Remove this with multi-target support. We are removing multiple DSN support |
130 | 148 | dsn := "" |
131 | 149 | if len(dsns) > 0 { |
132 | 150 | dsn = dsns[0] |
133 | 151 | } |
| 152 | + |
| 153 | + collOpts := []collector.Option{ |
| 154 | + collector.WithConstantLabels(parseConstLabels(*constantLabelsList)), |
| 155 | + } |
134 | 156 |
|
135 | | - pe, err := collector.NewPostgresCollector( |
| 157 | + pgColl, err := collector.NewPostgresCollector( |
136 | 158 | logger, |
137 | 159 | excludedDatabases, |
138 | 160 | dsn, |
139 | 161 | []string{}, |
| 162 | + collOpts... |
140 | 163 | ) |
141 | 164 | if err != nil { |
142 | 165 | level.Warn(logger).Log("msg", "Failed to create PostgresCollector", "err", err.Error()) |
143 | 166 | } else { |
144 | | - prometheus.MustRegister(pe) |
| 167 | + |
| 168 | + reg.MustRegister(pgColl) |
145 | 169 | } |
146 | 170 |
|
147 | | - http.Handle(*metricsPath, promhttp.Handler()) |
| 171 | + http.Handle(*metricsPath, promhttp.HandlerFor(reg, promhttp.HandlerOpts{})) |
148 | 172 |
|
149 | 173 | if *metricsPath != "/" && *metricsPath != "" { |
150 | 174 | landingConfig := web.LandingConfig{ |
@@ -174,3 +198,30 @@ func main() { |
174 | 198 | os.Exit(1) |
175 | 199 | } |
176 | 200 | } |
| 201 | + |
| 202 | +func runHealthCheck(webConfig *web.FlagConfig) (bool, error) { |
| 203 | + if len(*webConfig.WebListenAddresses) == 0 { |
| 204 | + return false, errors.New("no listen addresses to run the request to") |
| 205 | + } |
| 206 | + addr := (*webConfig.WebListenAddresses)[0] |
| 207 | + host, port, err := net.SplitHostPort(addr) |
| 208 | + if err != nil { |
| 209 | + return false, err |
| 210 | + } |
| 211 | + if host == "" { |
| 212 | + host = "localhost" |
| 213 | + } |
| 214 | + url := fmt.Sprintf("http://%s:%s/", host, port) |
| 215 | + req, err := http.NewRequest("GET", url, nil) |
| 216 | + if err != nil { |
| 217 | + return false, err |
| 218 | + } |
| 219 | + |
| 220 | + resp, err := http.DefaultClient.Do(req) |
| 221 | + if err != nil { |
| 222 | + return false, err |
| 223 | + } |
| 224 | + |
| 225 | + defer resp.Body.Close() |
| 226 | + return resp.StatusCode == 200, nil |
| 227 | +} |
0 commit comments