Files
unpoller_unpoller/pkg/lokiunifi/report.go
T
Cody LeeandClaude Sonnet 4.6 2f1e28c7d3 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>
2026-03-23 21:10:52 -05:00

112 lines
2.9 KiB
Go

package lokiunifi
import (
"fmt"
"strings"
"time"
"github.com/unpoller/unifi/v5"
"github.com/unpoller/unpoller/pkg/poller"
)
// LogStream contains a stream of logs (like a log file).
// This app uses one stream per log entry because each log may have different labels.
type LogStream struct {
Labels map[string]string `json:"stream"` // "the file name"
Entries [][]string `json:"values"` // "the log lines"
}
// Logs is the main logs-holding structure. This is the Loki-output format.
type Logs struct {
Streams []LogStream `json:"streams"` // "multiple files"
}
// Report is the temporary data generated by processing events.
type Report struct {
Start time.Time
Oldest time.Time
Collect poller.Collect
ExtraLabels map[string]string
poller.Logger
Counts map[string]int
}
// NewReport makes a new report.
func (l *Loki) NewReport(start time.Time) *Report {
return &Report{
Start: start,
Oldest: l.last,
Collect: l.Collect,
ExtraLabels: l.ExtraLabels,
Logger: l,
Counts: make(map[string]int),
}
}
// ProcessEventLogs loops the event Logs, matches the interface type, calls the
// appropriate method for the data, and compiles the Logs into a Loki format.
// This runs once per interval, if there was no collection error.
func (r *Report) ProcessEventLogs(events *poller.Events) *Logs {
logs := &Logs{}
for _, e := range events.Logs {
switch event := e.(type) {
case *unifi.IDS:
r.IDs(event, logs)
case *unifi.Event:
r.Event(event, logs)
case *unifi.Alarm:
r.Alarm(event, logs)
case *unifi.Anomaly:
r.Anomaly(event, logs)
case *unifi.SystemLogEntry:
r.SystemLogEvent(event, logs)
case *unifi.ProtectLogEntry:
r.ProtectLogEvent(event, logs)
default: // unlikely.
if r.Collect != nil && r.Collect.Poller().LogUnknownTypes {
r.LogDebugf("unknown event type: %T", e)
}
}
}
return logs
}
func (r *Report) String() string {
s := fmt.Sprintf("%s: %d, %s: %d, %s: %d, %s: %d, %s: %d, %s: %d",
typeEvent, r.Counts[typeEvent], typeIDs, r.Counts[typeIDs],
typeAlarm, r.Counts[typeAlarm], typeAnomaly, r.Counts[typeAnomaly],
typeSystemLog, r.Counts[typeSystemLog], typeProtectLog, r.Counts[typeProtectLog])
if r.Counts[typeProtectThumbnail] > 0 {
s += fmt.Sprintf(" (thumbs: %d)", r.Counts[typeProtectThumbnail])
}
s += fmt.Sprintf(", Dur: %v", time.Since(r.Start).Round(time.Millisecond))
return s
}
// CleanLabels removes any tag that is empty.
func CleanLabels(labels map[string]string) map[string]string {
for i := range labels {
if strings.TrimSpace(labels[i]) == "" {
delete(labels, i)
}
}
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
}