diff --git a/pkg/lokiunifi/loki.go b/pkg/lokiunifi/loki.go index dc6c7a0e..e94c4d3a 100644 --- a/pkg/lokiunifi/loki.go +++ b/pkg/lokiunifi/loki.go @@ -34,8 +34,9 @@ type Config struct { 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"` + 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. diff --git a/pkg/lokiunifi/report.go b/pkg/lokiunifi/report.go index e61e18fb..f74c95b7 100644 --- a/pkg/lokiunifi/report.go +++ b/pkg/lokiunifi/report.go @@ -23,9 +23,10 @@ type Logs struct { // Report is the temporary data generated by processing events. type Report struct { - Start time.Time - Oldest time.Time - Collect poller.Collect + Start time.Time + Oldest time.Time + Collect poller.Collect + ExtraLabels map[string]string poller.Logger Counts map[string]int } @@ -33,11 +34,12 @@ type Report struct { // NewReport makes a new report. func (l *Loki) NewReport(start time.Time) *Report { return &Report{ - Start: start, - Oldest: l.last, - Collect: l.Collect, - Logger: l, - Counts: make(map[string]int), + Start: start, + Oldest: l.last, + Collect: l.Collect, + ExtraLabels: l.ExtraLabels, + Logger: l, + Counts: make(map[string]int), } } @@ -95,3 +97,14 @@ func CleanLabels(labels map[string]string) map[string]string { return labels } + +// MergeLabels merges extra into labels. Keys already present in labels are not overwritten. +func MergeLabels(labels, extra map[string]string) map[string]string { + for k, v := range extra { + if _, exists := labels[k]; !exists { + labels[k] = v + } + } + + return labels +} diff --git a/pkg/lokiunifi/report_alarm.go b/pkg/lokiunifi/report_alarm.go index f8bd19e3..1ae85852 100644 --- a/pkg/lokiunifi/report_alarm.go +++ b/pkg/lokiunifi/report_alarm.go @@ -26,10 +26,10 @@ func (r *Report) Alarm(event *unifi.Alarm, logs *Logs) { logs.Streams = append(logs.Streams, LogStream{ Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), string(msg)}}, - Labels: CleanLabels(map[string]string{ + Labels: CleanLabels(MergeLabels(map[string]string{ "application": "unifi_alarm", "source": event.SourceName, "site_name": event.SiteName, - }), + }, r.ExtraLabels)), }) } diff --git a/pkg/lokiunifi/report_anomaly.go b/pkg/lokiunifi/report_anomaly.go index 8a3d49e6..d9ca734a 100644 --- a/pkg/lokiunifi/report_anomaly.go +++ b/pkg/lokiunifi/report_anomaly.go @@ -26,10 +26,10 @@ func (r *Report) Anomaly(event *unifi.Anomaly, logs *Logs) { logs.Streams = append(logs.Streams, LogStream{ Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), string(msg)}}, - Labels: CleanLabels(map[string]string{ + Labels: CleanLabels(MergeLabels(map[string]string{ "application": "unifi_anomaly", "source": event.SourceName, "site_name": event.SiteName, - }), + }, r.ExtraLabels)), }) } diff --git a/pkg/lokiunifi/report_event.go b/pkg/lokiunifi/report_event.go index 56e3046d..e7680fef 100644 --- a/pkg/lokiunifi/report_event.go +++ b/pkg/lokiunifi/report_event.go @@ -27,11 +27,11 @@ func (r *Report) Event(event *unifi.Event, logs *Logs) { logs.Streams = append(logs.Streams, LogStream{ Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), string(msg)}}, - Labels: CleanLabels(map[string]string{ + Labels: CleanLabels(MergeLabels(map[string]string{ "application": "unifi_event", "site_name": event.SiteName, "source": event.SourceName, - }), + }, r.ExtraLabels)), }) } @@ -52,12 +52,12 @@ func (r *Report) SystemLogEvent(event *unifi.SystemLogEntry, logs *Logs) { logs.Streams = append(logs.Streams, LogStream{ Entries: [][]string{{strconv.FormatInt(event.Datetime().UnixNano(), 10), string(msg)}}, - Labels: CleanLabels(map[string]string{ + Labels: CleanLabels(MergeLabels(map[string]string{ "application": "unifi_system_log", "site_name": event.SiteName, "source": event.SourceName, "category": event.Category, "severity": event.Severity, - }), + }, r.ExtraLabels)), }) } diff --git a/pkg/lokiunifi/report_ids.go b/pkg/lokiunifi/report_ids.go index 63bb4b17..735951c5 100644 --- a/pkg/lokiunifi/report_ids.go +++ b/pkg/lokiunifi/report_ids.go @@ -26,10 +26,10 @@ func (r *Report) IDs(event *unifi.IDS, logs *Logs) { logs.Streams = append(logs.Streams, LogStream{ Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), string(msg)}}, - Labels: CleanLabels(map[string]string{ + Labels: CleanLabels(MergeLabels(map[string]string{ "application": "unifi_ids", "source": event.SourceName, "site_name": event.SiteName, - }), + }, r.ExtraLabels)), }) } diff --git a/pkg/lokiunifi/report_protect.go b/pkg/lokiunifi/report_protect.go index 50ddd673..7a928e64 100644 --- a/pkg/lokiunifi/report_protect.go +++ b/pkg/lokiunifi/report_protect.go @@ -34,14 +34,14 @@ func (r *Report) ProtectLogEvent(event *unifi.ProtectLogEntry, logs *Logs) { // Add event log line logs.Streams = append(logs.Streams, LogStream{ Entries: [][]string{{strconv.FormatInt(event.Datetime().UnixNano(), 10), string(msg)}}, - Labels: CleanLabels(map[string]string{ + 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 @@ -57,12 +57,12 @@ func (r *Report) ProtectLogEvent(event *unifi.ProtectLogEntry, logs *Logs) { // 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(map[string]string{ + Labels: CleanLabels(MergeLabels(map[string]string{ "application": "unifi_protect_thumbnail", "source": event.SourceName, "event_id": event.ID, "camera": event.Camera, - }), + }, r.ExtraLabels)), }) } }