move some more bits around
This commit is contained in:
		
							parent
							
								
									6ab0da0cf6
								
							
						
					
					
						commit
						7ac82f6e9c
					
				|  | @ -1,6 +1,7 @@ | ||||||
| package lokiunifi | package lokiunifi | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"io/ioutil" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | @ -10,7 +11,7 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	maxInterval     = time.Hour | 	maxInterval     = 10 * time.Minute | ||||||
| 	minInterval     = 10 * time.Second | 	minInterval     = 10 * time.Second | ||||||
| 	defaultTimeout  = 10 * time.Second | 	defaultTimeout  = 10 * time.Second | ||||||
| 	defaultInterval = 2 * time.Minute | 	defaultInterval = 2 * time.Minute | ||||||
|  | @ -20,7 +21,7 @@ const ( | ||||||
| 	// InputName is the name of plugin that gives us data.
 | 	// InputName is the name of plugin that gives us data.
 | ||||||
| 	InputName = "unifi" | 	InputName = "unifi" | ||||||
| 	// PluginName is the name of this plugin.
 | 	// PluginName is the name of this plugin.
 | ||||||
| 	PluginName = "loki" | 	PluginName = "Loki" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Config is the plugin's input data.
 | // Config is the plugin's input data.
 | ||||||
|  | @ -81,6 +82,15 @@ func (l *Loki) ValidateConfig() { | ||||||
| 		l.Interval.Duration = minInterval | 		l.Interval.Duration = minInterval | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if strings.HasPrefix(l.Password, "file://") { | ||||||
|  | 		pass, err := ioutil.ReadFile(strings.TrimPrefix(l.Password, "file://")) | ||||||
|  | 		if err != nil { | ||||||
|  | 			l.LogErrorf("Reading Loki Password File: %v", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		l.Password = strings.TrimSpace(string(pass)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	l.last = time.Now().Add(-l.Interval.Duration) | 	l.last = time.Now().Add(-l.Interval.Duration) | ||||||
| 	l.client = l.httpClient() | 	l.client = l.httpClient() | ||||||
| 	l.URL = strings.TrimRight(l.URL, "/") // gets a path appended to it later.
 | 	l.URL = strings.TrimRight(l.URL, "/") // gets a path appended to it later.
 | ||||||
|  | @ -100,7 +110,7 @@ func (l *Loki) PollController() { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		err = l.ProcessEvents(l.NewReport(), events, start) | 		err = l.ProcessEvents(l.NewReport(start), events) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			l.LogErrorf("%v", err) | 			l.LogErrorf("%v", err) | ||||||
| 		} | 		} | ||||||
|  | @ -108,20 +118,19 @@ func (l *Loki) PollController() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ProcessEvents offloads some of the loop from PollController.
 | // ProcessEvents offloads some of the loop from PollController.
 | ||||||
| func (l *Loki) ProcessEvents(report *Report, events *poller.Events, start time.Time) error { | func (l *Loki) ProcessEvents(report *Report, events *poller.Events) error { | ||||||
| 	// Sometimes it gets stuck on old messages. This gets it past that.
 | 	// Sometimes it gets stuck on old messages. This gets it past that.
 | ||||||
| 	if time.Since(l.last) > 4*l.Interval.Duration { | 	if time.Since(l.last) > 4*l.Interval.Duration { | ||||||
| 		l.last = time.Now().Add(-4 * l.Interval.Duration) | 		l.last = time.Now().Add(-4 * l.Interval.Duration) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	report.ProcessEventLogs(events) | 	logs := report.ProcessEventLogs(events) | ||||||
| 
 | 	if err := l.client.Post(logs); err != nil { | ||||||
| 	if err := l.client.Post(report.Logs); err != nil { |  | ||||||
| 		return errors.Wrap(err, "sending to Loki failed") | 		return errors.Wrap(err, "sending to Loki failed") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	l.last = start | 	l.last = report.Start | ||||||
| 	report.LogOutput(l.last) | 	l.Logf("Events sent to Loki. %v", report) | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| package lokiunifi | package lokiunifi | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | @ -15,51 +16,58 @@ type LogStream struct { | ||||||
| 	Entries [][]string        `json:"values"` // "the log lines"
 | 	Entries [][]string        `json:"values"` // "the log lines"
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Logs is the main logs-holding structure.
 | // Logs is the main logs-holding structure. This is the Loki-output format.
 | ||||||
| type Logs struct { | type Logs struct { | ||||||
| 	Streams []LogStream `json:"streams"` // "multiple files"
 | 	Streams []LogStream `json:"streams"` // "multiple files"
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Report is the temporary data generated and sent to Loki at every interval.
 | // Report is the temporary data generated by processing events.
 | ||||||
| type Report struct { | type Report struct { | ||||||
| 	Logs |  | ||||||
| 	Counts map[string]int | 	Counts map[string]int | ||||||
| 	Oldest time.Time | 	Oldest time.Time | ||||||
|  | 	Start  time.Time | ||||||
| 	poller.Logger | 	poller.Logger | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewReport makes a new report.
 | // NewReport makes a new report.
 | ||||||
| func (l *Loki) NewReport() *Report { | func (l *Loki) NewReport(start time.Time) *Report { | ||||||
| 	return &Report{ | 	return &Report{ | ||||||
| 		Logger: l.Collect, | 		Counts: make(map[string]int), | ||||||
| 		Oldest: l.last, | 		Oldest: l.last, | ||||||
|  | 		Start:  start, | ||||||
|  | 		Logger: l.Collect, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r *Report) LogOutput(start time.Time) { | // ProcessEventLogs loops the event Logs, matches the interface type, calls the
 | ||||||
| 	r.Logf("Events sent to Loki. Event: %d, IDS: %d, Alarm: %d, Anomaly: %d, Dur: %v", | // appropriate method for the data, and compiles the Logs into a Loki format.
 | ||||||
| 		r.Counts[typeEvent], r.Counts[typeIDS], r.Counts[typeAlarm], r.Counts[typeAnomaly], |  | ||||||
| 		time.Since(start).Round(time.Millisecond)) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // ProcessEventLogs loops the event Logs, matches the interface
 |  | ||||||
| // type, calls the appropriate method for the data, and compiles the report.
 |  | ||||||
| // This runs once per interval, if there was no collection error.
 | // This runs once per interval, if there was no collection error.
 | ||||||
| func (r *Report) ProcessEventLogs(events *poller.Events) { | func (r *Report) ProcessEventLogs(events *poller.Events) *Logs { | ||||||
|  | 	logs := &Logs{} | ||||||
|  | 
 | ||||||
| 	for _, e := range events.Logs { | 	for _, e := range events.Logs { | ||||||
| 		switch event := e.(type) { | 		switch event := e.(type) { | ||||||
| 		case *unifi.IDS: | 		case *unifi.IDS: | ||||||
| 			r.IDS(event) | 			r.IDS(event, logs) | ||||||
| 		case *unifi.Event: | 		case *unifi.Event: | ||||||
| 			r.Event(event) | 			r.Event(event, logs) | ||||||
| 		case *unifi.Alarm: | 		case *unifi.Alarm: | ||||||
| 			r.Alarm(event) | 			r.Alarm(event, logs) | ||||||
| 		case *unifi.Anomaly: | 		case *unifi.Anomaly: | ||||||
| 			r.Anomaly(event) | 			r.Anomaly(event, logs) | ||||||
| 		default: // unlikely.
 | 		default: // unlikely.
 | ||||||
| 			r.LogErrorf("unknown event type: %T", e) | 			r.LogErrorf("unknown event type: %T", e) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	return logs | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (r *Report) String() string { | ||||||
|  | 	return fmt.Sprintf("%s: %d, %s: %d, %s: %d, %s: %d, Dur: %v", | ||||||
|  | 		typeEvent, r.Counts[typeEvent], typeIDS, r.Counts[typeIDS], | ||||||
|  | 		typeAlarm, r.Counts[typeAlarm], typeAnomaly, r.Counts[typeAnomaly], | ||||||
|  | 		time.Since(r.Start).Round(time.Millisecond)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CleanLabels removes any tag that is empty.
 | // CleanLabels removes any tag that is empty.
 | ||||||
|  |  | ||||||
|  | @ -6,16 +6,17 @@ import ( | ||||||
| 	"github.com/unifi-poller/unifi" | 	"github.com/unifi-poller/unifi" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const typeAlarm = "alarm" | const typeAlarm = "Alarm" | ||||||
| 
 | 
 | ||||||
| // Alarm stores a structured Alarm for batch sending to Loki.
 | // Alarm stores a structured Alarm for batch sending to Loki.
 | ||||||
| func (r *Report) Alarm(event *unifi.Alarm) { | func (r *Report) Alarm(event *unifi.Alarm, logs *Logs) { | ||||||
| 	if event.Datetime.Before(r.Oldest) { | 	if event.Datetime.Before(r.Oldest) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	r.Counts[typeAlarm]++ // increase counter and append new log line.
 | 	r.Counts[typeAlarm]++ // increase counter and append new log line.
 | ||||||
| 	r.Streams = append(r.Streams, LogStream{ | 
 | ||||||
|  | 	logs.Streams = append(logs.Streams, LogStream{ | ||||||
| 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}}, | 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}}, | ||||||
| 		Labels: CleanLabels(map[string]string{ | 		Labels: CleanLabels(map[string]string{ | ||||||
| 			"application":  "unifi_alarm", | 			"application":  "unifi_alarm", | ||||||
|  |  | ||||||
|  | @ -6,16 +6,17 @@ import ( | ||||||
| 	"github.com/unifi-poller/unifi" | 	"github.com/unifi-poller/unifi" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const typeAnomaly = "anomaly" | const typeAnomaly = "Anomaly" | ||||||
| 
 | 
 | ||||||
| // Anomaly stores a structured Anomaly for batch sending to Loki.
 | // Anomaly stores a structured Anomaly for batch sending to Loki.
 | ||||||
| func (r *Report) Anomaly(event *unifi.Anomaly) { | func (r *Report) Anomaly(event *unifi.Anomaly, logs *Logs) { | ||||||
| 	if event.Datetime.Before(r.Oldest) { | 	if event.Datetime.Before(r.Oldest) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	r.Counts[typeAnomaly]++ // increase counter and append new log line.
 | 	r.Counts[typeAnomaly]++ // increase counter and append new log line.
 | ||||||
| 	r.Streams = append(r.Streams, LogStream{ | 
 | ||||||
|  | 	logs.Streams = append(logs.Streams, LogStream{ | ||||||
| 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Anomaly}}, | 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Anomaly}}, | ||||||
| 		Labels: CleanLabels(map[string]string{ | 		Labels: CleanLabels(map[string]string{ | ||||||
| 			"application": "unifi_anomaly", | 			"application": "unifi_anomaly", | ||||||
|  |  | ||||||
|  | @ -6,16 +6,17 @@ import ( | ||||||
| 	"github.com/unifi-poller/unifi" | 	"github.com/unifi-poller/unifi" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const typeEvent = "event" | const typeEvent = "Event" | ||||||
| 
 | 
 | ||||||
| // Event stores a structured UniFi Event for batch sending to Loki.
 | // Event stores a structured UniFi Event for batch sending to Loki.
 | ||||||
| func (r *Report) Event(event *unifi.Event) { | func (r *Report) Event(event *unifi.Event, logs *Logs) { | ||||||
| 	if event.Datetime.Before(r.Oldest) { | 	if event.Datetime.Before(r.Oldest) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	r.Counts[typeEvent]++ // increase counter and append new log line.
 | 	r.Counts[typeEvent]++ // increase counter and append new log line.
 | ||||||
| 	r.Streams = append(r.Streams, LogStream{ | 
 | ||||||
|  | 	logs.Streams = append(logs.Streams, LogStream{ | ||||||
| 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}}, | 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}}, | ||||||
| 		Labels: CleanLabels(map[string]string{ | 		Labels: CleanLabels(map[string]string{ | ||||||
| 			"application":  "unifi_event", | 			"application":  "unifi_event", | ||||||
|  |  | ||||||
|  | @ -6,16 +6,17 @@ import ( | ||||||
| 	"github.com/unifi-poller/unifi" | 	"github.com/unifi-poller/unifi" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const typeIDS = "ids" | const typeIDS = "IDS" | ||||||
| 
 | 
 | ||||||
| // event stores a structured event Event for batch sending to Loki.
 | // event stores a structured event Event for batch sending to Loki.
 | ||||||
| func (r *Report) IDS(event *unifi.IDS) { | func (r *Report) IDS(event *unifi.IDS, logs *Logs) { | ||||||
| 	if event.Datetime.Before(r.Oldest) { | 	if event.Datetime.Before(r.Oldest) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	r.Counts[typeIDS]++ // increase counter and append new log line.
 | 	r.Counts[typeIDS]++ // increase counter and append new log line.
 | ||||||
| 	r.Streams = append(r.Streams, LogStream{ | 
 | ||||||
|  | 	logs.Streams = append(logs.Streams, LogStream{ | ||||||
| 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}}, | 		Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}}, | ||||||
| 		Labels: CleanLabels(map[string]string{ | 		Labels: CleanLabels(map[string]string{ | ||||||
| 			"application":  "unifi_ids", | 			"application":  "unifi_ids", | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue