mirror of
https://github.com/unpoller/unpoller.git
synced 2026-04-05 08:54:00 -04:00
Add an ExtraLabels map[string]string field to the Loki Config struct so users can define static key=value labels that are merged into the stream labels of every log line sent to Loki. This allows users to distinguish streams (e.g., by environment or datacenter) without hardcoding values. Built-in dynamic labels (application, site_name, source, etc.) always take precedence over extra labels to preserve existing behavior. Example config (TOML): [loki.extra_labels] environment = "production" datacenter = "us-east-1" Closes #691 Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
70 lines
2.2 KiB
Go
70 lines
2.2 KiB
Go
package lokiunifi
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strconv"
|
|
|
|
"github.com/unpoller/unifi/v5"
|
|
)
|
|
|
|
const typeProtectLog = "ProtectLog"
|
|
const typeProtectThumbnail = "ProtectThumbnail"
|
|
|
|
// ProtectLogEvent stores a structured UniFi Protect Log Entry for batch sending to Loki.
|
|
// Logs the raw JSON for parsing with Loki's `| json` pipeline.
|
|
// If the event has a thumbnail, it's sent as a separate log line.
|
|
func (r *Report) ProtectLogEvent(event *unifi.ProtectLogEntry, logs *Logs) {
|
|
if event.Datetime().Before(r.Oldest) {
|
|
return
|
|
}
|
|
|
|
r.Counts[typeProtectLog]++ // increase counter and append new log line.
|
|
|
|
// Store thumbnail separately before marshaling (it's excluded from JSON by default now)
|
|
thumbnailBase64 := event.ThumbnailBase64
|
|
|
|
// 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
|
|
logs.Streams = append(logs.Streams, LogStream{
|
|
Entries: [][]string{{strconv.FormatInt(event.Datetime().UnixNano(), 10), string(msg)}},
|
|
Labels: CleanLabels(MergeLabels(map[string]string{
|
|
"application": "unifi_protect_log",
|
|
"source": event.SourceName,
|
|
"event_type": event.GetEventType(),
|
|
"category": event.GetCategory(),
|
|
"severity": event.GetSeverity(),
|
|
"camera": event.Camera,
|
|
}, r.ExtraLabels)),
|
|
})
|
|
|
|
// Add thumbnail as separate log line if present
|
|
if thumbnailBase64 != "" {
|
|
r.Counts[typeProtectThumbnail]++
|
|
|
|
thumbnailJSON, _ := json.Marshal(map[string]string{
|
|
"event_id": event.ID,
|
|
"thumbnail_base64": thumbnailBase64,
|
|
"mime_type": "image/jpeg",
|
|
})
|
|
|
|
// Use timestamp + 1 nanosecond to ensure ordering (thumbnail after event)
|
|
logs.Streams = append(logs.Streams, LogStream{
|
|
Entries: [][]string{{strconv.FormatInt(event.Datetime().UnixNano()+1, 10), string(thumbnailJSON)}},
|
|
Labels: CleanLabels(MergeLabels(map[string]string{
|
|
"application": "unifi_protect_thumbnail",
|
|
"source": event.SourceName,
|
|
"event_id": event.ID,
|
|
"camera": event.Camera,
|
|
}, r.ExtraLabels)),
|
|
})
|
|
}
|
|
}
|
|
|