Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[winlogbeat] Make experimental api GA #41770

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff]
- Language setting also added to decode xml wineventlog processor {pull}41525[41525]
- Format embedded messages in the experimental api {pull}41525[41525]
- Implement exclusion range support for event_id. {issue}38623[38623] {pull}41639[41639]
- Make the experimental API GA and rename it to winlogbeat-raw {issue}39580[39580] {pull}41770[41770]


*Functionbeat*
Expand Down
4 changes: 2 additions & 2 deletions winlogbeat/_meta/fields.common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
required: true
description: >
The event log API type used to read the record. The possible values are
"wineventlog" for the Windows Event Log API or "wineventlog-experimental" for its
experimental implementation.
"wineventlog" for the Windows Event Log XML reader or "wineventlog-raw" for its
more performant implementation.

- name: activity_id
type: keyword
Expand Down
2 changes: 1 addition & 1 deletion winlogbeat/docs/fields.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -16282,7 +16282,7 @@ All fields specific to the Windows Event Log are defined here.
*`winlog.api`*::
+
--
The event log API type used to read the record. The possible values are "wineventlog" for the Windows Event Log API or "wineventlog-experimental" for its experimental implementation.
The event log API type used to read the record. The possible values are "wineventlog" for the Windows Event Log XML reader or "wineventlog-raw" for its more performant implementation.


required: True
Expand Down
12 changes: 4 additions & 8 deletions winlogbeat/docs/winlogbeat-options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -500,21 +500,17 @@ example of how to read from an `.evtx` file in the <<reading-from-evtx,FAQ>>.
==== `event_logs.api`

This selects the event log reader implementation that is used to read events
from the Windows APIs. You should only set this option when testing experimental
features. When the value is set to `wineventlog-experimental` Winlogbeat will
replace the default event log reader with the **experimental** implementation.
We are evaluating this implementation to see if it can provide increased
performance and reduce CPU usage. *{vista_and_newer}*
from the Windows APIs. When the value is set to `wineventlog-raw` Winlogbeat will
replace the default XML event log reader with a more performant implementation.
*{vista_and_newer}*

[source,yaml]
--------------------------------------------------------------------------------
winlogbeat.event_logs:
- name: ForwardedEvents
api: wineventlog-experimental
api: wineventlog-raw
--------------------------------------------------------------------------------

There are a few notable differences in the events:

* If `include_xml` is `true` the performance will be the same as the default API,
as performance improvements are lost when parsing the XML.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"go.uber.org/multierr"
"golang.org/x/sys/windows"

"github.com/elastic/beats/v7/libbeat/common/cfgwarn"
"github.com/elastic/beats/v7/winlogbeat/checkpoint"
win "github.com/elastic/beats/v7/winlogbeat/sys/wineventlog"
conf "github.com/elastic/elastic-agent-libs/config"
Expand All @@ -39,19 +38,23 @@ const (
// winEventLogExpApiName is the name used to identify the Windows Event Log API
// as both an event type and an API.
winEventLogExpAPIName = "wineventlog-experimental"
// winEventLogRawAPIName is the name used to identify the Windows Event Log API
// as both an event type and an API.
winEventLogRawAPIName = "wineventlog-raw"
)

func init() {
// Register wineventlog API if it is available.
available, _ := win.IsAvailable()
if available {
Register(winEventLogExpAPIName, 10, newWinEventLogExp, win.Channels)
Register(winEventLogExpAPIName, 10, newWinEventLogRaw, win.Channels)
Register(winEventLogRawAPIName, 11, newWinEventLogRaw, win.Channels)
}
}

// winEventLogExp implements the EventLog interface for reading from the Windows
// winEventLogRaw implements the EventLog interface for reading from the Windows
// Event Log API.
type winEventLogExp struct {
type winEventLogRaw struct {
config winEventLogConfig
query string
id string // Identifier of this event log.
Expand All @@ -67,16 +70,14 @@ type winEventLogExp struct {
metrics *inputMetrics
}

// newWinEventLogExp creates and returns a new EventLog for reading event logs
// newWinEventLogRaw creates and returns a new EventLog for reading event logs
// using the Windows Event Log.
func newWinEventLogExp(options *conf.C) (EventLog, error) {
func newWinEventLogRaw(options *conf.C) (EventLog, error) {
var xmlQuery string
var err error
var isFile bool
var log *logp.Logger

cfgwarn.Experimental("The %s event log reader is experimental.", winEventLogExpAPIName)

c := winEventLogConfig{BatchReadSize: 512}
if err := readConfig(options, &c); err != nil {
return nil, err
Expand Down Expand Up @@ -115,7 +116,7 @@ func newWinEventLogExp(options *conf.C) (EventLog, error) {
log = logp.NewLogger("wineventlog").With("id", id).With("channel", c.Name)
}

l := &winEventLogExp{
l := &winEventLogRaw{
config: c,
query: xmlQuery,
id: id,
Expand Down Expand Up @@ -148,27 +149,27 @@ func newWinEventLogExp(options *conf.C) (EventLog, error) {
return l, nil
}

func (l *winEventLogExp) isForwarded() bool {
func (l *winEventLogRaw) isForwarded() bool {
c := l.config
return (c.Forwarded != nil && *c.Forwarded) || (c.Forwarded == nil && c.Name == "ForwardedEvents")
}

// Name returns the name of the event log (i.e. Application, Security, etc.).
func (l *winEventLogExp) Name() string {
func (l *winEventLogRaw) Name() string {
return l.id
}

// Channel returns the event log's channel name.
func (l *winEventLogExp) Channel() string {
func (l *winEventLogRaw) Channel() string {
return l.channelName
}

// IsFile returns true if the event log is an evtx file.
func (l *winEventLogExp) IsFile() bool {
func (l *winEventLogRaw) IsFile() bool {
return l.file
}

func (l *winEventLogExp) Open(state checkpoint.EventLogState) error {
func (l *winEventLogRaw) Open(state checkpoint.EventLogState) error {
l.lastRead = state
// we need to defer metrics initialization since when the event log
// is used from winlog input it would register it twice due to CheckConfig calls
Expand All @@ -185,7 +186,7 @@ func (l *winEventLogExp) Open(state checkpoint.EventLogState) error {
return err
}

func (l *winEventLogExp) open(state checkpoint.EventLogState) (win.EvtHandle, error) {
func (l *winEventLogRaw) open(state checkpoint.EventLogState) (win.EvtHandle, error) {
var bookmark win.Bookmark
if len(state.Bookmark) > 0 {
var err error
Expand All @@ -202,7 +203,7 @@ func (l *winEventLogExp) open(state checkpoint.EventLogState) (win.EvtHandle, er
return l.openChannel(bookmark)
}

func (l *winEventLogExp) openFile(state checkpoint.EventLogState, bookmark win.Bookmark) (win.EvtHandle, error) {
func (l *winEventLogRaw) openFile(state checkpoint.EventLogState, bookmark win.Bookmark) (win.EvtHandle, error) {
path := l.channelName

h, err := win.EvtQuery(0, path, l.query, win.EvtQueryFilePath|win.EvtQueryForwardDirection)
Expand Down Expand Up @@ -239,7 +240,7 @@ func (l *winEventLogExp) openFile(state checkpoint.EventLogState, bookmark win.B
return h, err
}

func (l *winEventLogExp) openChannel(bookmark win.Bookmark) (win.EvtHandle, error) {
func (l *winEventLogRaw) openChannel(bookmark win.Bookmark) (win.EvtHandle, error) {
// Using a pull subscription to receive events. See:
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa385771(v=vs.85).aspx#pull
signalEvent, err := windows.CreateEvent(nil, 0, 0, nil)
Expand Down Expand Up @@ -281,7 +282,7 @@ func (l *winEventLogExp) openChannel(bookmark win.Bookmark) (win.EvtHandle, erro
}
}

func (l *winEventLogExp) Read() ([]Record, error) {
func (l *winEventLogRaw) Read() ([]Record, error) {
//nolint:prealloc // Avoid unnecessary preallocation for each reader every second when event log is inactive.
var records []Record
defer func() {
Expand Down Expand Up @@ -319,7 +320,7 @@ func (l *winEventLogExp) Read() ([]Record, error) {
return records, nil
}

func (l *winEventLogExp) processHandle(h win.EvtHandle) (*Record, error) {
func (l *winEventLogRaw) processHandle(h win.EvtHandle) (*Record, error) {
defer h.Close()

// NOTE: Render can return an error and a partial event.
Expand Down Expand Up @@ -357,7 +358,7 @@ func (l *winEventLogExp) processHandle(h win.EvtHandle) (*Record, error) {
return r, nil
}

func (l *winEventLogExp) createBookmarkFromEvent(evtHandle win.EvtHandle) (string, error) {
func (l *winEventLogRaw) createBookmarkFromEvent(evtHandle win.EvtHandle) (string, error) {
bookmark, err := win.NewBookmarkFromEvent(evtHandle)
if err != nil {
return "", fmt.Errorf("failed to create new bookmark from event handle: %w", err)
Expand All @@ -367,18 +368,18 @@ func (l *winEventLogExp) createBookmarkFromEvent(evtHandle win.EvtHandle) (strin
return bookmark.XML()
}

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

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

func (l *winEventLogExp) close() error {
func (l *winEventLogRaw) close() error {
if l.iterator == nil {
return l.renderer.Close()
}
Expand Down
12 changes: 6 additions & 6 deletions winlogbeat/eventlog/wineventlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,11 @@ func TestWindowsEventLogAPI(t *testing.T) {
testWindowsEventLog(t, winEventLogAPIName, false)
}

func TestWindowsEventLogAPIExperimental(t *testing.T) {
// for the experimental api using include xml behave differently than not
func TestWindowsEventLogAPIRaw(t *testing.T) {
// for the raw api using include xml behave differently than not
// so we must test both settings
testWindowsEventLog(t, winEventLogExpAPIName, true)
testWindowsEventLog(t, winEventLogExpAPIName, false)
testWindowsEventLog(t, winEventLogRawAPIName, true)
testWindowsEventLog(t, winEventLogRawAPIName, false)
}

func testWindowsEventLog(t *testing.T, api string, includeXML bool) {
Expand Down Expand Up @@ -407,8 +407,8 @@ func openLog(t testing.TB, api string, state *checkpoint.EventLogState, config m
switch api {
case winEventLogAPIName:
log, err = newWinEventLog(cfg)
case winEventLogExpAPIName:
log, err = newWinEventLogExp(cfg)
case winEventLogRawAPIName:
log, err = newWinEventLogRaw(cfg)
default:
t.Fatalf("Unknown API name: '%s'", api)
}
Expand Down
2 changes: 1 addition & 1 deletion winlogbeat/include/fields.go

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions winlogbeat/sys/wineventlog/wineventlog_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ func TestWinEventLog(t *testing.T) {
}{
{path: "application-windows-error-reporting.evtx", events: 1},
{path: "sysmon-9.01.evtx", events: 32},
{path: "ec1.evtx", events: 1}, // eventcreate /id 1000 /t error /l application /d "My custom error event for the application log"
{path: "ec2.evtx", events: 1}, // eventcreate /id 999 /t error /l application /so WinWord /d "Winword event 999 happened due to low diskspace"
{path: "ec3.evtx", events: 1}, // eventcreate /id 5 /t error /l system /d "Catastrophe!"
{path: "ec4.evtx", events: 1}, // eventcreate /id 5 /t error /l system /so Backup /d "Backup failure"
{path: "ec3and4.evtx", events: 2}, // ec3 and ec3 exported as a single evtx.
{path: "original.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPI test.
{path: "experimental.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPIExperimental test.
{path: "ec1.evtx", events: 1}, // eventcreate /id 1000 /t error /l application /d "My custom error event for the application log"
{path: "ec2.evtx", events: 1}, // eventcreate /id 999 /t error /l application /so WinWord /d "Winword event 999 happened due to low diskspace"
{path: "ec3.evtx", events: 1}, // eventcreate /id 5 /t error /l system /d "Catastrophe!"
{path: "ec4.evtx", events: 1}, // eventcreate /id 5 /t error /l system /so Backup /d "Backup failure"
{path: "ec3and4.evtx", events: 2}, // ec3 and ec3 exported as a single evtx.
{path: "original.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPI test.
{path: "raw.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPIRaw test.
} {
t.Run(test.path, func(t *testing.T) {
evtx, err := filepath.Abs(filepath.Join("testdata", test.path))
Expand Down
Loading