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: Use bookmarks to persist last published event #6150

Merged
merged 9 commits into from
Jan 30, 2018

Conversation

adriansr
Copy link
Contributor

When using the Windows Event Log API, a bookmark is used to persist the
last position read in the stream. This is a first step to support XML
queries potentially involving multiple channels (#1054). Also fixes a problem
when using Forwarded Events (#3731).


// CreateBookmarkFromEvent creates a new handle to a bookmark. Close must be called on
// returned EvtHandle when finished with the handle.
func CreateBookmarkFromXml(bookmarkXml string) (EvtHandle, error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func CreateBookmarkFromXml should be CreateBookmarkFromXML
func parameter bookmarkXml should be bookmarkXML

return h, nil
}

// CreateBookmarkFromEvent creates a new handle to a bookmark. Close must be called on

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment on exported function CreateBookmarkFromXml should be of the form "CreateBookmarkFromXml ..."

// CreateBookmarkFromXml creates a new bookmark from the serialised representation
// of an existing bookmark. Close must be called on returned EvtHandle when
// finished with the handle.
func CreateBookmarkFromXml(bookmarkXml string) (EvtHandle, error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func CreateBookmarkFromXml should be CreateBookmarkFromXML
func parameter bookmarkXml should be bookmarkXML

// CreateBookmarkFromXml creates a new bookmark from the serialised representation
// of an existing bookmark. Close must be called on returned EvtHandle when
// finished with the handle.
func CreateBookmarkFromXml(bookmarkXml string) (EvtHandle, error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func CreateBookmarkFromXml should be CreateBookmarkFromXML
func parameter bookmarkXml should be bookmarkXML

@adriansr
Copy link
Contributor Author

Jenkins, test it and not fail this time please

@adriansr adriansr removed the in progress Pull request is currently in progress. label Jan 24, 2018
Copy link
Member

@andrewkroh andrewkroh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. There are some registry tests that should be updated too.

@@ -41,7 +41,7 @@ type EventLog interface {
// Open the event log. recordNumber is the last successfully read event log
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The godocs should be updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -9,6 +9,8 @@ import (

"github.com/joeshaw/multierror"

"github.com/elastic/beats/winlogbeat/checkpoint"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be added to the group below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

var bookmark win.EvtHandle
var err error
if len(state.Bookmark) > 0 {
bookmark, err = win.CreateBookmarkFromXML(state.Bookmark)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing an error check. Looks like you intended to move the error check below outside the if/else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

RecordNumber: r.RecordID,
Timestamp: r.TimeCreated.SystemTime,
}
if r.Offset.Bookmark, err = l.createBookmarkFromEvent(h); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea as to the impact of calling this for every event? Could you run these benchmarks and share the before and after results.

Copy link
Contributor Author

@adriansr adriansr Jan 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did run some tests at first and method was taking less than 1ms to complete. However, I also found out that every event was persisted so it was necessary to always create a bookmark anyway. Maybe there was something wrong in my configuration, a side-effect of running with -N.

The benchmark results:

Before:

=== RUN   TestBenchmarkBatchReadSize
--- PASS: TestBenchmarkBatchReadSize (74.86s)
        bench_test.go:80: batch_size=10, total_events=50000, batch_time=3.543758ms, events_per_sec=2821.863118192608, bytes_alloced_per_event=14 kB, total_allocs=12330717
        bench_test.go:80: batch_size=100, total_events=50000, batch_time=33.800801ms, events_per_sec=2958.509770227043, bytes_alloced_per_event=14 kB, total_allocs=12260220
        bench_test.go:80: batch_size=500, total_events=50000, batch_time=169.47269ms, events_per_sec=2950.32786698553, bytes_alloced_per_event=14 kB, total_allocs=12252311
        bench_test.go:80: batch_size=1000, total_events=50000, batch_time=333.476478ms, events_per_sec=2998.7122510032027, bytes_alloced_per_event=14 kB, total_allocs=12251057
PASS
ok      github.com/elastic/beats/winlogbeat/eventlog    74.900s

After:

=== RUN   TestBenchmarkBatchReadSize
--- PASS: TestBenchmarkBatchReadSize (77.18s)
        bench_test.go:80: batch_size=10, total_events=50000, batch_time=3.655664ms, events_per_sec=2735.4811601941537, bytes_alloced_per_event=14 kB, total_allocs=12430766
        bench_test.go:80: batch_size=100, total_events=50000, batch_time=34.74005ms, events_per_sec=2878.522051637807, bytes_alloced_per_event=14 kB, total_allocs=12360267
        bench_test.go:80: batch_size=500, total_events=50000, batch_time=173.232487ms, events_per_sec=2886.294647492996, bytes_alloced_per_event=14 kB, total_allocs=12352376
        bench_test.go:80: batch_size=1000, total_events=50000, batch_time=343.0666ms, events_per_sec=2914.885914280201, bytes_alloced_per_event=14 kB, total_allocs=12351096
PASS
ok      github.com/elastic/beats/winlogbeat/eventlog    77.221s

@@ -197,9 +197,9 @@ func RenderEvent(
// include the RenderingInfo (message). If the event is not rendered then the
// XML will not include the message, and in this case RenderEvent should be
// used.
func RenderEventXML(eventHandle EvtHandle, renderBuf []byte, out io.Writer) error {
func RenderEventXML(eventHandle EvtHandle, flag EvtRenderFlag, renderBuf []byte, out io.Writer) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function name is no longer fully reflective of the usage because it can render both events and bookmarks based on the flag. I suggest renaming it to be more general such as RenderXML or create RenderEventXML and RenderBookmarkXML and have them call this function (with it being renamed to something like renderXML).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -12,6 +12,8 @@ import (
"github.com/pkg/errors"
"golang.org/x/sys/windows"

"github.com/elastic/beats/winlogbeat/checkpoint"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Group this import with the other elastic imports.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -45,6 +45,7 @@ type EventLogState struct {
Name string `yaml:"name"`
RecordNumber uint64 `yaml:"record_number"`
Timestamp time.Time `yaml:"timestamp"`
Bookmark string `yaml:"bookmark"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is optional for the eventlog API add ,omitempty to the yaml tag.

update_time: 2018-01-24T16:05:31.2972263Z
event_logs:
- name: WinlogbeatTestPython
  record_number: 37134
  timestamp: 2018-01-24T16:05:30Z
  bookmark: ""

source

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@andrewkroh
Copy link
Member

There doesn't appear to be any existing test that verifies Winlogbeat resumes from the position specified in the registry. I think this would be a good test to add. Something like

  • write an event to the log
  • run WLB
  • stop WLB after the event is read
  • write more events to the log
  • run WLB
  • assert that the first event has the correct record number

When using the Windows Event Log API, a bookmark is used to persist the
last position read in the stream. This is a first step to support XML
queries (potentially involving multiple channels). Also fixes a problem
when using Forwarded Events.
The hostname reported by beats is fully-qualified wheter platform.node()
might only include the host name.
Copy link
Member

@andrewkroh andrewkroh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Can you please add a CHANGLOG entry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants