youtubebeat/vendor/github.com/elastic/beats/winlogbeat/beater/eventlogger.go

146 lines
3.6 KiB
Go
Raw Normal View History

2018-11-18 11:08:38 +01:00
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package beater
import (
"time"
"github.com/elastic/beats/libbeat/beat"
"github.com/elastic/beats/libbeat/common"
"github.com/elastic/beats/libbeat/logp"
"github.com/elastic/beats/libbeat/processors"
"github.com/elastic/beats/winlogbeat/checkpoint"
"github.com/elastic/beats/winlogbeat/eventlog"
)
type eventLogger struct {
source eventlog.EventLog
eventMeta common.EventMetadata
processors beat.ProcessorList
}
type eventLoggerConfig struct {
common.EventMetadata `config:",inline"` // Fields and tags to add to events.
Processors processors.PluginConfig `config:"processors"`
}
func newEventLogger(
source eventlog.EventLog,
options *common.Config,
) (*eventLogger, error) {
config := eventLoggerConfig{}
if err := options.Unpack(&config); err != nil {
return nil, err
}
processors, err := processors.New(config.Processors)
if err != nil {
return nil, err
}
return &eventLogger{
source: source,
eventMeta: config.EventMetadata,
processors: processors,
}, nil
}
func (e *eventLogger) connect(pipeline beat.Pipeline) (beat.Client, error) {
api := e.source.Name()
return pipeline.ConnectWith(beat.ClientConfig{
PublishMode: beat.GuaranteedSend,
EventMetadata: e.eventMeta,
Meta: nil, // TODO: configure modules/ES ingest pipeline?
Processor: e.processors,
ACKCount: func(n int) {
addPublished(api, n)
logp.Info("EventLog[%s] successfully published %d events", api, n)
},
})
}
func (e *eventLogger) run(
done <-chan struct{},
pipeline beat.Pipeline,
state checkpoint.EventLogState,
) {
api := e.source
// Initialize per event log metrics.
initMetrics(api.Name())
client, err := e.connect(pipeline)
if err != nil {
logp.Warn("EventLog[%s] Pipeline error. Failed to connect to publisher pipeline",
api.Name())
return
}
// close client on function return or when `done` is triggered (unblock client)
defer client.Close()
go func() {
<-done
client.Close()
}()
err = api.Open(state)
if err != nil {
logp.Warn("EventLog[%s] Open() error. No events will be read from "+
"this source. %v", api.Name(), err)
return
}
defer func() {
logp.Info("EventLog[%s] Stop processing.", api.Name())
if err := api.Close(); err != nil {
logp.Warn("EventLog[%s] Close() error. %v", api.Name(), err)
return
}
}()
debugf("EventLog[%s] opened successfully", api.Name())
for {
select {
case <-done:
return
default:
}
// Read from the event.
records, err := api.Read()
if err != nil {
logp.Warn("EventLog[%s] Read() error: %v", api.Name(), err)
break
}
debugf("EventLog[%s] Read() returned %d records", api.Name(), len(records))
if len(records) == 0 {
// TODO: Consider implementing notifications using
// NotifyChangeEventLog instead of polling.
time.Sleep(time.Second)
continue
}
for _, lr := range records {
client.Publish(lr.ToEvent())
}
}
}