mirror of
https://github.com/unpoller/unpoller.git
synced 2026-03-31 06:24:21 -04:00
Merge pull request #919 from unpoller/issue-415
Enrich alarms with device names for Loki logs
This commit is contained in:
4
go.mod
4
go.mod
@@ -12,7 +12,7 @@ require (
|
||||
github.com/prometheus/common v0.67.5
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/unpoller/unifi/v5 v5.6.0
|
||||
github.com/unpoller/unifi/v5 v5.7.0
|
||||
golang.org/x/crypto v0.47.0
|
||||
golang.org/x/term v0.39.0
|
||||
golift.io/cnfg v0.2.3
|
||||
@@ -46,3 +46,5 @@ require (
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
|
||||
// replace github.com/unpoller/unifi/v5 => ../unifi
|
||||
|
||||
4
go.sum
4
go.sum
@@ -77,8 +77,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/unpoller/unifi/v5 v5.6.0 h1:qryEAJNYXG/WbjIqrIEZ/npRNBwHTsv/ZFbseYry8ug=
|
||||
github.com/unpoller/unifi/v5 v5.6.0/go.mod h1:vSIXIclPG9dpKxUp+pavfgENHWaTZXvDg7F036R1YCo=
|
||||
github.com/unpoller/unifi/v5 v5.7.0 h1:mGdHLOvmeQqnyB8mgI/ZzMMd/7kaGm+zd9p6iIF4W6g=
|
||||
github.com/unpoller/unifi/v5 v5.7.0/go.mod h1:vSIXIclPG9dpKxUp+pavfgENHWaTZXvDg7F036R1YCo=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
|
||||
@@ -51,6 +51,56 @@ func (u *InputUnifi) collectAlarms(logs []any, sites []*unifi.Site, c *Controlle
|
||||
if *c.SaveAlarms {
|
||||
u.LogDebugf("Collecting controller alarms: %s (%s)", c.URL, c.ID)
|
||||
|
||||
// Get devices for all sites to build MAC-to-name lookup
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range sites {
|
||||
events, err := c.Unifi.GetAlarmsSite(s)
|
||||
if err != nil {
|
||||
@@ -58,6 +108,9 @@ func (u *InputUnifi) collectAlarms(logs []any, sites []*unifi.Site, c *Controlle
|
||||
}
|
||||
|
||||
for _, e := range events {
|
||||
// Try to extract MAC address from alarm message and enrich with device name
|
||||
e.DeviceName = u.extractDeviceNameFromAlarm(e, macToName)
|
||||
|
||||
logs = append(logs, e)
|
||||
|
||||
webserver.NewInputEvent(PluginName, s.ID+"_alarms", &webserver.Event{
|
||||
@@ -343,3 +396,39 @@ func hasProtectThumbnail(eventType string) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// extractDeviceNameFromAlarm attempts to extract a device name for an alarm by looking up
|
||||
// MAC addresses found in the alarm message or fields. Returns empty string if no match found.
|
||||
func (u *InputUnifi) extractDeviceNameFromAlarm(alarm *unifi.Alarm, macToName map[string]string) string {
|
||||
// Try to extract MAC from message like "AP[fc:ec:da:89:a6:91] was disconnected"
|
||||
// Look for pattern: [XX:XX:XX:XX:XX:XX] where X is hex digit
|
||||
msg := alarm.Msg
|
||||
|
||||
// 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]
|
||||
// Basic validation: should be 17 characters and contain colons
|
||||
if len(potentialMAC) == 17 && strings.Count(potentialMAC, ":") == 5 {
|
||||
if name, ok := macToName[strings.ToLower(potentialMAC)]; ok {
|
||||
return name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also try SrcMAC and DstMAC fields if present
|
||||
if alarm.SrcMAC != "" {
|
||||
if name, ok := macToName[strings.ToLower(alarm.SrcMAC)]; ok {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
if alarm.DstMAC != "" {
|
||||
if name, ok := macToName[strings.ToLower(alarm.DstMAC)]; ok {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user