146 lines
3.6 KiB
Go
146 lines
3.6 KiB
Go
|
// 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())
|
||
|
}
|
||
|
}
|
||
|
}
|