Skip to content

Commit

Permalink
sampling/eventstorage: introduce event storage
Browse files Browse the repository at this point in the history
Introduce a package which provides local event storage,
tailored for tail-based sampling. Storage is backed by
Badger (github.com/dgraph-io/badger).

The Storage type provides two types for readiing/writing
data: ReadWriter, and ShardedReadWriter. ReadWriter is
not safe for concurrent access, while ShardedReadWriter is.
ShardedReadWriter provides locked access to one of several
ReadWriters, sharding on trace ID.

Currently we encode transactions and spans as JSON.
We should look into developing a more efficient codec
later, using protobuf or similar.
  • Loading branch information
axw committed Aug 26, 2020
1 parent fa7ee8d commit 5eafce8
Show file tree
Hide file tree
Showing 10 changed files with 918 additions and 2 deletions.
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ require (
github.com/cespare/xxhash/v2 v2.1.1
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
github.com/client9/misspell v0.3.5-0.20180309020325-c0b55c823952 // indirect
github.com/dgraph-io/badger/v2 v2.0.3
github.com/dgraph-io/ristretto v0.0.2 // indirect
github.com/dlclark/regexp2 v1.2.1 // indirect
github.com/dop251/goja v0.0.0-20200824171909-536f9d946569 // indirect
github.com/dop251/goja_nodejs v0.0.0-20200811150831-9bc458b4bbeb // indirect
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4
github.com/dustin/go-humanize v1.0.0
github.com/elastic/beats/v7 v7.0.0-alpha2.0.20200824113715-49e8024953a4
github.com/elastic/go-elasticsearch/v7 v7.8.0
github.com/elastic/go-elasticsearch/v8 v8.0.0-20200819071622-59b6a186f8dd
Expand All @@ -28,13 +30,16 @@ require (
github.com/google/addlicense v0.0.0-20190907113143-be125746c2c4 // indirect
github.com/google/go-cmp v0.4.0
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99
github.com/hashicorp/go-multierror v1.1.0
github.com/hashicorp/golang-lru v0.5.3
github.com/ianlancetaylor/demangle v0.0.0-20200715173712-053cf528c12f // indirect
github.com/jaegertracing/jaeger v1.16.0
github.com/jcmturner/gofork v1.0.0 // indirect
github.com/josephspurrier/goversioninfo v1.2.0 // indirect
github.com/json-iterator/go v1.1.8
github.com/jstemmer/go-junit-report v0.9.1
github.com/klauspost/compress v1.9.3-0.20191122130757-c099ac9f21dd // indirect
github.com/kr/pretty v0.2.0 // indirect
github.com/magefile/mage v1.10.0
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/mitchellh/hashstructure v1.0.0 // indirect
Expand All @@ -60,7 +65,7 @@ require (
go.elastic.co/apm/module/apmgrpc v1.7.0
go.elastic.co/apm/module/apmhttp v1.7.2
go.elastic.co/ecszap v0.2.0 // indirect
go.elastic.co/fastjson v1.1.0 // indirect
go.elastic.co/fastjson v1.1.0
go.uber.org/atomic v1.6.0
go.uber.org/zap v1.15.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
Expand Down
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,16 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/godog v0.7.13/go.mod h1:z2OZ6a3X0/YAKVqLfVzYBwFt3j6uSt3Xrqa7XTtcQE0=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI=
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
Expand Down Expand Up @@ -200,9 +203,16 @@ github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892/go.mod h1:CTDl0pzVz
github.com/denisenkom/go-mssqldb v0.0.0-20200206145737-bbfc9a55622e/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
github.com/devigned/tab v0.1.2-0.20190607222403-0c15cf42f9a2/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
github.com/dgraph-io/badger/v2 v2.0.3 h1:inzdf6VF/NZ+tJ8RwwYMjJMvsOALTHYdozn0qSl6XJI=
github.com/dgraph-io/badger/v2 v2.0.3/go.mod h1:3KY8+bsP8wI0OEnQJAKpd4wIJW/Mm32yw2j/9FUVnIM=
github.com/dgraph-io/ristretto v0.0.2-0.20200115201040-8f368f2f2ab3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po=
github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible h1:4jGdduO4ceTJFKf0IhgaB8NJapGqKHwC2b4xQ/cXujM=
github.com/dgrijalva/jwt-go v3.2.1-0.20190620180102-5e25c22bd5d6+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/digitalocean/go-libvirt v0.0.0-20180301200012-6075ea3c39a1/go.mod h1:PRcPVAAma6zcLpFd4GZrjR/MRpood3TamjKI2m/z/Uw=
Expand All @@ -225,6 +235,8 @@ github.com/dop251/goja_nodejs v0.0.0-20171011081505-adff31b136e6 h1:RrkoB0pT3gnj
github.com/dop251/goja_nodejs v0.0.0-20171011081505-adff31b136e6/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
Expand Down Expand Up @@ -557,6 +569,7 @@ github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
Expand Down Expand Up @@ -652,6 +665,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
Expand Down Expand Up @@ -893,6 +908,7 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs=
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
Expand Down Expand Up @@ -1158,6 +1174,7 @@ golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
1 change: 1 addition & 0 deletions x-pack/apm-server/sampling/eventstorage/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package eventstorage
34 changes: 34 additions & 0 deletions x-pack/apm-server/sampling/eventstorage/jsoncodec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package eventstorage

import (
"encoding/json"

// NOTE(axw) encoding/json is faster for encoding,
// json-iterator is faster for decoding.
jsoniter "github.com/json-iterator/go"

"github.com/elastic/apm-server/model"
)

// JSONCodec is an implementation of Codec, using JSON encoding.
type JSONCodec struct{}

// DecodeSpan decodes data as JSON into span.
func (JSONCodec) DecodeSpan(data []byte, span *model.Span) error {
return jsoniter.ConfigFastest.Unmarshal(data, span)
}

// DecodeTransaction decodes data as JSON into tx.
func (JSONCodec) DecodeTransaction(data []byte, tx *model.Transaction) error {
return jsoniter.ConfigFastest.Unmarshal(data, tx)
}

// EncodeSpan encodes span as JSON.
func (JSONCodec) EncodeSpan(span *model.Span) ([]byte, error) {
return json.Marshal(span)
}

// EncodeTransaction encodes tx as JSON.
func (JSONCodec) EncodeTransaction(tx *model.Transaction) ([]byte, error) {
return json.Marshal(tx)
}
17 changes: 17 additions & 0 deletions x-pack/apm-server/sampling/eventstorage/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package eventstorage

import "github.com/elastic/beats/v7/libbeat/logp"

// LogpAdaptor adapts logp.Logger to the badger.Logger interface.
type LogpAdaptor struct {
*logp.Logger
}

// Warningf adapts badger.Logger.Warningf to logp.Logger.Warngf.
func (a LogpAdaptor) Warningf(format string, args ...interface{}) {
a.Warnf(format, args...)
}
135 changes: 135 additions & 0 deletions x-pack/apm-server/sampling/eventstorage/sharded.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package eventstorage

import (
"runtime"
"sync"

"github.com/cespare/xxhash/v2"
"github.com/hashicorp/go-multierror"

"github.com/elastic/apm-server/model"
)

// ShardedReadWriter provides sharded, locked, access to a Storage.
//
// ShardedReadWriter shards on trace ID.
type ShardedReadWriter struct {
readWriters []lockedReadWriter
}

func newShardedReadWriter(storage *Storage) *ShardedReadWriter {
s := &ShardedReadWriter{
// Create as many ReadWriters as there are CPUs,
// so we can ideally minimise lock contention.
readWriters: make([]lockedReadWriter, runtime.NumCPU()),
}
for i := range s.readWriters {
s.readWriters[i].rw = storage.NewReadWriter()
}
return s
}

// Close closes all sharded storage readWriters.
func (s *ShardedReadWriter) Close() {
for i := range s.readWriters {
s.readWriters[i].Close()
}
}

// Flush flushes all sharded storage readWriters.
func (s *ShardedReadWriter) Flush() error {
var result error
for i := range s.readWriters {
if err := s.readWriters[i].Flush(); err != nil {
result = multierror.Append(result, err)
}
}
return result
}

// ReadEvents calls Writer.ReadEvents, using a sharded, locked, Writer.
func (s *ShardedReadWriter) ReadEvents(traceID string, out *model.Batch) error {
return s.getWriter(traceID).ReadEvents(traceID, out)
}

// WriteTransaction calls Writer.WriteTransaction, using a sharded, locked, Writer.
func (s *ShardedReadWriter) WriteTransaction(tx *model.Transaction) error {
return s.getWriter(tx.TraceID).WriteTransaction(tx)
}

// WriteSpan calls Writer.WriteSpan, using a sharded, locked, Writer.
func (s *ShardedReadWriter) WriteSpan(span *model.Span) error {
return s.getWriter(span.TraceID).WriteSpan(span)
}

// WriteTraceSampled calls Writer.WriteTraceSampled, using a sharded, locked, Writer.
func (s *ShardedReadWriter) WriteTraceSampled(traceID string, sampled bool) error {
return s.getWriter(traceID).WriteTraceSampled(traceID, sampled)
}

// IsTraceSampled calls Writer.IsTraceSampled, using a sharded, locked, Writer.
func (s *ShardedReadWriter) IsTraceSampled(traceID string) (bool, error) {
return s.getWriter(traceID).IsTraceSampled(traceID)
}

// getWriter returns an event storage writer for the given trace ID.
//
// This method is idempotent, which is necessary to avoid transaction
// conflicts and ensure all events are reported once a sampling decision
// has been recorded.
func (s *ShardedReadWriter) getWriter(traceID string) *lockedReadWriter {
var h xxhash.Digest
h.WriteString(traceID)
return &s.readWriters[h.Sum64()%uint64(len(s.readWriters))]
}

type lockedReadWriter struct {
mu sync.Mutex
rw *ReadWriter
}

func (rw *lockedReadWriter) Close() {
rw.mu.Lock()
defer rw.mu.Unlock()
rw.rw.Close()
}

func (rw *lockedReadWriter) Flush() error {
rw.mu.Lock()
defer rw.mu.Unlock()
return rw.rw.Flush()
}

func (rw *lockedReadWriter) ReadEvents(traceID string, out *model.Batch) error {
rw.mu.Lock()
defer rw.mu.Unlock()
return rw.rw.ReadEvents(traceID, out)
}

func (rw *lockedReadWriter) WriteTransaction(tx *model.Transaction) error {
rw.mu.Lock()
defer rw.mu.Unlock()
return rw.rw.WriteTransaction(tx)
}

func (rw *lockedReadWriter) WriteSpan(s *model.Span) error {
rw.mu.Lock()
defer rw.mu.Unlock()
return rw.rw.WriteSpan(s)
}

func (rw *lockedReadWriter) WriteTraceSampled(traceID string, sampled bool) error {
rw.mu.Lock()
defer rw.mu.Unlock()
return rw.rw.WriteTraceSampled(traceID, sampled)
}

func (rw *lockedReadWriter) IsTraceSampled(traceID string) (bool, error) {
rw.mu.Lock()
defer rw.mu.Unlock()
return rw.rw.IsTraceSampled(traceID)
}
51 changes: 51 additions & 0 deletions x-pack/apm-server/sampling/eventstorage/sharded_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package eventstorage_test

import (
"testing"
"time"

"github.com/gofrs/uuid"

"github.com/elastic/apm-server/model"
"github.com/elastic/apm-server/x-pack/apm-server/sampling/eventstorage"
)

func BenchmarkShardedWriteTransactionUncontended(b *testing.B) {
db := newBadgerDB(b, badgerOptions)
ttl := time.Minute
store := eventstorage.New(db, eventstorage.JSONCodec{}, ttl)
sharded := store.NewShardedReadWriter()
defer sharded.Close()

b.RunParallel(func(pb *testing.PB) {
traceUUID := uuid.Must(uuid.NewV4())
transaction := &model.Transaction{TraceID: traceUUID.String(), ID: traceUUID.String()}
for pb.Next() {
if err := sharded.WriteTransaction(transaction); err != nil {
b.Fatal(err)
}
}
})
}

func BenchmarkShardedWriteTransactionContended(b *testing.B) {
db := newBadgerDB(b, badgerOptions)
ttl := time.Minute
store := eventstorage.New(db, eventstorage.JSONCodec{}, ttl)
sharded := store.NewShardedReadWriter()
defer sharded.Close()

// Use a single trace ID, causing all events to go through
// the same sharded writer, contending for a single lock.
traceUUID := uuid.Must(uuid.NewV4())

b.RunParallel(func(pb *testing.PB) {
transactionUUID := uuid.Must(uuid.NewV4())
transaction := &model.Transaction{TraceID: traceUUID.String(), ID: transactionUUID.String()}
for pb.Next() {
if err := sharded.WriteTransaction(transaction); err != nil {
b.Fatal(err)
}
}
})
}
Loading

0 comments on commit 5eafce8

Please sign in to comment.