forked from elastic/beats
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Backport: Fix for errno 1734 when calling EvtNext (elastic#3112) (ela…
…stic#3124) * Fix for errno 1734 when calling EvtNext When reading a batch of large event log records the Windows function EvtNext returns errno 1734 (0x6C6) which is RPC_S_INVALID_BOUND ("The array bounds are invalid."). This seems to be a bug in Windows because there is no documentation about this behavior. This fix handles the error by resetting the event log subscription handle (so events are not lost) and then retries the EvtNext call with maxHandles/2. Fixes elastic#3076 (cherry picked from commit 226eb10) * Add benchmark test for batch_read_size in Winlogbeat
- Loading branch information
1 parent
1db70fa
commit d06e42c
Showing
9 changed files
with
285 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// +build windows | ||
|
||
package eventlog | ||
|
||
import ( | ||
"flag" | ||
"math/rand" | ||
"os/exec" | ||
"strconv" | ||
"testing" | ||
"time" | ||
|
||
elog "github.com/andrewkroh/sys/windows/svc/eventlog" | ||
"github.com/dustin/go-humanize" | ||
) | ||
|
||
// Benchmark tests with customized output. (`go test -v -benchtime 10s -benchtest .`) | ||
|
||
var ( | ||
benchTest = flag.Bool("benchtest", false, "Run benchmarks for the eventlog package") | ||
injectAmount = flag.Int("inject", 50000, "Number of events to inject before running benchmarks") | ||
) | ||
|
||
// TestBenchmarkBatchReadSize tests the performance of different | ||
// batch_read_size values. | ||
func TestBenchmarkBatchReadSize(t *testing.T) { | ||
if !*benchTest { | ||
t.Skip("-benchtest not enabled") | ||
} | ||
|
||
log, err := initLog(providerName, sourceName, eventCreateMsgFile) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer func() { | ||
err := uninstallLog(providerName, sourceName, log) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
}() | ||
|
||
// Increase the log size so that it can hold these large events. | ||
output, err := exec.Command("wevtutil.exe", "sl", "/ms:1073741824", providerName).CombinedOutput() | ||
if err != nil { | ||
t.Fatal(err, string(output)) | ||
} | ||
|
||
// Publish test messages: | ||
for i := 0; i < *injectAmount; i++ { | ||
err = log.Report(elog.Info, uint32(rng.Int63()%1000), []string{strconv.Itoa(i) + " " + randString(256)}) | ||
if err != nil { | ||
t.Fatal("ReportEvent error", err) | ||
} | ||
} | ||
|
||
setup := func(t testing.TB, batchReadSize int) (EventLog, func()) { | ||
eventlog, err := newWinEventLog(map[string]interface{}{"name": providerName, "batch_read_size": batchReadSize}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
err = eventlog.Open(0) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
return eventlog, func() { | ||
err := eventlog.Close() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
} | ||
|
||
benchTest := func(batchSize int) { | ||
var err error | ||
result := testing.Benchmark(func(b *testing.B) { | ||
eventlog, tearDown := setup(b, batchSize) | ||
defer tearDown() | ||
b.ResetTimer() | ||
|
||
// Each iteration reads one batch. | ||
for i := 0; i < b.N; i++ { | ||
_, err = eventlog.Read() | ||
if err != nil { | ||
return | ||
} | ||
} | ||
}) | ||
|
||
if err != nil { | ||
t.Fatal(err) | ||
return | ||
} | ||
|
||
t.Logf("batch_size=%v, total_events=%v, batch_time=%v, events_per_sec=%v, bytes_alloced_per_event=%v, total_allocs=%v", | ||
batchSize, | ||
result.N*batchSize, | ||
time.Duration(result.NsPerOp()), | ||
float64(batchSize)/time.Duration(result.NsPerOp()).Seconds(), | ||
humanize.Bytes(result.MemBytes/(uint64(result.N)*uint64(batchSize))), | ||
result.MemAllocs) | ||
} | ||
|
||
benchTest(10) | ||
benchTest(100) | ||
benchTest(500) | ||
benchTest(1000) | ||
} | ||
|
||
// Utility Functions | ||
|
||
var rng = rand.NewSource(time.Now().UnixNano()) | ||
|
||
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
const ( | ||
letterIdxBits = 6 // 6 bits to represent a letter index | ||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits | ||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits | ||
) | ||
|
||
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang | ||
func randString(n int) string { | ||
b := make([]byte, n) | ||
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters! | ||
for i, cache, remain := n-1, rng.Int63(), letterIdxMax; i >= 0; { | ||
if remain == 0 { | ||
cache, remain = rng.Int63(), letterIdxMax | ||
} | ||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) { | ||
b[i] = letterBytes[idx] | ||
i-- | ||
} | ||
cache >>= letterIdxBits | ||
remain-- | ||
} | ||
|
||
return string(b) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.