From c0fc105e8cbbe53950bf89675b06853d0d5b27db Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Fri, 29 Jan 2016 17:46:08 -0500 Subject: [PATCH] Add caching of event metadata handles and the system render context for wineventlog API --- CHANGELOG.asciidoc | 7 +--- winlogbeat/eventlog/wineventlog.go | 32 +++++++++++++++++-- .../sys/wineventlog/wineventlog_windows.go | 20 ++++++++++-- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index c922e05b5f9d..989dccdaf70c 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -68,13 +68,8 @@ https://github.com/elastic/beats/compare/v1.1.0...master[Check the HEAD diff] - Add close_older configuration option to complete ignore_older https://github.com/elastic/filebeat/issues/181[181] - Add experimental option to enable filebeat publisher pipeline to operate asynchonrously {pull}782[782] -*Packetbeat* - -*Topbeat* - -*Filebeat* - *Winlogbeat* +- Add caching of event metadata handles and the system render context for the wineventlog API {pull}888[888] ==== Deprecated diff --git a/winlogbeat/eventlog/wineventlog.go b/winlogbeat/eventlog/wineventlog.go index 1fd99929c3b4..592140f79fb9 100644 --- a/winlogbeat/eventlog/wineventlog.go +++ b/winlogbeat/eventlog/wineventlog.go @@ -6,13 +6,14 @@ import ( "fmt" "github.com/elastic/beats/libbeat/logp" + "github.com/elastic/beats/winlogbeat/sys/eventlogging" sys "github.com/elastic/beats/winlogbeat/sys/wineventlog" "golang.org/x/sys/windows" ) const ( // defaultMaxNumRead is the maximum number of event Read will return. - defaultMaxNumRead = 50 + defaultMaxNumRead = 100 // renderBufferSize is the size in bytes of the buffer used to render events. renderBufferSize = 1 << 14 @@ -33,7 +34,9 @@ type winEventLog struct { subscription sys.EvtHandle // Handle to the subscription. maxRead int // Maximum number returned in one Read. - renderBuf []byte // Buffer used for rendering event. + renderBuf []byte // Buffer used for rendering event. + systemCtx sys.EvtHandle // System render context. + cache *messageFilesCache // Cached mapping of source name to event message file handles. logPrefix string // String to prefix on log messages. } @@ -91,7 +94,7 @@ func (l *winEventLog) Read() ([]Record, error) { var records []Record for _, h := range handles { - e, err := sys.RenderEvent(h, 0, 0, l.renderBuf, nil) + e, err := sys.RenderEvent(h, l.systemCtx, 0, l.renderBuf, l.cache.get) if err != nil { logp.Err("%s Dropping event with rendering error. %v", l.logPrefix, err) continue @@ -138,11 +141,34 @@ func (l *winEventLog) Close() error { // newWinEventLog creates and returns a new EventLog for reading event logs // using the Windows Event Log. func newWinEventLog(c Config) (EventLog, error) { + eventMetadataHandle := func(providerName, sourceName string) eventlogging.MessageFiles { + mf := eventlogging.MessageFiles{SourceName: sourceName} + h, err := sys.OpenPublisherMetadata(0, providerName, 0) + if err != nil { + mf.Err = err + return mf + } + + mf.Handles = []eventlogging.FileHandle{eventlogging.FileHandle{Handle: uintptr(h)}} + return mf + } + + freeHandle := func(handle uintptr) error { + return sys.Close(sys.EvtHandle(handle)) + } + + ctx, err := sys.CreateRenderContext(nil, sys.EvtRenderContextSystem) + if err != nil { + return nil, err + } + return &winEventLog{ channelName: c.Name, remoteServer: c.RemoteAddress, maxRead: defaultMaxNumRead, renderBuf: make([]byte, renderBufferSize), + systemCtx: ctx, + cache: newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle), logPrefix: fmt.Sprintf("WinEventLog[%s]", c.Name), }, nil } diff --git a/winlogbeat/sys/wineventlog/wineventlog_windows.go b/winlogbeat/sys/wineventlog/wineventlog_windows.go index f9cc17b6ac24..1456419bcce2 100644 --- a/winlogbeat/sys/wineventlog/wineventlog_windows.go +++ b/winlogbeat/sys/wineventlog/wineventlog_windows.go @@ -144,7 +144,7 @@ func RenderEvent( systemContext EvtHandle, lang uint32, renderBuf []byte, - pubHandleProvider func(string) uintptr, + pubHandleProvider func(string) eventlogging.MessageFiles, ) (Event, error) { var err error @@ -187,7 +187,12 @@ func RenderEvent( var publisherHandle uintptr if pubHandleProvider != nil { - publisherHandle = pubHandleProvider(e.ProviderName) + messageFiles := pubHandleProvider(e.ProviderName) + if messageFiles.Err == nil { + // There is only ever a single handle when using the Windows Event + // Log API. + publisherHandle = messageFiles.Handles[0].Handle + } } // Populate strings that must be looked up. @@ -311,6 +316,17 @@ func CreateBookmark(channel string, recordID uint64) (EvtHandle, error) { return h, nil } +// Create a render context. Close must be called on returned EvtHandle when +// finished with the handle. +func CreateRenderContext(valuePaths []string, flag EvtRenderContextFlag) (EvtHandle, error) { + context, err := _EvtCreateRenderContext(0, nil, EvtRenderContextSystem) + if err != nil { + return 0, err + } + + return context, nil +} + // OpenPublisherMetadata opens a handle to the publisher's metadata. Close must // be called on returned EvtHandle when finished with the handle. func OpenPublisherMetadata(