mirror of
https://github.com/unpoller/unpoller.git
synced 2026-03-31 06:24:21 -04:00
chore: apply linter auto-fixes (wsl_v5, nlreturn, tagalign) (#984)
golangci-lint auto-fixes across multiple packages: - wsl_v5: blank lines between logical blocks - nlreturn: newlines before return statements - tagalign: struct field tag alignment No logic changes. Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,46 +64,55 @@ func (u *InputUnifi) collectAlarms(logs []any, sites []*unifi.Site, c *Controlle
|
||||
devices, err := c.Unifi.GetDevices(sites)
|
||||
if err != nil {
|
||||
u.LogDebugf("Failed to get devices for alarm enrichment: %v (continuing without device names)", err)
|
||||
|
||||
devices = &unifi.Devices{} // Empty devices struct, alarms will not have device names
|
||||
}
|
||||
|
||||
// Build MAC address to device name lookup map
|
||||
macToName := make(map[string]string)
|
||||
|
||||
for _, d := range devices.UAPs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.USGs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.USWs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.UDMs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.UXGs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.PDUs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.UBBs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.UCIs {
|
||||
if d.Mac != "" && d.Name != "" {
|
||||
macToName[strings.ToLower(d.Mac)] = d.Name
|
||||
@@ -153,7 +162,7 @@ func (u *InputUnifi) collectAnomalies(logs []any, sites []*unifi.Site, c *Contro
|
||||
e.SiteName = c.DefaultSiteNameOverride
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logs = append(logs, e)
|
||||
|
||||
webserver.NewInputEvent(PluginName, s.ID+"_anomalies", &webserver.Event{
|
||||
@@ -201,6 +210,7 @@ func (u *InputUnifi) collectSyslog(logs []any, sites []*unifi.Site, c *Controlle
|
||||
|
||||
// Use v2 system-log API
|
||||
req := unifi.DefaultSystemLogRequest(time.Hour)
|
||||
|
||||
entries, err := c.Unifi.GetSystemLog(sites, req)
|
||||
if err != nil {
|
||||
return logs, fmt.Errorf("unifi.GetSystemLog(): %w", err)
|
||||
@@ -229,6 +239,7 @@ func (u *InputUnifi) collectProtectLogs(logs []any, _ []*unifi.Site, c *Controll
|
||||
u.LogDebugf("Collecting Protect logs: %s (%s)", c.URL, c.ID)
|
||||
|
||||
req := unifi.DefaultProtectLogRequest(0) // Uses default 24-hour window
|
||||
|
||||
entries, err := c.Unifi.GetProtectLogs(req)
|
||||
if err != nil {
|
||||
return logs, fmt.Errorf("unifi.GetProtectLogs(): %w", err)
|
||||
@@ -245,6 +256,7 @@ func (u *InputUnifi) collectProtectLogs(logs []any, _ []*unifi.Site, c *Controll
|
||||
if len(thumbID) > 2 && thumbID[:2] == "e-" {
|
||||
thumbID = thumbID[2:]
|
||||
}
|
||||
|
||||
if thumbData, err := c.Unifi.GetProtectEventThumbnail(thumbID); err == nil {
|
||||
e.ThumbnailBase64 = base64.StdEncoding.EncodeToString(thumbData)
|
||||
} else {
|
||||
@@ -343,6 +355,7 @@ func redactSystemLogEntry(e *unifi.SystemLogEntry, hash *bool, dropPII *bool) *u
|
||||
client.ID = RedactMacPII(client.ID, hash, dropPII)
|
||||
client.IP = RedactIPPII(client.IP, hash, dropPII)
|
||||
}
|
||||
|
||||
e.Parameters["CLIENT"] = client
|
||||
}
|
||||
|
||||
@@ -355,6 +368,7 @@ func redactSystemLogEntry(e *unifi.SystemLogEntry, hash *bool, dropPII *bool) *u
|
||||
ip.ID = RedactIPPII(ip.ID, hash, dropPII)
|
||||
ip.Name = RedactIPPII(ip.Name, hash, dropPII)
|
||||
}
|
||||
|
||||
e.Parameters["IP"] = ip
|
||||
}
|
||||
|
||||
@@ -365,6 +379,7 @@ func redactSystemLogEntry(e *unifi.SystemLogEntry, hash *bool, dropPII *bool) *u
|
||||
} else {
|
||||
admin.Name = RedactNamePII(admin.Name, hash, dropPII)
|
||||
}
|
||||
|
||||
e.Parameters["ADMIN"] = admin
|
||||
}
|
||||
|
||||
@@ -415,6 +430,7 @@ func (u *InputUnifi) extractDeviceNameFromAlarm(alarm *unifi.Alarm, macToName ma
|
||||
|
||||
// Simple regex-like search for MAC address in brackets
|
||||
start := strings.Index(msg, "[")
|
||||
|
||||
end := strings.Index(msg, "]")
|
||||
if start >= 0 && end > start {
|
||||
potentialMAC := msg[start+1 : end]
|
||||
|
||||
@@ -55,17 +55,21 @@ func (u *InputUnifi) Initialize(l poller.Logger) error {
|
||||
discovered, err := u.discoverRemoteControllers(c.APIKey)
|
||||
if err != nil {
|
||||
u.LogErrorf("Failed to discover remote controllers for controller: %v", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if len(discovered) > 0 {
|
||||
// Replace this controller with discovered ones
|
||||
// Remove the current one and add discovered
|
||||
newControllers := []*Controller{}
|
||||
|
||||
for _, existing := range u.Controllers {
|
||||
if existing != c {
|
||||
newControllers = append(newControllers, existing)
|
||||
}
|
||||
}
|
||||
|
||||
newControllers = append(newControllers, discovered...)
|
||||
u.Controllers = newControllers
|
||||
}
|
||||
@@ -214,6 +218,7 @@ func (u *InputUnifi) Events(filter *poller.Filter) (*poller.Events, error) {
|
||||
// Log error but continue to next controller
|
||||
u.LogErrorf("Failed to collect events from controller %s: %v", c.URL, err)
|
||||
collectionErrors = append(collectionErrors, fmt.Errorf("%s: %w", c.URL, err))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
|
||||
if len(consoles) == 0 {
|
||||
u.Logf("No Network-capable consoles found via remote API (NVR/Protect/display-only consoles are excluded)")
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -46,33 +47,43 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
if consoleName == "" {
|
||||
consoleName = console.ReportedState.Name
|
||||
}
|
||||
|
||||
if consoleName == "" {
|
||||
consoleName = console.ReportedState.Hostname
|
||||
}
|
||||
|
||||
if consoleName == "" {
|
||||
consoleName = console.ID
|
||||
}
|
||||
|
||||
u.LogDebugf("Discovering sites for console: %s (%s)", console.ID, consoleName)
|
||||
|
||||
var sites []unifi.RemoteSite
|
||||
var lastErr error
|
||||
var (
|
||||
sites []unifi.RemoteSite
|
||||
lastErr error
|
||||
)
|
||||
|
||||
for attempt := 1; attempt <= discoverMaxAttempts; attempt++ {
|
||||
sites, lastErr = client.DiscoverSites(console.ID)
|
||||
if lastErr == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if attempt < discoverMaxAttempts {
|
||||
u.LogDebugf("Discover sites attempt %d/%d failed for %s: %v; retrying in %v", attempt, discoverMaxAttempts, consoleName, lastErr, discoverRetryDelay)
|
||||
time.Sleep(discoverRetryDelay)
|
||||
}
|
||||
}
|
||||
|
||||
if lastErr != nil {
|
||||
u.Logf("Excluding controller %s: api key does not have permissions (after %d attempts)", consoleName, discoverMaxAttempts)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if len(sites) == 0 {
|
||||
u.LogDebugf("No sites found for console %s", console.ID)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -99,6 +110,7 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
// Set remote-specific defaults and ensure all boolean pointers are initialized
|
||||
t := true
|
||||
f := false
|
||||
|
||||
if controller.VerifySSL == nil {
|
||||
controller.VerifySSL = &t // Remote API should verify SSL
|
||||
}
|
||||
@@ -106,39 +118,51 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
if controller.HashPII == nil {
|
||||
controller.HashPII = &f
|
||||
}
|
||||
|
||||
if controller.DropPII == nil {
|
||||
controller.DropPII = &f
|
||||
}
|
||||
|
||||
if controller.SaveSites == nil {
|
||||
controller.SaveSites = &t
|
||||
}
|
||||
|
||||
if controller.SaveDPI == nil {
|
||||
controller.SaveDPI = &f
|
||||
}
|
||||
|
||||
if controller.SaveEvents == nil {
|
||||
controller.SaveEvents = &f
|
||||
}
|
||||
|
||||
if controller.SaveAlarms == nil {
|
||||
controller.SaveAlarms = &f
|
||||
}
|
||||
|
||||
if controller.SaveAnomal == nil {
|
||||
controller.SaveAnomal = &f
|
||||
}
|
||||
|
||||
if controller.SaveIDs == nil {
|
||||
controller.SaveIDs = &f
|
||||
}
|
||||
|
||||
if controller.SaveTraffic == nil {
|
||||
controller.SaveTraffic = &f
|
||||
}
|
||||
|
||||
if controller.SaveRogue == nil {
|
||||
controller.SaveRogue = &f
|
||||
}
|
||||
|
||||
if controller.SaveSyslog == nil {
|
||||
controller.SaveSyslog = &f
|
||||
}
|
||||
|
||||
if controller.SaveProtectLogs == nil {
|
||||
controller.SaveProtectLogs = &f
|
||||
}
|
||||
|
||||
if controller.ProtectThumbnails == nil {
|
||||
controller.ProtectThumbnails = &f
|
||||
}
|
||||
@@ -162,6 +186,7 @@ func (u *InputUnifi) discoverRemoteControllers(apiKey string) ([]*Controller, er
|
||||
controller.DefaultSiteNameOverride = consoleName
|
||||
// Keep the actual site name for API calls
|
||||
controller.Sites = siteNames
|
||||
|
||||
u.LogDebugf("Using console name '%s' as default site name override for Cloud Gateway (API will use 'default')", consoleName)
|
||||
} else if len(siteNames) > 0 {
|
||||
controller.Sites = siteNames
|
||||
|
||||
@@ -18,10 +18,12 @@ func controllerID(c *Controller) string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
client := c.Unifi
|
||||
if client == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return client.UUID
|
||||
}
|
||||
|
||||
@@ -32,12 +34,15 @@ func updateWeb(c *Controller, metrics *Metrics) {
|
||||
log.Printf("[ERROR] updateWeb panic recovered: %v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
if c == nil || metrics == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.Unifi == nil {
|
||||
return
|
||||
}
|
||||
|
||||
webserver.UpdateInput(&webserver.Input{
|
||||
Name: PluginName, // Forgetting this leads to 3 hours of head scratching.
|
||||
Sites: formatSites(c, metrics.Sites),
|
||||
@@ -97,6 +102,7 @@ func formatSites(c *Controller, sites []*unifi.Site) (s webserver.Sites) {
|
||||
if site == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
s = append(s, &webserver.Site{
|
||||
ID: site.ID,
|
||||
Name: site.Name,
|
||||
@@ -114,6 +120,7 @@ func formatClients(c *Controller, clients []*unifi.Client) (d webserver.Clients)
|
||||
if client == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
clientType, deviceMAC := "unknown", "unknown"
|
||||
if client.ApMac != "" {
|
||||
clientType = "wireless"
|
||||
@@ -157,6 +164,7 @@ func formatDevices(c *Controller, devices *unifi.Devices) (d webserver.Devices)
|
||||
if device == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
d = append(d, &webserver.Device{
|
||||
Name: device.Name,
|
||||
SiteID: device.SiteID,
|
||||
@@ -177,6 +185,7 @@ func formatDevices(c *Controller, devices *unifi.Devices) (d webserver.Devices)
|
||||
if device == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
d = append(d, &webserver.Device{
|
||||
Name: device.Name,
|
||||
SiteID: device.SiteID,
|
||||
@@ -197,6 +206,7 @@ func formatDevices(c *Controller, devices *unifi.Devices) (d webserver.Devices)
|
||||
if device == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
d = append(d, &webserver.Device{
|
||||
Name: device.Name,
|
||||
SiteID: device.SiteID,
|
||||
@@ -217,6 +227,7 @@ func formatDevices(c *Controller, devices *unifi.Devices) (d webserver.Devices)
|
||||
if device == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
d = append(d, &webserver.Device{
|
||||
Name: device.Name,
|
||||
SiteID: device.SiteID,
|
||||
|
||||
@@ -28,15 +28,15 @@ const (
|
||||
|
||||
// Config is the plugin's input data.
|
||||
type Config struct {
|
||||
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" toml:"url" xml:"url" yaml:"url"`
|
||||
Username string `json:"user" toml:"user" xml:"user" yaml:"user"`
|
||||
Password string `json:"pass" toml:"pass" xml:"pass" yaml:"pass"`
|
||||
TenantID string `json:"tenant_id" toml:"tenant_id" xml:"tenant_id" yaml:"tenant_id"`
|
||||
Interval cnfg.Duration `json:"interval" toml:"interval" xml:"interval" yaml:"interval"`
|
||||
Timeout cnfg.Duration `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
|
||||
ExtraLabels map[string]string `json:"extra_labels" toml:"extra_labels" xml:"extra_labels" yaml:"extra_labels"`
|
||||
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" toml:"url" xml:"url" yaml:"url"`
|
||||
Username string `json:"user" toml:"user" xml:"user" yaml:"user"`
|
||||
Password string `json:"pass" toml:"pass" xml:"pass" yaml:"pass"`
|
||||
TenantID string `json:"tenant_id" toml:"tenant_id" xml:"tenant_id" yaml:"tenant_id"`
|
||||
Interval cnfg.Duration `json:"interval" toml:"interval" xml:"interval" yaml:"interval"`
|
||||
Timeout cnfg.Duration `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
|
||||
ExtraLabels map[string]string `json:"extra_labels" toml:"extra_labels" xml:"extra_labels" yaml:"extra_labels"`
|
||||
}
|
||||
|
||||
// Loki is the main library struct. This satisfies the poller.Output interface.
|
||||
|
||||
@@ -84,6 +84,7 @@ func (r *Report) String() string {
|
||||
}
|
||||
|
||||
s += fmt.Sprintf(", Dur: %v", time.Since(r.Start).Round(time.Millisecond))
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,12 @@ func (r *Report) ProtectLogEvent(event *unifi.ProtectLogEntry, logs *Logs) {
|
||||
|
||||
// Marshal event to JSON for the log line (without thumbnail to keep it small)
|
||||
event.ThumbnailBase64 = "" // Temporarily clear for marshaling
|
||||
|
||||
msg, err := json.Marshal(event)
|
||||
if err != nil {
|
||||
msg = []byte(event.Msg())
|
||||
}
|
||||
|
||||
event.ThumbnailBase64 = thumbnailBase64 // Restore
|
||||
|
||||
// Add event log line
|
||||
@@ -68,4 +70,3 @@ func (r *Report) ProtectLogEvent(event *unifi.ProtectLogEntry, logs *Logs) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
// exportFirewallPolicies emits per-rule and per-site aggregate firewall policy metrics.
|
||||
func (u *OtelOutput) exportFirewallPolicies(ctx context.Context, meter metric.Meter, m *poller.Metrics, r *Report) {
|
||||
type siteKey struct{ site, source string }
|
||||
|
||||
type siteStats struct {
|
||||
total int
|
||||
enabled int
|
||||
|
||||
@@ -65,9 +65,9 @@ type OtelUnifi struct {
|
||||
|
||||
// OtelOutput is the working struct for this plugin.
|
||||
type OtelOutput struct {
|
||||
Collector poller.Collect
|
||||
LastCheck time.Time
|
||||
provider *sdkmetric.MeterProvider
|
||||
Collector poller.Collect
|
||||
LastCheck time.Time
|
||||
provider *sdkmetric.MeterProvider
|
||||
*OtelUnifi
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ func (u *OtelOutput) Run(c poller.Collect) error {
|
||||
|
||||
// pollController runs the ticker loop, pushing metrics on each tick.
|
||||
func (u *OtelOutput) pollController() {
|
||||
interval := u.Interval.Duration.Round(time.Second)
|
||||
interval := u.Interval.Round(time.Second)
|
||||
ticker := time.NewTicker(interval)
|
||||
|
||||
defer ticker.Stop()
|
||||
@@ -290,7 +290,7 @@ func (u *OtelOutput) setConfigDefaults() {
|
||||
u.Interval = cnfg.Duration{Duration: minimumInterval}
|
||||
}
|
||||
|
||||
u.Interval = cnfg.Duration{Duration: u.Interval.Duration.Round(time.Second)}
|
||||
u.Interval = cnfg.Duration{Duration: u.Interval.Round(time.Second)}
|
||||
|
||||
if u.Timeout.Duration == 0 {
|
||||
u.Timeout = cnfg.Duration{Duration: 10 * time.Second}
|
||||
|
||||
@@ -42,9 +42,9 @@ func (u *OtelOutput) exportUSW(ctx context.Context, meter metric.Meter, r *Repor
|
||||
u.recordGauge(ctx, meter, r, "unifi_device_usw_load_avg_1",
|
||||
"USW load average 1-minute", s.SysStats.Loadavg1.Val, attrs)
|
||||
u.recordGauge(ctx, meter, r, "unifi_device_usw_rx_bytes",
|
||||
"USW total receive bytes", s.Stat.Sw.RxBytes.Val, attrs)
|
||||
"USW total receive bytes", s.Stat.RxBytes.Val, attrs)
|
||||
u.recordGauge(ctx, meter, r, "unifi_device_usw_tx_bytes",
|
||||
"USW total transmit bytes", s.Stat.Sw.TxBytes.Val, attrs)
|
||||
"USW total transmit bytes", s.Stat.TxBytes.Val, attrs)
|
||||
|
||||
if !u.DeadPorts {
|
||||
for _, p := range s.PortTable {
|
||||
|
||||
@@ -163,6 +163,7 @@ func (u *UnifiPoller) HealthCheck() error {
|
||||
|
||||
// Check if at least one output is enabled.
|
||||
hasEnabledOutput := false
|
||||
|
||||
for _, output := range outputs {
|
||||
if output.Enabled() {
|
||||
hasEnabledOutput = true
|
||||
|
||||
@@ -6,22 +6,22 @@ import (
|
||||
)
|
||||
|
||||
type controller struct {
|
||||
Info *prometheus.Desc
|
||||
UptimeSeconds *prometheus.Desc
|
||||
UpdateAvailable *prometheus.Desc
|
||||
UpdateDownloaded *prometheus.Desc
|
||||
AutobackupEnabled *prometheus.Desc
|
||||
WebRTCSupport *prometheus.Desc
|
||||
IsCloudConsole *prometheus.Desc
|
||||
DataRetentionDays *prometheus.Desc
|
||||
DataRetention5minHours *prometheus.Desc
|
||||
DataRetentionHourlyHours *prometheus.Desc
|
||||
DataRetentionDailyHours *prometheus.Desc
|
||||
Info *prometheus.Desc
|
||||
UptimeSeconds *prometheus.Desc
|
||||
UpdateAvailable *prometheus.Desc
|
||||
UpdateDownloaded *prometheus.Desc
|
||||
AutobackupEnabled *prometheus.Desc
|
||||
WebRTCSupport *prometheus.Desc
|
||||
IsCloudConsole *prometheus.Desc
|
||||
DataRetentionDays *prometheus.Desc
|
||||
DataRetention5minHours *prometheus.Desc
|
||||
DataRetentionHourlyHours *prometheus.Desc
|
||||
DataRetentionDailyHours *prometheus.Desc
|
||||
DataRetentionMonthlyHours *prometheus.Desc
|
||||
UnsupportedDeviceCount *prometheus.Desc
|
||||
InformPort *prometheus.Desc
|
||||
HTTPSPort *prometheus.Desc
|
||||
PortalHTTPPort *prometheus.Desc
|
||||
UnsupportedDeviceCount *prometheus.Desc
|
||||
InformPort *prometheus.Desc
|
||||
HTTPSPort *prometheus.Desc
|
||||
PortalHTTPPort *prometheus.Desc
|
||||
}
|
||||
|
||||
func descController(ns string) *controller {
|
||||
@@ -31,22 +31,22 @@ func descController(ns string) *controller {
|
||||
nd := prometheus.NewDesc
|
||||
|
||||
return &controller{
|
||||
Info: nd(ns+"controller_info", "Controller information (always 1)", infoLabels, nil),
|
||||
UptimeSeconds: nd(ns+"controller_uptime_seconds", "Controller uptime in seconds", labels, nil),
|
||||
UpdateAvailable: nd(ns+"controller_update_available", "Update available (1/0)", labels, nil),
|
||||
UpdateDownloaded: nd(ns+"controller_update_downloaded", "Update downloaded (1/0)", labels, nil),
|
||||
AutobackupEnabled: nd(ns+"controller_autobackup_enabled", "Auto backup enabled (1/0)", labels, nil),
|
||||
WebRTCSupport: nd(ns+"controller_webrtc_support", "WebRTC supported (1/0)", labels, nil),
|
||||
IsCloudConsole: nd(ns+"controller_is_cloud_console", "Is cloud console (1/0)", labels, nil),
|
||||
DataRetentionDays: nd(ns+"controller_data_retention_days", "Data retention in days", labels, nil),
|
||||
DataRetention5minHours: nd(ns+"controller_data_retention_5min_hours", "5-minute scale retention hours", labels, nil),
|
||||
DataRetentionHourlyHours: nd(ns+"controller_data_retention_hourly_hours", "Hourly scale retention hours", labels, nil),
|
||||
DataRetentionDailyHours: nd(ns+"controller_data_retention_daily_hours", "Daily scale retention hours", labels, nil),
|
||||
Info: nd(ns+"controller_info", "Controller information (always 1)", infoLabels, nil),
|
||||
UptimeSeconds: nd(ns+"controller_uptime_seconds", "Controller uptime in seconds", labels, nil),
|
||||
UpdateAvailable: nd(ns+"controller_update_available", "Update available (1/0)", labels, nil),
|
||||
UpdateDownloaded: nd(ns+"controller_update_downloaded", "Update downloaded (1/0)", labels, nil),
|
||||
AutobackupEnabled: nd(ns+"controller_autobackup_enabled", "Auto backup enabled (1/0)", labels, nil),
|
||||
WebRTCSupport: nd(ns+"controller_webrtc_support", "WebRTC supported (1/0)", labels, nil),
|
||||
IsCloudConsole: nd(ns+"controller_is_cloud_console", "Is cloud console (1/0)", labels, nil),
|
||||
DataRetentionDays: nd(ns+"controller_data_retention_days", "Data retention in days", labels, nil),
|
||||
DataRetention5minHours: nd(ns+"controller_data_retention_5min_hours", "5-minute scale retention hours", labels, nil),
|
||||
DataRetentionHourlyHours: nd(ns+"controller_data_retention_hourly_hours", "Hourly scale retention hours", labels, nil),
|
||||
DataRetentionDailyHours: nd(ns+"controller_data_retention_daily_hours", "Daily scale retention hours", labels, nil),
|
||||
DataRetentionMonthlyHours: nd(ns+"controller_data_retention_monthly_hours", "Monthly scale retention hours", labels, nil),
|
||||
UnsupportedDeviceCount: nd(ns+"controller_unsupported_device_count", "Number of unsupported devices", labels, nil),
|
||||
InformPort: nd(ns+"controller_inform_port", "Inform port number", labels, nil),
|
||||
HTTPSPort: nd(ns+"controller_https_port", "HTTPS port number", labels, nil),
|
||||
PortalHTTPPort: nd(ns+"controller_portal_http_port", "Portal HTTP port number", labels, nil),
|
||||
UnsupportedDeviceCount: nd(ns+"controller_unsupported_device_count", "Number of unsupported devices", labels, nil),
|
||||
InformPort: nd(ns+"controller_inform_port", "Inform port number", labels, nil),
|
||||
HTTPSPort: nd(ns+"controller_https_port", "HTTPS port number", labels, nil),
|
||||
PortalHTTPPort: nd(ns+"controller_portal_http_port", "Portal HTTP port number", labels, nil),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +55,11 @@ func (u *promUnifi) exportSysinfo(r report, s *unifi.Sysinfo) {
|
||||
if hostname == "" {
|
||||
hostname = s.Name
|
||||
}
|
||||
|
||||
if hostname == "" {
|
||||
hostname = s.SiteName // fallback when API omits both (e.g. remote/cloud)
|
||||
}
|
||||
|
||||
labels := []string{hostname, s.SiteName, s.SourceName}
|
||||
infoLabels := []string{s.Version, s.Build, s.DeviceType, s.ConsoleVer, hostname, s.SiteName, s.SourceName}
|
||||
|
||||
@@ -65,18 +67,22 @@ func (u *promUnifi) exportSysinfo(r report, s *unifi.Sysinfo) {
|
||||
if s.UpdateAvail {
|
||||
updateAvail = 1
|
||||
}
|
||||
|
||||
updateDown := 0
|
||||
if s.UpdateDown {
|
||||
updateDown = 1
|
||||
}
|
||||
|
||||
autobackup := 0
|
||||
if s.Autobackup {
|
||||
autobackup = 1
|
||||
}
|
||||
|
||||
webrtc := 0
|
||||
if s.HasWebRTC {
|
||||
webrtc = 1
|
||||
}
|
||||
|
||||
cloud := 0
|
||||
if s.IsCloud {
|
||||
cloud = 1
|
||||
|
||||
@@ -58,6 +58,7 @@ func (u *promUnifi) exportFirewallPolicies(r report, policies []*unifi.FirewallP
|
||||
|
||||
// Per-site aggregate counters, keyed by "siteName|source"
|
||||
type siteKey struct{ site, source string }
|
||||
|
||||
type siteStats struct {
|
||||
total int
|
||||
enabled int
|
||||
|
||||
@@ -59,18 +59,18 @@ type pdu struct {
|
||||
OutletPowerFactor *prometheus.Desc
|
||||
OutletVoltage *prometheus.Desc
|
||||
// UPS battery health (vbms_table)
|
||||
BatteryLevelPercent *prometheus.Desc
|
||||
BatteryTimeRemaining *prometheus.Desc
|
||||
BatteryCharging *prometheus.Desc
|
||||
BatteryMode *prometheus.Desc
|
||||
BatteriesAvailable *prometheus.Desc
|
||||
BatteriesReady *prometheus.Desc
|
||||
PowerBudgetWatts *prometheus.Desc
|
||||
PowerOutputWatts *prometheus.Desc
|
||||
PowerFactor *prometheus.Desc
|
||||
OutputVoltage *prometheus.Desc
|
||||
OutputCurrentAmps *prometheus.Desc
|
||||
LoadPercent *prometheus.Desc
|
||||
BatteryLevelPercent *prometheus.Desc
|
||||
BatteryTimeRemaining *prometheus.Desc
|
||||
BatteryCharging *prometheus.Desc
|
||||
BatteryMode *prometheus.Desc
|
||||
BatteriesAvailable *prometheus.Desc
|
||||
BatteriesReady *prometheus.Desc
|
||||
PowerBudgetWatts *prometheus.Desc
|
||||
PowerOutputWatts *prometheus.Desc
|
||||
PowerFactor *prometheus.Desc
|
||||
OutputVoltage *prometheus.Desc
|
||||
OutputCurrentAmps *prometheus.Desc
|
||||
LoadPercent *prometheus.Desc
|
||||
BMSAnomalyCount *prometheus.Desc
|
||||
PowerCycleOnRecoveryEnabled *prometheus.Desc
|
||||
}
|
||||
@@ -182,6 +182,7 @@ func (u *promUnifi) exportPDU(r report, d *unifi.PDU) {
|
||||
if d.VBMSTable != nil {
|
||||
u.exportPDUVBMS(r, d, append([]string{d.SiteName, d.Name, d.Mac, d.SourceName}, tag))
|
||||
}
|
||||
|
||||
u.exportBYTstats(r, labels, d.TxBytes, d.RxBytes)
|
||||
u.exportSYSstats(r, labels, d.SysStats, d.SystemStats)
|
||||
u.exportSTAcount(r, labels, d.UserNumSta, d.GuestNumSta)
|
||||
|
||||
@@ -72,6 +72,7 @@ func (r *Report) export(m *metric, v float64) prometheus.Metric {
|
||||
for _, label := range m.Labels {
|
||||
bytes += len(label) + 3 // label value + quotes and comma/equals overhead
|
||||
}
|
||||
|
||||
bytes += 20 // approximate size for value and timestamp
|
||||
|
||||
r.Bytes += bytes
|
||||
|
||||
Reference in New Issue
Block a user