Skip to content
Open
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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2023-present Datadog, Inc.

//go:build windows

package evtlog

import (
"fmt"

"github.com/DataDog/datadog-agent/pkg/persistentcache"
evtbookmark "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/bookmark"
)

// persistentCacheSaver implements evtbookmark.Saver using the Agent's persistent cache.
type persistentCacheSaver struct {
key string
}

// newPersistentCacheSaver creates a new persistentCacheSaver with the given cache key.
func newPersistentCacheSaver(key string) evtbookmark.Saver {
return &persistentCacheSaver{key: key}
}

// Save writes the bookmark XML to the persistent cache.
func (s *persistentCacheSaver) Save(bookmarkXML string) error {
err := persistentcache.Write(s.key, bookmarkXML)
if err != nil {
return fmt.Errorf("failed to write bookmark to persistent cache: %w", err)
}
return nil
}

// Load reads the bookmark XML from the persistent cache.
func (s *persistentCacheSaver) Load() (string, error) {
bookmarkXML, err := persistentcache.Read(s.key)
if err != nil {
// persistentcache.Read() does not return error if key does not exist,
// but we'll handle any other errors
return "", fmt.Errorf("failed to read bookmark from persistent cache: %w", err)
}
return bookmarkXML, nil
}
11 changes: 6 additions & 5 deletions comp/checks/windowseventlog/windowseventlogimpl/check/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/DataDog/datadog-agent/pkg/util/option"
evtapi "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/api"
winevtapi "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/api/windows"
evtbookmark "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/bookmark"
evtsession "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/session"
evtsubscribe "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/subscription"

Expand Down Expand Up @@ -67,7 +68,7 @@ type Check struct {
evtapi evtapi.API
systemRenderContext evtapi.EventRenderContextHandle
userRenderContext evtapi.EventRenderContextHandle
bookmarkSaver *bookmarkSaver
bookmarkManager evtbookmark.Manager
publisherMetadataCache publishermetadatacache.Component
}

Expand Down Expand Up @@ -101,7 +102,7 @@ func (c *Check) Run() error {
// if the events read are less than bookmark_frequency then a bookmark won't
// be saved before the process exits. saving here, too, gives us a good time periodic
// save/persist in addition to the count periodic bookmark_frequency option.
err = c.bookmarkSaver.saveLastBookmark()
err = c.bookmarkManager.Save()
if err != nil {
c.Warnf("error saving bookmark: %v", err)
}
Expand All @@ -118,7 +119,7 @@ func (c *Check) fetchEventsLoop(outCh chan<- *evtapi.EventRecord, pipelineWaiter

// Save the bookmark at the end of the loop, regardless of the bookmarkFrequency
defer func() {
err := c.bookmarkSaver.saveLastBookmark()
err := c.bookmarkManager.Save()
if err != nil {
c.Warnf("error saving bookmark: %v", err)
}
Expand Down Expand Up @@ -292,8 +293,8 @@ func (c *Check) Cancel() {
c.session.Close()
}

if c.bookmarkSaver != nil && c.bookmarkSaver.bookmark != nil {
c.bookmarkSaver.bookmark.Close()
if c.bookmarkManager != nil {
c.bookmarkManager.Close()
}

if c.systemRenderContext != evtapi.EventRenderContextHandle(0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ start: now
check, err := s.newCheck(instanceConfig)
require.NoError(s.T(), err)

// Starting from latest, should collect 0 events
s.assertNoEvents(check)

// Get the persistent cache key
cacheKey := check.bookmarkPersistentCacheKey()

Expand Down Expand Up @@ -287,6 +290,9 @@ start: now
require.NoError(s.T(), err)
defer check.Cancel()

// No events in log yet
s.assertNoEvents(check)

// Get the persistent cache key
cacheKey := check.bookmarkPersistentCacheKey()

Expand All @@ -295,10 +301,17 @@ start: now
require.NoError(s.T(), err)
require.NotEmpty(s.T(), bookmarkXML, "Initial bookmark should be persisted even for empty log")

check.Cancel()

// Generate events after bookmark creation
err = s.ti.GenerateEvents(s.eventSource, s.numEvents)
require.NoError(s.T(), err)

// create new check, should resume from bookmark
check2, err := s.newCheck(instanceConfig)
require.NoError(s.T(), err)
defer check2.Cancel()

// Should collect all events since bookmark was at the beginning
s.assertCountEvents(check, s.numEvents)
}
Expand All @@ -319,16 +332,27 @@ start: oldest
require.NoError(s.T(), err)
defer check.Cancel()

// Should collect all pre-existing events
s.assertCountEvents(check, s.numEvents)

// Cancel check to ensure bookmark is created
check.Cancel()

// Get the persistent cache key
cacheKey := check.bookmarkPersistentCacheKey()

// Verify bookmark was created and persisted
bookmarkXML, err := persistentcache.Read(cacheKey)
require.NoError(s.T(), err)
require.NotEmpty(s.T(), bookmarkXML, "Empty bookmark should be persisted for oldest mode")
require.NotEmpty(s.T(), bookmarkXML)

// Should collect all pre-existing events
s.assertCountEvents(check, s.numEvents)
// create new check
check2, err := s.newCheck(instanceConfig)
require.NoError(s.T(), err)
defer check2.Cancel()

// Should resume from bookmark and read 0 events
s.assertNoEvents(check2)
}

// Test initial bookmark with multi-channel queries
Expand All @@ -354,6 +378,9 @@ start: now
check, err := s.newCheck(instanceConfig)
require.NoError(s.T(), err)

// Starting from latest, should collect 0 events
s.assertNoEvents(check)

// Get the persistent cache key
cacheKey := check.bookmarkPersistentCacheKey()

Expand All @@ -380,7 +407,6 @@ start: now

// Test that check's fallback interpret_messages option works
func (s *GetEventsTestSuite) TestGetEventsWithMissingProvider() {

source := "source-does-not-exist"
// Per MSDN: If source is not found then Application log is used
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-registereventsourcew
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
agentEvent "github.com/DataDog/datadog-agent/pkg/metrics/event"
"github.com/DataDog/datadog-agent/pkg/util/log"
evtapi "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/api"
evtbookmark "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/bookmark"
)

// The lower cased version of the `API SOURCE ATTRIBUTE` column from the table located here:
Expand All @@ -24,9 +25,9 @@ const sourceTypeName = "event viewer"

// ddEventSubmitter transforms Windows events into Datadog events and submits them to the sender
type ddEventSubmitter struct {
sender sender.Sender
inCh <-chan *eventWithMessage
bookmarkSaver *bookmarkSaver
sender sender.Sender
inCh <-chan *eventWithMessage
bookmarkManager evtbookmark.Manager

// config
eventPriority agentEvent.Priority
Expand All @@ -44,8 +45,8 @@ func (s *ddEventSubmitter) run(w *sync.WaitGroup) {
for e := range s.inCh {
s.submit(e)

// bookmarkSaver manages whether or not to save/persist the bookmark
err := s.bookmarkSaver.updateBookmark(e.winevent)
// bookmarkManager manages whether or not to save/persist the bookmark
err := s.bookmarkManager.UpdateAndSave(e.winevent.EventRecordHandle)
if err != nil {
log.Warnf("%v", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/DataDog/datadog-agent/pkg/logs/util/windowsevent"
"github.com/DataDog/datadog-agent/pkg/util/log"
evtapi "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/api"
evtbookmark "github.com/DataDog/datadog-agent/pkg/util/winutil/eventlog/bookmark"

"golang.org/x/sys/windows"
)
Expand All @@ -31,7 +32,7 @@ type ddLogSubmitter struct {
doneCh <-chan struct{}
inCh <-chan *eventWithMessage
logsAgent logsAgent.Component
bookmarkSaver *bookmarkSaver
bookmarkManager evtbookmark.Manager
logSource *sources.LogSource
publisherMetadataCache publishermetadatacache.Component
}
Expand All @@ -53,8 +54,8 @@ func (s *ddLogSubmitter) run(w *sync.WaitGroup) {
return
}

// bookmarkSaver manages whether or not to save/persist the bookmark
err = s.bookmarkSaver.updateBookmark(e.winevent)
// bookmarkManager manages whether or not to save/persist the bookmark
err = s.bookmarkManager.UpdateAndSave(e.winevent.EventRecordHandle)
if err != nil {
log.Errorf("%v", err)
}
Expand Down
Loading