Skip to content

Commit

Permalink
winlogbeat/eventlog: ensure event loggers retain metric collection wh…
Browse files Browse the repository at this point in the history
…en handling recoverable errors (#36483)

When winlogbeat's event loggers encounter recoverable errors they handle
this by closing and reopening the channel. This causes the metric
collection for the beat and dependent winlog filebeat input to lose
metric collection as metric registration only occurs on configuration.
So add a soft-close method, Reset, that only closes the channel and
leaves the event logger valid, leaving the metrics in tact, and use this
for recovering from errors.
  • Loading branch information
efd6 authored Sep 5, 2023
1 parent ffae391 commit edc7321
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff]
- Fix panic when redact option is not provided to CEL input. {issue}36387[36387] {pull}36388[36388]
- Remove 'onFilteredOut' and 'onDroppedOnPublish' callback logs {issue}36299[36299] {pull}36399[36399]
- Added a fix for Crowdstrike pipeline handling process arrays {pull}36496[36496]
- Ensure winlog input retains metric collection when handling recoverable errors. {issue}36479[36479] {pull}36483[36483]

*Heartbeat*

Expand Down Expand Up @@ -139,6 +140,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff]

*Winlogbeat*

- Ensure event loggers retains metric collection when handling recoverable errors. {issue}36479[36479] {pull}36483[36483]

*Elastic Logging Plugin*

Expand Down
8 changes: 4 additions & 4 deletions filebeat/input/winlog/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ runLoop:
records, err := api.Read()
if eventlog.IsRecoverable(err) {
log.Errorw("Encountered recoverable error when reading from Windows Event Log", "error", err)
if closeErr := api.Close(); closeErr != nil {
log.Errorw("Error closing Windows Event Log handle", "error", closeErr)
if resetErr := api.Reset(); resetErr != nil {
log.Errorw("Error resetting Windows Event Log handle", "error", resetErr)
}
continue runLoop
}
if !api.IsFile() && eventlog.IsChannelNotFound(err) {
log.Errorw("Encountered channel not found error when reading from Windows Event Log", "error", err)
if closeErr := api.Close(); closeErr != nil {
log.Errorw("Error closing Windows Event Log handle", "error", closeErr)
if resetErr := api.Reset(); resetErr != nil {
log.Errorw("Error resetting Windows Event Log handle", "error", resetErr)
}
continue runLoop
}
Expand Down
8 changes: 4 additions & 4 deletions winlogbeat/beater/eventlogger.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,15 @@ runLoop:
records, err := api.Read()
if eventlog.IsRecoverable(err) {
e.log.Warnw("Read() encountered recoverable error. Reopening handle...", "error", err, "channel", api.Channel())
if closeErr := api.Close(); closeErr != nil {
e.log.Warnw("Close() error.", "error", err)
if resetErr := api.Reset(); resetErr != nil {
e.log.Warnw("Reset() error.", "error", err)
}
continue runLoop
}
if !api.IsFile() && eventlog.IsChannelNotFound(err) {
e.log.Warnw("Read() encountered channel not found error for channel %q. Reopening handle...", "error", err, "channel", api.Channel())
if closeErr := api.Close(); closeErr != nil {
e.log.Warnw("Close() error.", "error", err)
if resetErr := api.Reset(); resetErr != nil {
e.log.Warnw("Reset() error.", "error", err)
}
continue runLoop
}
Expand Down
5 changes: 5 additions & 0 deletions winlogbeat/eventlog/eventlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ type EventLog interface {
// reading and close the log.
Read() ([]Record, error)

// Reset closes the event log channel to allow recovering from recoverable
// errors. Open must be successfully called after a Reset before Read may
// be called.
Reset() error

// Close the event log. It should not be re-opened after closing.
Close() error

Expand Down
5 changes: 5 additions & 0 deletions winlogbeat/eventlog/wineventlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,11 @@ func (l *winEventLog) createBookmarkFromEvent(evtHandle win.EvtHandle) (string,
return string(l.outputBuf.Bytes()), err
}

func (l *winEventLog) Reset() error {
debugf("%s Closing handle for reset", l.logPrefix)
return win.Close(l.subscription)
}

func (l *winEventLog) Close() error {
debugf("%s Closing handle", l.logPrefix)
l.metrics.close()
Expand Down
9 changes: 9 additions & 0 deletions winlogbeat/eventlog/wineventlog_experimental.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,18 @@ func (l *winEventLogExp) createBookmarkFromEvent(evtHandle win.EvtHandle) (strin
return bookmark.XML()
}

func (l *winEventLogExp) Reset() error {
l.log.Debug("Closing event log reader handles for reset.")
return l.close()
}

func (l *winEventLogExp) Close() error {
l.log.Debug("Closing event log reader handles.")
l.metrics.close()
return l.close()
}

func (l *winEventLogExp) close() error {
if l.iterator == nil {
return l.renderer.Close()
}
Expand Down

0 comments on commit edc7321

Please sign in to comment.