Skip to content

Commit

Permalink
Make experimental api GA (#41770)
Browse files Browse the repository at this point in the history
  • Loading branch information
marc-gr authored Dec 5, 2024
1 parent 15d189d commit c51c8ce
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 48 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,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.

File renamed without changes.
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

0 comments on commit c51c8ce

Please sign in to comment.