Permalink
Browse files

Implement query references (#8)

This commit adds a global map of queries which can be reused
in each job to save duplication of possibly huge queries.

Fixes #7
  • Loading branch information...
dominikschulz committed Apr 10, 2017
1 parent 15609d1 commit 84413ffe69770ff17ac4a573f4c84e189ebb4f84
Showing with 32 additions and 12 deletions.
  1. +11 −9 config.go
  2. +10 −0 config.yml.dist
  3. +1 −1 exporter.go
  4. +10 −2 job.go
View
@@ -37,7 +37,8 @@ func Read(path string) (File, error) {
// File is a collection of jobs
type File struct {
Jobs []*Job `yaml:"jobs"`
Jobs []*Job `yaml:"jobs"`
Queries map[string]string `yaml:"queries"`
}
// Job is a collection of connections and queries
@@ -63,12 +64,13 @@ type connection struct {
// Query is an SQL query that is executed on a connection
type Query struct {
sync.Mutex
log log.Logger
desc *prometheus.Desc
metrics map[*connection][]prometheus.Metric
Name string `yaml:"name"` // the prometheus metric name
Help string `yaml:"help"` // the prometheus metric help text
Labels []string `yaml:"labels"` // expose these columns as labels per gauge
Values []string `yaml:"values"` // expose each of these as an gauge
Query string `yaml:"query"`
log log.Logger
desc *prometheus.Desc
metrics map[*connection][]prometheus.Metric
Name string `yaml:"name"` // the prometheus metric name
Help string `yaml:"help"` // the prometheus metric help text
Labels []string `yaml:"labels"` // expose these columns as labels per gauge
Values []string `yaml:"values"` // expose each of these as an gauge
Query string `yaml:"query"` // a literal query
QueryRef string `yaml:"query_ref"` // references an query in the query map
}
View
@@ -106,3 +106,13 @@ jobs:
, idx_blks_read::float
, idx_blks_hit::float
FROM pg_statio_user_tables;
queries:
pg_statio_user_tables: |
SELECT
schemaname::text
, relname::text
, heap_blks_read::float
, heap_blks_hit::float
, idx_blks_read::float
, idx_blks_hit::float
FROM pg_statio_user_tables;
View
@@ -34,7 +34,7 @@ func NewExporter(logger log.Logger, configFile string) (*Exporter, error) {
if job == nil {
continue
}
if err := job.Init(logger); err != nil {
if err := job.Init(logger, cfg.Queries); err != nil {
level.Warn(logger).Log("msg", "Skipping job. Failed to initialize", "err", err, "job", job.Name)
continue
}
View
12 job.go
@@ -24,14 +24,23 @@ var (
)
// Init will initialize the metric descriptors
func (j *Job) Init(logger log.Logger) error {
func (j *Job) Init(logger log.Logger, queries map[string]string) error {
j.log = log.With(logger, "job", j.Name)
// register each query as an metric
for _, q := range j.Queries {
if q == nil {
level.Warn(j.log).Log("msg", "Skipping invalid query")
continue
}
q.log = log.With(j.log, "query", q.Name)
if q.Query == "" && q.QueryRef != "" {
if qry, found := queries[q.QueryRef]; found {
q.Query = qry
}
}
if q.Query == "" {
level.Warn(q.log).Log("msg", "Skipping empty query")
}
if q.metrics == nil {
// we have no way of knowing how many metrics will be returned by the
// queries, so we just assume that each query returns at least one metric.
@@ -41,7 +50,6 @@ func (j *Job) Init(logger log.Logger) error {
// try to satisfy prometheus naming restrictions
name := MetricNameRE.ReplaceAllString("sql_"+q.Name, "")
help := q.Help
q.log = log.With(j.log, "query", q.Name)
// prepare a new metrics descriptor
//
// the tricky part here is that the *order* of labels has to match the

0 comments on commit 84413ff

Please sign in to comment.