@@ -31,11 +31,16 @@ import (
3131 "time"
3232
3333 "github.com/blang/semver"
34+ "github.com/go-kit/kit/log"
35+ "github.com/go-kit/kit/log/level"
3436 "github.com/lib/pq"
3537 "github.com/prometheus/client_golang/prometheus"
3638 "github.com/prometheus/client_golang/prometheus/promhttp"
37- "github.com/prometheus/common/log"
39+ "github.com/prometheus/common/promlog"
40+ "github.com/prometheus/common/promlog/flag"
3841 "github.com/prometheus/common/version"
42+ "github.com/prometheus/exporter-toolkit/web"
43+ webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag"
3944 "gopkg.in/alecthomas/kingpin.v2"
4045 "gopkg.in/yaml.v2"
4146)
@@ -58,6 +63,7 @@ var VersionShort = "0.0.1"
5863
5964var (
6065 listenAddress = kingpin .Flag ("web.listen-address" , "Address to listen on for web interface and telemetry." ).Default (":9187" ).Envar ("PG_EXPORTER_WEB_LISTEN_ADDRESS" ).String ()
66+ webConfig = webflag .AddFlags (kingpin .CommandLine )
6167 metricPath = kingpin .Flag ("web.telemetry-path" , "Path under which to expose metrics." ).Default ("/metrics" ).Envar ("PG_EXPORTER_WEB_TELEMETRY_PATH" ).String ()
6268 disableDefaultMetrics = kingpin .Flag ("disable-default-metrics" , "Do not include default metrics." ).Default ("false" ).Envar ("PG_EXPORTER_DISABLE_DEFAULT_METRICS" ).Bool ()
6369 disableSettingsMetrics = kingpin .Flag ("disable-settings-metrics" , "Do not include pg_settings metrics." ).Default ("false" ).Envar ("PG_EXPORTER_DISABLE_SETTINGS_METRICS" ).Bool ()
6773 constantLabelsList = kingpin .Flag ("constantLabels" , "A list of label=value separated by comma(,)." ).Default ("" ).Envar ("PG_EXPORTER_CONSTANT_LABELS" ).String ()
6874 excludeDatabases = kingpin .Flag ("exclude-databases" , "A list of databases to remove when autoDiscoverDatabases is enabled" ).Default ("" ).Envar ("PG_EXPORTER_EXCLUDE_DATABASES" ).String ()
6975 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 ()
76+ logger = log .NewNopLogger ()
7077)
7178
7279// Metric name parts.
@@ -516,7 +523,7 @@ func makeQueryOverrideMap(pgVersion semver.Version, queryOverrides map[string][]
516523 }
517524 }
518525 if ! matched {
519- log . Warnln ( " No query matched override for" , name , "- disabling metric space." )
526+ level . Warn ( logger ). Log ( "msg" , " No query matched override, disabling metric space" , "name" , name )
520527 resultMap [name ] = ""
521528 }
522529 }
@@ -537,7 +544,7 @@ func parseUserQueries(content []byte) (map[string]intermediateMetricMap, map[str
537544 newQueryOverrides := make (map [string ]string )
538545
539546 for metric , specs := range userQueries {
540- log . Debugln ( " New user metric namespace from YAML: " , metric , "Will cache results for: " , specs .CacheSeconds )
547+ level . Debug ( logger ). Log ( "msg" , " New user metric namespace from YAML metric " , " metric" , metric , "cache_seconds " , specs .CacheSeconds )
541548 newQueryOverrides [metric ] = specs .Query
542549 metricMap , ok := metricMaps [metric ]
543550 if ! ok {
@@ -589,9 +596,9 @@ func addQueries(content []byte, pgVersion semver.Version, server *Server) error
589596 for k , v := range partialExporterMap {
590597 _ , found := server .metricMap [k ]
591598 if found {
592- log . Debugln ( "Overriding metric " , k , " from user YAML file." )
599+ level . Debug ( logger ). Log ( "msg " , "Overriding metric from user YAML file" , "metric" , k )
593600 } else {
594- log . Debugln ( " Adding new metric" , k , " from user YAML file." )
601+ level . Debug ( logger ). Log ( "msg" , " Adding new metric from user YAML file" , "metric" , k )
595602 }
596603 server .metricMap [k ] = v
597604 }
@@ -600,9 +607,9 @@ func addQueries(content []byte, pgVersion semver.Version, server *Server) error
600607 for k , v := range newQueryOverrides {
601608 _ , found := server .queryOverrides [k ]
602609 if found {
603- log . Debugln ( " Overriding query override" , k , " from user YAML file." )
610+ level . Debug ( logger ). Log ( "msg" , " Overriding query override from user YAML file" , "query_override" , k )
604611 } else {
605- log . Debugln ( " Adding new query override" , k , " from user YAML file." )
612+ level . Debug ( logger ). Log ( "msg" , " Adding new query override from user YAML file" , "query_override" , k )
606613 }
607614 server .queryOverrides [k ] = v
608615 }
@@ -633,7 +640,7 @@ func makeDescMap(pgVersion semver.Version, serverLabels prometheus.Labels, metri
633640 if ! columnMapping .supportedVersions (pgVersion ) {
634641 // It's very useful to be able to see what columns are being
635642 // rejected.
636- log . Debugln ( columnName , "is being forced to discard due to version incompatibility." )
643+ level . Debug ( logger ). Log ( "msg" , "Column is being forced to discard due to version incompatibility" , "column" , columnName )
637644 thisMap [columnName ] = MetricMap {
638645 discard : true ,
639646 conversion : func (_ interface {}) (float64 , bool ) {
@@ -720,7 +727,7 @@ func makeDescMap(pgVersion semver.Version, serverLabels prometheus.Labels, metri
720727 case string :
721728 durationString = t
722729 default :
723- log . Errorln ( "DURATION conversion metric was not a string" )
730+ level . Error ( logger ). Log ( "msg" , "Duration conversion metric was not a string" )
724731 return math .NaN (), false
725732 }
726733
@@ -730,7 +737,7 @@ func makeDescMap(pgVersion semver.Version, serverLabels prometheus.Labels, metri
730737
731738 d , err := time .ParseDuration (durationString )
732739 if err != nil {
733- log . Errorln ( " Failed converting result to metric: " , columnName , in , err )
740+ level . Error ( logger ). Log ( "msg" , " Failed converting result to metric" , "column" , columnName , "in" , in , "err" , err )
734741 return math .NaN (), false
735742 }
736743 return float64 (d / time .Millisecond ), true
@@ -793,14 +800,14 @@ func dbToFloat64(t interface{}) (float64, bool) {
793800 strV := string (v )
794801 result , err := strconv .ParseFloat (strV , 64 )
795802 if err != nil {
796- log . Infoln ( " Could not parse []byte: " , err )
803+ level . Info ( logger ). Log ( "msg" , " Could not parse []byte" , "err " , err )
797804 return math .NaN (), false
798805 }
799806 return result , true
800807 case string :
801808 result , err := strconv .ParseFloat (v , 64 )
802809 if err != nil {
803- log . Infoln ( " Could not parse string: " , err )
810+ level . Info ( logger ). Log ( "msg" , " Could not parse string" , "err " , err )
804811 return math .NaN (), false
805812 }
806813 return result , true
@@ -833,14 +840,14 @@ func dbToUint64(t interface{}) (uint64, bool) {
833840 strV := string (v )
834841 result , err := strconv .ParseUint (strV , 10 , 64 )
835842 if err != nil {
836- log . Infoln ( " Could not parse []byte: " , err )
843+ level . Info ( logger ). Log ( "msg" , " Could not parse []byte" , "err " , err )
837844 return 0 , false
838845 }
839846 return result , true
840847 case string :
841848 result , err := strconv .ParseUint (v , 10 , 64 )
842849 if err != nil {
843- log . Infoln ( " Could not parse string: " , err )
850+ level . Info ( logger ). Log ( "msg" , " Could not parse string" , "err " , err )
844851 return 0 , false
845852 }
846853 return result , true
@@ -980,7 +987,7 @@ func NewServer(dsn string, opts ...ServerOpt) (*Server, error) {
980987 db .SetMaxOpenConns (1 )
981988 db .SetMaxIdleConns (1 )
982989
983- log . Infof ( " Established new database connection to %q. " , fingerprint )
990+ level . Info ( logger ). Log ( "msg" , " Established new database connection" , "fingerprint " , fingerprint )
984991
985992 s := & Server {
986993 db : db ,
@@ -1007,7 +1014,7 @@ func (s *Server) Close() error {
10071014func (s * Server ) Ping () error {
10081015 if err := s .db .Ping (); err != nil {
10091016 if cerr := s .Close (); cerr != nil {
1010- log . Errorf ( " Error while closing non-pinging DB connection to %q: %v" , s , cerr )
1017+ level . Error ( logger ). Log ( "msg" , " Error while closing non-pinging DB connection" , "server" , s , "err" , cerr )
10111018 }
10121019 return err
10131020 }
@@ -1093,7 +1100,7 @@ func (s *Servers) Close() {
10931100 defer s .m .Unlock ()
10941101 for _ , server := range s .servers {
10951102 if err := server .Close (); err != nil {
1096- log . Errorf ( "failed to close connection to %q: %v" , server , err )
1103+ level . Error ( logger ). Log ( "msg" , "Failed to close connection" , "server" , server , "err" , err )
10971104 }
10981105 }
10991106}
@@ -1178,7 +1185,7 @@ func parseConstLabels(s string) prometheus.Labels {
11781185 for _ , p := range parts {
11791186 keyValue := strings .Split (strings .TrimSpace (p ), "=" )
11801187 if len (keyValue ) != 2 {
1181- log . Errorf ( `Wrong constant labels format %q , should be "key=value"` , p )
1188+ level . Error ( logger ). Log ( `Wrong constant labels format, should be "key=value"` , "input" , p )
11821189 continue
11831190 }
11841191 key := strings .TrimSpace (keyValue [0 ])
@@ -1457,10 +1464,10 @@ func queryNamespaceMappings(ch chan<- prometheus.Metric, server *Server) map[str
14571464 scrapeStart := time .Now ()
14581465
14591466 for namespace , mapping := range server .metricMap {
1460- log . Debugln ( " Querying namespace: " , namespace )
1467+ level . Debug ( logger ). Log ( "msg" , " Querying namespace" , "namespace " , namespace )
14611468
14621469 if mapping .master && ! server .master {
1463- log . Debugln ( "Query skipped..." )
1470+ level . Debug ( logger ). Log ( "msg" , "Query skipped..." )
14641471 continue
14651472 }
14661473
@@ -1469,7 +1476,7 @@ func queryNamespaceMappings(ch chan<- prometheus.Metric, server *Server) map[str
14691476 serVersion , _ := semver .Parse (server .lastMapVersion .String ())
14701477 runServerRange , _ := semver .ParseRange (server .runonserver )
14711478 if ! runServerRange (serVersion ) {
1472- log . Debugln ( " Query skipped for database version: " , server .lastMapVersion .String (), " as it should be run on database server version: " , server .runonserver )
1479+ level . Debug ( logger ). Log ( "msg" , " Query skipped for this database version" , "version" , server .lastMapVersion .String (), "target_version " , server .runonserver )
14731480 continue
14741481 }
14751482 }
@@ -1500,12 +1507,12 @@ func queryNamespaceMappings(ch chan<- prometheus.Metric, server *Server) map[str
15001507 // Serious error - a namespace disappeared
15011508 if err != nil {
15021509 namespaceErrors [namespace ] = err
1503- log . Infoln ( err )
1510+ level . Info ( logger ). Log ( "err" , err )
15041511 }
15051512 // Non-serious errors - likely version or parsing problems.
15061513 if len (nonFatalErrors ) > 0 {
15071514 for _ , err := range nonFatalErrors {
1508- log . Infoln ( err . Error () )
1515+ level . Info ( logger ). Log ( "err" , err )
15091516 }
15101517 }
15111518
@@ -1532,7 +1539,7 @@ func queryNamespaceMappings(ch chan<- prometheus.Metric, server *Server) map[str
15321539
15331540// Check and update the exporters query maps if the version has changed.
15341541func (e * Exporter ) checkMapVersions (ch chan <- prometheus.Metric , server * Server ) error {
1535- log . Debugf ( " Querying Postgres Version on %q " , server )
1542+ level . Debug ( logger ). Log ( "msg" , " Querying PostgreSQL version" , "server " , server )
15361543 versionRow := server .db .QueryRow ("SELECT version();" )
15371544 var versionString string
15381545 err := versionRow .Scan (& versionString )
@@ -1544,12 +1551,12 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, server *Server)
15441551 return fmt .Errorf ("Error parsing version string on %q: %v" , server , err )
15451552 }
15461553 if ! e .disableDefaultMetrics && semanticVersion .LT (lowestSupportedVersion ) {
1547- log . Warnf ( " PostgreSQL version is lower on %q then our lowest supported version! Got %s minimum supported is %s." , server , semanticVersion , lowestSupportedVersion )
1554+ level . Warn ( logger ). Log ( "msg" , " PostgreSQL version is lower than our lowest supported version" , "server" , server , "version" , semanticVersion , "lowest_supported_version" , lowestSupportedVersion )
15481555 }
15491556
15501557 // Check if semantic version changed and recalculate maps if needed.
15511558 if semanticVersion .NE (server .lastMapVersion ) || server .metricMap == nil {
1552- log . Infof ( " Semantic Version Changed on %q: %s -> %s" , server , server .lastMapVersion , semanticVersion )
1559+ level . Info ( logger ). Log ( "msg" , " Semantic version changed" , "server" , server , "from" , server .lastMapVersion , "to" , semanticVersion )
15531560 server .mappingMtx .Lock ()
15541561
15551562 // Get Default Metrics only for master database
@@ -1570,13 +1577,13 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, server *Server)
15701577 // Calculate the hashsum of the useQueries
15711578 userQueriesData , err := ioutil .ReadFile (e .userQueriesPath )
15721579 if err != nil {
1573- log . Errorln ( " Failed to reload user queries: " , e .userQueriesPath , err )
1580+ level . Error ( logger ). Log ( "msg" , " Failed to reload user queries" , "path" , e .userQueriesPath , "err" , err )
15741581 e .userQueriesError .WithLabelValues (e .userQueriesPath , "" ).Set (1 )
15751582 } else {
15761583 hashsumStr := fmt .Sprintf ("%x" , sha256 .Sum256 (userQueriesData ))
15771584
15781585 if err := addQueries (userQueriesData , semanticVersion , server ); err != nil {
1579- log . Errorln ( " Failed to reload user queries: " , e .userQueriesPath , err )
1586+ level . Error ( logger ). Log ( "msg" , " Failed to reload user queries" , "path" , e .userQueriesPath , "err" , err )
15801587 e .userQueriesError .WithLabelValues (e .userQueriesPath , hashsumStr ).Set (1 )
15811588 } else {
15821589 // Mark user queries as successfully loaded
@@ -1618,7 +1625,7 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
16181625 if err := e .scrapeDSN (ch , dsn ); err != nil {
16191626 errorsCount ++
16201627
1621- log . Errorf ( err . Error () )
1628+ level . Error (logger ). Log ( "err" , err )
16221629
16231630 if _ , ok := err .(* ErrorConnectToServer ); ok {
16241631 connectionErrorsCount ++
@@ -1656,19 +1663,19 @@ func (e *Exporter) discoverDatabaseDSNs() []string {
16561663 var err error
16571664 dsnURI , err = url .Parse (dsn )
16581665 if err != nil {
1659- log . Errorf ( " Unable to parse DSN as URI (%s): %v" , loggableDSN (dsn ), err )
1666+ level . Error ( logger ). Log ( "msg" , " Unable to parse DSN as URI" , "dsn" , loggableDSN (dsn ), "err" , err )
16601667 continue
16611668 }
16621669 } else if connstringRe .MatchString (dsn ) {
16631670 dsnConnstring = dsn
16641671 } else {
1665- log . Errorf ( " Unable to parse DSN as either URI or connstring (%s) " , loggableDSN (dsn ))
1672+ level . Error ( logger ). Log ( "msg" , " Unable to parse DSN as either URI or connstring" , "dsn " , loggableDSN (dsn ))
16661673 continue
16671674 }
16681675
16691676 server , err := e .servers .GetServer (dsn )
16701677 if err != nil {
1671- log . Errorf ( " Error opening connection to database (%s): %v" , loggableDSN (dsn ), err )
1678+ level . Error ( logger ). Log ( "msg" , " Error opening connection to database" , "dsn" , loggableDSN (dsn ), "err" , err )
16721679 continue
16731680 }
16741681 dsns [dsn ] = struct {}{}
@@ -1678,7 +1685,7 @@ func (e *Exporter) discoverDatabaseDSNs() []string {
16781685
16791686 databaseNames , err := queryDatabases (server )
16801687 if err != nil {
1681- log . Errorf ( " Error querying databases (%s): %v" , loggableDSN (dsn ), err )
1688+ level . Error ( logger ). Log ( "msg" , " Error querying databases" , "dsn" , loggableDSN (dsn ), "err" , err )
16821689 continue
16831690 }
16841691 for _ , databaseName := range databaseNames {
@@ -1722,7 +1729,7 @@ func (e *Exporter) scrapeDSN(ch chan<- prometheus.Metric, dsn string) error {
17221729
17231730 // Check if map versions need to be updated
17241731 if err := e .checkMapVersions (ch , server ); err != nil {
1725- log . Warnln ( " Proceeding with outdated query maps, as the Postgres version could not be determined: " , err )
1732+ level . Warn ( logger ). Log ( "msg" , " Proceeding with outdated query maps, as the Postgres version could not be determined" , "err " , err )
17261733 }
17271734
17281735 return server .Scrape (ch , e .disableSettingsMetrics )
@@ -1790,8 +1797,10 @@ func contains(a []string, x string) bool {
17901797
17911798func main () {
17921799 kingpin .Version (fmt .Sprintf ("postgres_exporter %s (built with %s)\n " , Version , runtime .Version ()))
1793- log .AddFlags (kingpin .CommandLine )
1800+ promlogConfig := & promlog.Config {}
1801+ flag .AddFlags (kingpin .CommandLine , promlogConfig )
17941802 kingpin .Parse ()
1803+ logger = promlog .New (promlogConfig )
17951804
17961805 // landingPage contains the HTML served at '/'.
17971806 // TODO: Make this nicer and more informative.
@@ -1811,11 +1820,13 @@ func main() {
18111820
18121821 dsn , err := getDataSources ()
18131822 if err != nil {
1814- log .Fatalf ("failed reading data sources: %s" , err .Error ())
1823+ level .Error (logger ).Log ("msg" , "Failed reading data sources" , "err" , err .Error ())
1824+ os .Exit (1 )
18151825 }
18161826
18171827 if len (dsn ) == 0 {
1818- log .Fatal ("couldn't find environment variables describing the datasource to use" )
1828+ level .Error (logger ).Log ("msg" , "Couldn't find environment variables describing the datasource to use" )
1829+ os .Exit (1 )
18191830 }
18201831
18211832 opts := []ExporterOpt {
@@ -1847,6 +1858,10 @@ func main() {
18471858 w .Write (landingPage ) // nolint: errcheck
18481859 })
18491860
1850- log .Infof ("Starting Server: %s" , * listenAddress )
1851- log .Fatal (http .ListenAndServe (* listenAddress , nil ))
1861+ level .Info (logger ).Log ("msg" , "Listening on address" , "address" , * listenAddress )
1862+ srv := & http.Server {Addr : * listenAddress }
1863+ if err := web .ListenAndServe (srv , * webConfig , logger ); err != nil {
1864+ level .Error (logger ).Log ("msg" , "Error running HTTP server" , "err" , err )
1865+ os .Exit (1 )
1866+ }
18521867}
0 commit comments