131 lines
4 KiB
Go
131 lines
4 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"os/user"
|
|
"path"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/kkyr/fig"
|
|
)
|
|
|
|
// Config is the service-mode configuration, loaded from YAML (via fig) and
|
|
// overridable by flags. It only governs the output exporters; drive discovery
|
|
// and SMART collection auto-detect their tools and need no configuration.
|
|
type Config struct {
|
|
// Hostname is used as the host tag/label on every metric. When empty it is
|
|
// resolved from the system hostname.
|
|
Hostname string `fig:"hostname"`
|
|
|
|
// Metric outputs.
|
|
HTTP HTTPOutputConfig `fig:"http_output"`
|
|
Influx InfluxOutputConfig `fig:"influx_output"`
|
|
}
|
|
|
|
// HTTPOutputConfig configures the Prometheus HTTP exporter.
|
|
type HTTPOutputConfig struct {
|
|
Enabled bool `fig:"enabled"`
|
|
BindAddr string `fig:"bind_addr"`
|
|
Port uint `fig:"port"`
|
|
MetricsPath string `fig:"metrics_path"`
|
|
}
|
|
|
|
// InfluxOutputConfig configures the scheduled InfluxDB output. Metrics are
|
|
// pushed every Frequency to InfluxDB's v2 API and/or to Kafka. A zero Frequency
|
|
// (or no destination configured) disables the output.
|
|
type InfluxOutputConfig struct {
|
|
Frequency time.Duration `fig:"frequency"`
|
|
|
|
KafkaBrokers []string `fig:"kafka_brokers"`
|
|
KafkaTopic string `fig:"kafka_topic"`
|
|
KafkaUsername string `fig:"kafka_username"`
|
|
KafkaPassword string `fig:"kafka_password"`
|
|
KafkaInsecureSkipVerify bool `fig:"kafka_insecure_skip_verify"`
|
|
KafkaOutputFormat string `fig:"kafka_output_format"` // lineprotocol (default) or json.
|
|
|
|
InfluxServer string `fig:"influx_server"`
|
|
Token string `fig:"token"`
|
|
Org string `fig:"org"`
|
|
Bucket string `fig:"bucket"`
|
|
}
|
|
|
|
// defaultConfig returns the configuration with all defaults applied, used as the
|
|
// base before a file (if any) is loaded over it.
|
|
func defaultConfig() *Config {
|
|
return &Config{
|
|
HTTP: HTTPOutputConfig{
|
|
Enabled: true,
|
|
Port: 9101,
|
|
MetricsPath: "/metrics",
|
|
},
|
|
Influx: InfluxOutputConfig{
|
|
KafkaOutputFormat: "lineprotocol",
|
|
},
|
|
}
|
|
}
|
|
|
|
// findConfigFile returns the first configuration file that exists, preferring
|
|
// the -config flag (configPath), then a local file, the user config dir, and
|
|
// finally /etc. It returns "" when none is found — configuration is optional.
|
|
func findConfigFile(configPath string) string {
|
|
if configPath != "" {
|
|
if _, err := os.Stat(configPath); err == nil {
|
|
return configPath
|
|
}
|
|
log.Printf("Configured config path %q not found, falling back to defaults", configPath)
|
|
}
|
|
|
|
candidates := []string{}
|
|
if local, err := filepath.Abs("./config.yaml"); err == nil {
|
|
candidates = append(candidates, local)
|
|
}
|
|
if usr, err := user.Current(); err == nil {
|
|
candidates = append(candidates, usr.HomeDir+"/.config/drive-health-metrics/config.yaml")
|
|
}
|
|
candidates = append(candidates, "/etc/drive-health-metrics.yaml")
|
|
|
|
for _, c := range candidates {
|
|
if _, err := os.Stat(c); err == nil {
|
|
return c
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// ReadConfig loads the configuration into app.config. It always succeeds with a
|
|
// usable config: a file is loaded over the defaults when present, flag overrides
|
|
// are applied, and the host tag is resolved when unset.
|
|
func (a *App) ReadConfig() {
|
|
config := defaultConfig()
|
|
|
|
// Load a configuration file over the defaults when one is available.
|
|
if configFile := findConfigFile(a.flags.ConfigPath); configFile != "" {
|
|
dir, name := path.Split(configFile)
|
|
if dir == "" {
|
|
dir = "."
|
|
}
|
|
if err := fig.Load(config, fig.File(name), fig.Dirs(dir)); err != nil {
|
|
log.Printf("Error parsing configuration %q: %s", configFile, err)
|
|
}
|
|
}
|
|
|
|
// Resolve the host tag from the system when not configured.
|
|
if config.Hostname == "" {
|
|
config.Hostname = hostname()
|
|
}
|
|
|
|
// Flag overrides for the HTTP output.
|
|
if a.flags.HTTPBind != "" {
|
|
config.HTTP.BindAddr = a.flags.HTTPBind
|
|
}
|
|
if a.flags.HTTPPort != 0 {
|
|
config.HTTP.Port = a.flags.HTTPPort
|
|
}
|
|
if a.flags.HTTPMetricsPath != "" {
|
|
config.HTTP.MetricsPath = a.flags.HTTPMetricsPath
|
|
}
|
|
|
|
a.config = config
|
|
}
|