Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cmd/sql_exporter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ var (

func init() {
prometheus.MustRegister(version.NewCollector("sql_exporter"))
flag.BoolVar(&cfg.EnablePing, "config.enable-ping", true, "Enable ping for targets")
flag.StringVar(&cfg.DsnOverride, "config.data-source-name", "", "Data source name to override the value in the configuration file with")
flag.StringVar(&cfg.TargetLabel, "config.target-label", "target", "Target label name")
}

Expand All @@ -47,7 +49,6 @@ func main() {
runtime.SetBlockProfileRate(1)
runtime.SetMutexProfileFraction(1)
}

flag.Parse()

promlogConfig := &promlog.Config{}
Expand Down Expand Up @@ -135,7 +136,7 @@ func reloadCollectors(e sql_exporter.Exporter) func(http.ResponseWriter, *http.R
klog.Warning("Reloading target collectors...")
// FIXME: Should be t.Collectors() instead of config.Collectors
target, err := sql_exporter.NewTarget("", currentConfig.Target.Name, string(currentConfig.Target.DSN),
exporterNewConfig.Target.Collectors(), nil, currentConfig.Globals)
exporterNewConfig.Target.Collectors(), nil, currentConfig.Globals, currentConfig.Target.EnablePing)
if err != nil {
klog.Errorf("Error recreating a target - %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down
19 changes: 13 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ import (
"k8s.io/klog/v2"
)

var (
EnablePing bool
DsnOverride string
TargetLabel string
)

// MaxInt32 defines the maximum value of allowed integers
// and serves to help us avoid overflow/wraparound issues.
const MaxInt32 int = 1<<31 - 1

var TargetLabel string

// Load attempts to parse the given config file and return a Config object.
func Load(configFile string) (*Config, error) {
klog.Infof("Loading configuration from %s", configFile)
Expand Down Expand Up @@ -204,10 +208,11 @@ func (g *GlobalConfig) UnmarshalYAML(unmarshal func(any) error) error {

// TargetConfig defines a DSN and a set of collectors to be executed on it.
type TargetConfig struct {
Name string `yaml:"name,omitempty"` // name of the target
DSN Secret `yaml:"data_source_name"` // data source name to connect to
AwsSecretName string `yaml:"aws_secret_name"` // AWS secret name
CollectorRefs []string `yaml:"collectors"` // names of collectors to execute on the target
Name string `yaml:"name,omitempty"` // name of the target
DSN Secret `yaml:"data_source_name"` // data source name to connect to
AwsSecretName string `yaml:"aws_secret_name"` // AWS secret name
CollectorRefs []string `yaml:"collectors"` // names of collectors to execute on the target
EnablePing *bool `yaml:"enable_ping,omitempty"` // ping the target before executing the collectors

collectors []*CollectorConfig // resolved collector references

Expand Down Expand Up @@ -293,6 +298,8 @@ type JobConfig struct {

collectors []*CollectorConfig // resolved collector references

EnablePing *bool `yaml:"enable_ping,omitempty"` // ping the target before executing the collectors

// Catches all undefined fields and must be empty after parsing.
XXX map[string]any `yaml:",inline" json:"-"`
}
Expand Down
17 changes: 9 additions & 8 deletions exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package sql_exporter
import (
"context"
"errors"
"flag"
"fmt"
"os"
"sync"
Expand All @@ -16,8 +15,6 @@ import (

const envDsnOverride = "SQLEXPORTER_TARGET_DSN"

var dsnOverride = flag.String("config.data-source-name", "", "Data source name to override the value in the configuration file with.")

// Exporter is a prometheus.Gatherer that gathers SQL metrics from targets and merges them with the default registry.
type Exporter interface {
prometheus.Gatherer
Expand All @@ -44,19 +41,23 @@ func NewExporter(configFile string) (Exporter, error) {
}

if val, ok := os.LookupEnv(envDsnOverride); ok {
*dsnOverride = val
config.DsnOverride = val
}
// Override the DSN if requested (and in single target mode).
if *dsnOverride != "" {
if config.DsnOverride != "" {
if len(c.Jobs) > 0 {
return nil, fmt.Errorf("the config.data-source-name flag (value %q) only applies in single target mode", *dsnOverride)
return nil, fmt.Errorf("the config.data-source-name flag (value %q) only applies in single target mode", config.DsnOverride)
}
c.Target.DSN = config.Secret(*dsnOverride)
c.Target.DSN = config.Secret(config.DsnOverride)
}

if c.Target.EnablePing == nil {
c.Target.EnablePing = &config.EnablePing
}

var targets []Target
if c.Target != nil {
target, err := NewTarget("", c.Target.Name, string(c.Target.DSN), c.Target.Collectors(), nil, c.Globals)
target, err := NewTarget("", c.Target.Name, string(c.Target.DSN), c.Target.Collectors(), nil, c.Globals, c.Target.EnablePing)
if err != nil {
return nil, err
}
Expand Down
6 changes: 5 additions & 1 deletion job.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func NewJob(jc *config.JobConfig, gc *config.GlobalConfig) (Job, errors.WithCont
logContext: fmt.Sprintf("job=%q", jc.Name),
}

if jc.EnablePing == nil {
jc.EnablePing = &config.EnablePing
}

for _, sc := range jc.StaticConfigs {
for tname, dsn := range sc.Targets {
constLabels := prometheus.Labels{
Expand All @@ -41,7 +45,7 @@ func NewJob(jc *config.JobConfig, gc *config.GlobalConfig) (Job, errors.WithCont
}
constLabels[name] = value
}
t, err := NewTarget(j.logContext, tname, string(dsn), jc.Collectors(), constLabels, gc)
t, err := NewTarget(j.logContext, tname, string(dsn), jc.Collectors(), constLabels, gc, jc.EnablePing)
if err != nil {
return nil, err
}
Expand Down
14 changes: 9 additions & 5 deletions target.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"database/sql/driver"
"flag"
"fmt"
"sort"
"sync"
Expand All @@ -17,8 +16,6 @@ import (
"google.golang.org/protobuf/proto"
)

var enablePing = flag.Bool("config.enable-ping", true, "Enable ping for targets")

const (
// Capacity for the channel to collect metrics.
capMetricChan = 1000
Expand Down Expand Up @@ -46,14 +43,15 @@ type target struct {
upDesc MetricDesc
scrapeDurationDesc MetricDesc
logContext string
enablePing *bool

conn *sql.DB
}

// NewTarget returns a new Target with the given target name, data source name, collectors and constant labels.
// An empty target name means the exporter is running in single target mode: no synthetic metrics will be exported.
func NewTarget(
logContext, tname, dsn string, ccs []*config.CollectorConfig, constLabels prometheus.Labels, gc *config.GlobalConfig) (
logContext, tname, dsn string, ccs []*config.CollectorConfig, constLabels prometheus.Labels, gc *config.GlobalConfig, ep *bool) (
Target, errors.WithContext,
) {

Expand Down Expand Up @@ -93,6 +91,7 @@ func NewTarget(
upDesc: upDesc,
scrapeDurationDesc: scrapeDurationDesc,
logContext: logContext,
enablePing: ep,
}
return &t, nil
}
Expand Down Expand Up @@ -154,7 +153,7 @@ func (t *target) ping(ctx context.Context) errors.WithContext {
// If we have a handle and the context is not closed, test whether the database is up.
// FIXME: we ping the database during each request even with cacheCollector. It leads
// to additional charges for paid database services.
if t.conn != nil && ctx.Err() == nil && *enablePing {
if t.conn != nil && ctx.Err() == nil && *t.enablePing {
var err error
// Ping up to max_connections + 1 times as long as the returned error is driver.ErrBadConn, to purge the connection
// pool of bad connections. This might happen if the previous scrape timed out and in-flight queries got canceled.
Expand All @@ -181,3 +180,8 @@ func boolToFloat64(value bool) float64 {
}
return 0.0
}

// OfBool returns bool address.
func OfBool(i bool) *bool {
return &i
}