@@ -19,6 +19,7 @@ import (
1919 "gopkg.in/alecthomas/kingpin.v2"
2020 "gopkg.in/yaml.v2"
2121
22+ "crypto/sha256"
2223 "github.com/blang/semver"
2324 _ "github.com/lib/pq"
2425 "github.com/prometheus/client_golang/prometheus"
@@ -371,15 +372,10 @@ func makeQueryOverrideMap(pgVersion semver.Version, queryOverrides map[string][]
371372// TODO: test code for all cu.
372373// TODO: use proper struct type system
373374// TODO: the YAML cu supports is "non-standard" - we should move away from it.
374- func addQueries (queriesPath string , pgVersion semver.Version , exporterMap map [string ]MetricMapNamespace , queryOverrideMap map [string ]string ) error {
375+ func addQueries (content [] byte , pgVersion semver.Version , exporterMap map [string ]MetricMapNamespace , queryOverrideMap map [string ]string ) error {
375376 var extra map [string ]interface {}
376377
377- content , err := ioutil .ReadFile (queriesPath )
378- if err != nil {
379- return err
380- }
381-
382- err = yaml .Unmarshal (content , & extra )
378+ err := yaml .Unmarshal (content , & extra )
383379 if err != nil {
384380 return err
385381 }
@@ -663,10 +659,11 @@ func dbToString(t interface{}) (string, bool) {
663659
664660// Exporter collects Postgres metrics. It implements prometheus.Collector.
665661type Exporter struct {
666- dsn string
667- userQueriesPath string
668- duration , error prometheus.Gauge
669- totalScrapes prometheus.Counter
662+ dsn string
663+ userQueriesPath string
664+ duration , error prometheus.Gauge
665+ userQueriesError * prometheus.GaugeVec
666+ totalScrapes prometheus.Counter
670667
671668 // dbDsn is the connection string used to establish the dbConnection
672669 dbDsn string
@@ -706,6 +703,12 @@ func NewExporter(dsn string, userQueriesPath string) *Exporter {
706703 Name : "last_scrape_error" ,
707704 Help : "Whether the last scrape of metrics from PostgreSQL resulted in an error (1 for error, 0 for success)." ,
708705 }),
706+ userQueriesError : prometheus .NewGaugeVec (prometheus.GaugeOpts {
707+ Namespace : namespace ,
708+ Subsystem : exporter ,
709+ Name : "user_queries_load_error" ,
710+ Help : "Whether the user queries file was loaded and parsed successfully (1 for error, 0 for success)." ,
711+ }, []string {"filename" , "hashsum" }),
709712 metricMap : nil ,
710713 queryOverrides : nil ,
711714 }
@@ -746,6 +749,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
746749 ch <- e .duration
747750 ch <- e .totalScrapes
748751 ch <- e .error
752+ e .userQueriesError .Collect (ch )
749753}
750754
751755func newDesc (subsystem , name , help string ) * prometheus.Desc {
@@ -906,8 +910,24 @@ func (e *Exporter) checkMapVersions(ch chan<- prometheus.Metric, db *sql.DB) err
906910 e .lastMapVersion = semanticVersion
907911
908912 if e .userQueriesPath != "" {
909- if err := addQueries (e .userQueriesPath , semanticVersion , e .metricMap , e .queryOverrides ); err != nil {
913+ // Clear the metric while a reload is happening
914+ e .userQueriesError .Reset ()
915+
916+ // Calculate the hashsum of the useQueries
917+ userQueriesData , err := ioutil .ReadFile (e .userQueriesPath )
918+ if err != nil {
910919 log .Errorln ("Failed to reload user queries:" , e .userQueriesPath , err )
920+ e .userQueriesError .WithLabelValues (e .userQueriesPath , "" ).Set (1 )
921+ } else {
922+ hashsumStr := fmt .Sprintf ("%x" , sha256 .Sum256 (userQueriesData ))
923+
924+ if err := addQueries (userQueriesData , semanticVersion , e .metricMap , e .queryOverrides ); err != nil {
925+ log .Errorln ("Failed to reload user queries:" , e .userQueriesPath , err )
926+ e .userQueriesError .WithLabelValues (e .userQueriesPath , hashsumStr ).Set (1 )
927+ } else {
928+ // Mark user queries as successfully loaded
929+ e .userQueriesError .WithLabelValues (e .userQueriesPath , hashsumStr ).Set (0 )
930+ }
911931 }
912932 }
913933
0 commit comments