mirror of
https://github.com/unpoller/unpoller.git
synced 2026-04-05 08:54:09 -04:00
Enrich alarms with device names for Loki logs
Added device name enrichment to alarms so that Loki logs show human-readable device names instead of just MAC addresses. Changes: - Modified collectAlarms to fetch devices and build MAC-to-name lookup - Added extractDeviceNameFromAlarm helper to extract MAC addresses from alarm messages and lookup corresponding device names - Device names are extracted from messages like "AP[fc:ec:da:89:a6:91]" or from SrcMAC/DstMAC fields - Added go.mod replace directive to use local unifi library with new DeviceName field The device_name field will now be included in the JSON output sent to Loki, making it easier to identify which device triggered an alarm. Fixes #415 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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