From 4b5072fd6df9a0047d20a4022abf73f2ddb6ab34 Mon Sep 17 00:00:00 2001 From: davidnewhall2 Date: Sun, 15 Dec 2019 03:27:34 -0800 Subject: [PATCH] trimming --- .../promunifi/pkg/influxunifi/metrics.go | 34 ++++++++++++------- integrations/promunifi/pkg/poller/config.go | 12 +++---- integrations/promunifi/pkg/poller/dumper.go | 8 ++--- integrations/promunifi/pkg/poller/outputs.go | 4 +-- integrations/promunifi/pkg/poller/start.go | 22 +++++------- .../promunifi/pkg/promunifi/collector.go | 27 ++++++++------- 6 files changed, 56 insertions(+), 51 deletions(-) diff --git a/integrations/promunifi/pkg/influxunifi/metrics.go b/integrations/promunifi/pkg/influxunifi/metrics.go index 6775ac06..e983edce 100644 --- a/integrations/promunifi/pkg/influxunifi/metrics.go +++ b/integrations/promunifi/pkg/influxunifi/metrics.go @@ -10,11 +10,12 @@ import ( "github.com/davidnewhall/unifi-poller/pkg/poller" influx "github.com/influxdata/influxdb1-client/v2" - conf "golift.io/config" + "golift.io/config" ) const ( defaultInterval = 30 * time.Second + minimumInterval = 10 * time.Second defaultInfluxDB = "unifi" defaultInfluxUser = "unifi" defaultInfluxURL = "http://127.0.0.1:8086" @@ -22,13 +23,13 @@ const ( // Config defines the data needed to store metrics in InfluxDB type Config struct { - Interval conf.Duration `json:"interval,omitempty" toml:"interval,omitempty" xml:"interval" yaml:"interval"` - Disable bool `json:"disable" toml:"disable" xml:"disable" yaml:"disable"` - VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"` - URL string `json:"url,omitempty" toml:"url,omitempty" xml:"url" yaml:"url"` - User string `json:"user,omitempty" toml:"user,omitempty" xml:"user" yaml:"user"` - Pass string `json:"pass,omitempty" toml:"pass,omitempty" xml:"pass" yaml:"pass"` - DB string `json:"db,omitempty" toml:"db,omitempty" xml:"db" yaml:"db"` + Interval config.Duration `json:"interval,omitempty" toml:"interval,omitempty" xml:"interval" yaml:"interval"` + Disable bool `json:"disable" toml:"disable" xml:"disable" yaml:"disable"` + VerifySSL bool `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"` + URL string `json:"url,omitempty" toml:"url,omitempty" xml:"url" yaml:"url"` + User string `json:"user,omitempty" toml:"user,omitempty" xml:"user" yaml:"user"` + Pass string `json:"pass,omitempty" toml:"pass,omitempty" xml:"pass" yaml:"pass"` + DB string `json:"db,omitempty" toml:"db,omitempty" xml:"db" yaml:"db"` } // InfluxDB allows the data to be nested in the config file. @@ -63,9 +64,9 @@ func init() { // This is started by Run() or RunBoth() after everything checks out. func (u *InfluxUnifi) PollController() { interval := u.Config.Interval.Round(time.Second) + ticker := time.NewTicker(interval) log.Printf("[INFO] Everything checks out! Poller started, InfluxDB interval: %v", interval) - ticker := time.NewTicker(interval) for u.LastCheck = range ticker.C { metrics, err := u.Collector.Metrics() if err != nil { @@ -128,12 +129,12 @@ func (u *InfluxUnifi) setConfigDefaults() { } if u.Config.Interval.Duration == 0 { - u.Config.Interval = conf.Duration{Duration: defaultInterval} - } else if u.Config.Interval.Duration < defaultInterval/2 { - u.Config.Interval = conf.Duration{Duration: defaultInterval / 2} + u.Config.Interval = config.Duration{Duration: defaultInterval} + } else if u.Config.Interval.Duration < minimumInterval { + u.Config.Interval = config.Duration{Duration: minimumInterval} } - u.Config.Interval = conf.Duration{Duration: u.Config.Interval.Duration.Round(time.Second)} + u.Config.Interval = config.Duration{Duration: u.Config.Interval.Duration.Round(time.Second)} } // ReportMetrics batches all device and client data into influxdb data points. @@ -179,6 +180,7 @@ func (u *InfluxUnifi) collect(r report, ch chan *metric) { // to the collect routine through the metric channel. func (u *InfluxUnifi) loopPoints(r report) { m := r.metrics() + r.add() go func() { defer r.done() @@ -186,6 +188,7 @@ func (u *InfluxUnifi) loopPoints(r report) { u.batchSite(r, s) } }() + r.add() go func() { defer r.done() @@ -193,6 +196,7 @@ func (u *InfluxUnifi) loopPoints(r report) { u.batchClient(r, s) } }() + r.add() go func() { defer r.done() @@ -200,6 +204,7 @@ func (u *InfluxUnifi) loopPoints(r report) { u.batchIDS(r, s) } }() + if m.Devices == nil { return } @@ -211,6 +216,7 @@ func (u *InfluxUnifi) loopPoints(r report) { u.batchUAP(r, s) } }() + r.add() go func() { defer r.done() @@ -218,6 +224,7 @@ func (u *InfluxUnifi) loopPoints(r report) { u.batchUSG(r, s) } }() + r.add() go func() { defer r.done() @@ -225,6 +232,7 @@ func (u *InfluxUnifi) loopPoints(r report) { u.batchUSW(r, s) } }() + r.add() go func() { defer r.done() diff --git a/integrations/promunifi/pkg/poller/config.go b/integrations/promunifi/pkg/poller/config.go index 0d6fe126..e77db20b 100644 --- a/integrations/promunifi/pkg/poller/config.go +++ b/integrations/promunifi/pkg/poller/config.go @@ -31,13 +31,13 @@ const ENVConfigPrefix = "UP" // UnifiPoller contains the application startup data, and auth info for UniFi & Influx. type UnifiPoller struct { - Flag *Flag + Flags *Flags Config *Config sync.Mutex // locks the Unifi struct member when re-authing to unifi. } -// Flag represents the CLI args available and their settings. -type Flag struct { +// Flags represents the CLI args available and their settings. +type Flags struct { ConfigFile string DumpJSON string ShowVer bool @@ -84,8 +84,8 @@ type Poller struct { // ParseConfigs parses the poller config and the config for each registered output plugin. func (u *UnifiPoller) ParseConfigs() error { // Parse config file. - if err := config.ParseFile(u.Config, u.Flag.ConfigFile); err != nil { - u.Flag.Usage() + if err := config.ParseFile(u.Config, u.Flags.ConfigFile); err != nil { + u.Flags.Usage() return err } @@ -99,7 +99,7 @@ func (u *UnifiPoller) ParseConfigs() error { for _, o := range outputs { // Parse config file for each output plugin. - if err := config.ParseFile(o.Config, u.Flag.ConfigFile); err != nil { + if err := config.ParseFile(o.Config, u.Flags.ConfigFile); err != nil { return err } diff --git a/integrations/promunifi/pkg/poller/dumper.go b/integrations/promunifi/pkg/poller/dumper.go index 3151ae9c..5892488b 100644 --- a/integrations/promunifi/pkg/poller/dumper.go +++ b/integrations/promunifi/pkg/poller/dumper.go @@ -37,12 +37,12 @@ func (u *UnifiPoller) DumpJSONPayload() (err error) { switch sites, err := u.GetFilteredSites(config); { case err != nil: return err - case StringInSlice(u.Flag.DumpJSON, []string{"d", "device", "devices"}): + case StringInSlice(u.Flags.DumpJSON, []string{"d", "device", "devices"}): return u.dumpSitesJSON(config, unifi.APIDevicePath, "Devices", sites) - case StringInSlice(u.Flag.DumpJSON, []string{"client", "clients", "c"}): + case StringInSlice(u.Flags.DumpJSON, []string{"client", "clients", "c"}): return u.dumpSitesJSON(config, unifi.APIClientPath, "Clients", sites) - case strings.HasPrefix(u.Flag.DumpJSON, "other "): - apiPath := strings.SplitN(u.Flag.DumpJSON, " ", 2)[1] + case strings.HasPrefix(u.Flags.DumpJSON, "other "): + apiPath := strings.SplitN(u.Flags.DumpJSON, " ", 2)[1] _, _ = fmt.Fprintf(os.Stderr, "[INFO] Dumping Path '%s':\n", apiPath) return u.PrintRawAPIJSON(config, apiPath) default: diff --git a/integrations/promunifi/pkg/poller/outputs.go b/integrations/promunifi/pkg/poller/outputs.go index 37f8fbb2..aaa9a47d 100644 --- a/integrations/promunifi/pkg/poller/outputs.go +++ b/integrations/promunifi/pkg/poller/outputs.go @@ -55,7 +55,7 @@ func (u *UnifiPoller) InitializeOutputs() error { } if count < 1 { - return fmt.Errorf("no output plugins configured") + return fmt.Errorf("no output plugins imported") } for err := range v { @@ -64,7 +64,7 @@ func (u *UnifiPoller) InitializeOutputs() error { } if count--; count < 1 { - return fmt.Errorf("all output plugins have stopped") + return fmt.Errorf("all output plugins have stopped, or none enabled") } } diff --git a/integrations/promunifi/pkg/poller/start.go b/integrations/promunifi/pkg/poller/start.go index 06069583..7893f32f 100644 --- a/integrations/promunifi/pkg/poller/start.go +++ b/integrations/promunifi/pkg/poller/start.go @@ -10,15 +10,9 @@ import ( "github.com/spf13/pflag" ) -// New returns a new poller struct preloaded with default values. -// No need to call this if you call Start.c +// New returns a new poller struct. func New() *UnifiPoller { - return &UnifiPoller{ - Config: &Config{}, - Flag: &Flag{ - ConfigFile: DefaultConfFile, - }, - } + return &UnifiPoller{Config: &Config{}, Flags: &Flags{}} } // Start begins the application from a CLI. @@ -27,15 +21,15 @@ func New() *UnifiPoller { func (u *UnifiPoller) Start() error { log.SetOutput(os.Stdout) log.SetFlags(log.LstdFlags) - u.Flag.Parse(os.Args[1:]) + u.Flags.Parse(os.Args[1:]) - if u.Flag.ShowVer { + if u.Flags.ShowVer { fmt.Printf("%s v%s\n", AppName, version.Version) return nil // don't run anything else w/ version request. } - if u.Flag.DumpJSON == "" { // do not print this when dumping JSON. - u.Logf("Loading Configuration File: %s", u.Flag.ConfigFile) + if u.Flags.DumpJSON == "" { // do not print this when dumping JSON. + u.Logf("Loading Configuration File: %s", u.Flags.ConfigFile) } // Parse config file and ENV variables. @@ -53,7 +47,7 @@ func (u *UnifiPoller) Start() error { }} } - if u.Flag.DumpJSON != "" { + if u.Flags.DumpJSON != "" { return u.DumpJSONPayload() } @@ -66,7 +60,7 @@ func (u *UnifiPoller) Start() error { } // Parse turns CLI arguments into data structures. Called by Start() on startup. -func (f *Flag) Parse(args []string) { +func (f *Flags) Parse(args []string) { f.FlagSet = pflag.NewFlagSet(AppName, pflag.ExitOnError) f.Usage = func() { fmt.Printf("Usage: %s [--config=/path/to/up.conf] [--version]", AppName) diff --git a/integrations/promunifi/pkg/promunifi/collector.go b/integrations/promunifi/pkg/promunifi/collector.go index 6da6db38..61c8db81 100644 --- a/integrations/promunifi/pkg/promunifi/collector.go +++ b/integrations/promunifi/pkg/promunifi/collector.go @@ -65,6 +65,7 @@ type metric struct { // Report accumulates counters that are printed to a log line. type Report struct { + Config Total int // Total count of metrics recorded. Errors int // Total count of errors recording metrics. Zeros int // Total count of metrics equal to zero. @@ -74,7 +75,6 @@ type Report struct { Start time.Time // Time collection began. ch chan []*metric wg sync.WaitGroup - Config } func init() { @@ -97,27 +97,28 @@ func (u *promUnifi) Run(c poller.Collect) error { u.Config.Namespace = strings.Replace(poller.AppName, "-", "", -1) } + u.Config.Namespace = strings.Replace(u.Config.Namespace, "-", "_", -1) + if u.Config.HTTPListen == "" { u.Config.HTTPListen = defaultHTTPListen } - name := strings.Replace(u.Config.Namespace, "-", "_", -1) + prometheus.MustRegister(version.NewCollector(u.Config.Namespace)) - ns := name - if ns = strings.Trim(ns, "_") + "_"; ns == "_" { - ns = "" + if u.Config.Namespace = strings.Trim(u.Config.Namespace, "_") + "_"; u.Config.Namespace == "_" { + u.Config.Namespace = "" } - prometheus.MustRegister(version.NewCollector(name)) prometheus.MustRegister(&promUnifi{ Collector: c, - Client: descClient(ns + "client_"), - Device: descDevice(ns + "device_"), // stats for all device types. - UAP: descUAP(ns + "device_"), - USG: descUSG(ns + "device_"), - USW: descUSW(ns + "device_"), - Site: descSite(ns + "site_"), + Client: descClient(u.Config.Namespace + "client_"), + Device: descDevice(u.Config.Namespace + "device_"), // stats for all device types. + UAP: descUAP(u.Config.Namespace + "device_"), + USG: descUSG(u.Config.Namespace + "device_"), + USW: descUSW(u.Config.Namespace + "device_"), + Site: descSite(u.Config.Namespace + "site_"), }) + c.Logf("Exporting Measurements for Prometheus at https://%s/metrics, namespace: %s", u.Config.HTTPListen, u.Config.Namespace) return http.ListenAndServe(u.Config.HTTPListen, nil) @@ -185,12 +186,14 @@ func (u *promUnifi) exportMetrics(r report, ch chan<- prometheus.Metric, ourChan r.error(ch, m.Desc, fmt.Sprintf("not a number: %v", m.Value)) } } + r.done() } } func (u *promUnifi) loopExports(r report) { m := r.metrics() + r.add() go func() { defer r.done()