-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement badger db for sampling store
Signed-off-by: slayer321 <[email protected]>
- Loading branch information
Showing
5 changed files
with
255 additions
and
1 deletion.
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,176 @@ | ||
package samplingstore | ||
|
||
import ( | ||
"bytes" | ||
"encoding/binary" | ||
"encoding/json" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/dgraph-io/badger/v3" | ||
"github.com/jaegertracing/jaeger/cmd/collector/app/sampling/model" | ||
jaegermodel "github.com/jaegertracing/jaeger/model" | ||
) | ||
|
||
const ( | ||
throughputKeyPrefix byte = 0x08 | ||
probabilitiesKeyPrefix byte = 0x09 | ||
) | ||
|
||
type SamplingStore struct { | ||
store *badger.DB | ||
} | ||
|
||
func NewSamplingStore(db *badger.DB) *SamplingStore { | ||
return &SamplingStore{ | ||
store: db, | ||
} | ||
} | ||
|
||
func (s *SamplingStore) InsertThroughput(throughput []*model.Throughput) error { | ||
fmt.Println("Inside badger samplingstore InsertThroughput") | ||
startTime := jaegermodel.TimeAsEpochMicroseconds(time.Now()) | ||
entriesToStore := make([]*badger.Entry, 0) | ||
entries, err := s.createThroughputEntry(throughput, startTime) | ||
if err != nil { | ||
return err | ||
} | ||
entriesToStore = append(entriesToStore, entries) | ||
err = s.store.Update(func(txn *badger.Txn) error { | ||
// Write the entries | ||
for i := range entriesToStore { | ||
err = txn.SetEntry(entriesToStore[i]) | ||
fmt.Println("Writing entry to badger") | ||
if err != nil { | ||
// Most likely primary key conflict, but let the caller check this | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
return nil | ||
} | ||
|
||
func (s *SamplingStore) GetThroughput(start, end time.Time) ([]*model.Throughput, error) { | ||
var retSlice []*model.Throughput | ||
fmt.Println("Inside badger samplingstore GetThroughput") | ||
|
||
prefix := []byte{throughputKeyPrefix} | ||
|
||
err := s.store.View(func(txn *badger.Txn) error { | ||
opts := badger.DefaultIteratorOptions | ||
it := txn.NewIterator(opts) | ||
defer it.Close() | ||
|
||
val := []byte{} | ||
for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() { | ||
item := it.Item() | ||
k := item.Key() | ||
startTime := k[1:9] | ||
fmt.Printf("key=%s\n", k) | ||
val, err := item.ValueCopy(val) | ||
if err != nil { | ||
return err | ||
} | ||
t, err := initalStartTime(startTime) | ||
if err != nil { | ||
return err | ||
} | ||
throughputs, err := decodeValue(val) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if t.After(start) && (t.Before(end) || t.Equal(end)) { | ||
retSlice = append(retSlice, throughputs...) | ||
} | ||
return nil | ||
} | ||
return nil | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return retSlice, nil | ||
} | ||
|
||
func (s *SamplingStore) InsertProbabilitiesAndQPS(hostname string, | ||
probabilities model.ServiceOperationProbabilities, | ||
qps model.ServiceOperationQPS) error { | ||
return nil | ||
} | ||
|
||
// GetLatestProbabilities implements samplingstore.Reader#GetLatestProbabilities. | ||
func (s *SamplingStore) GetLatestProbabilities() (model.ServiceOperationProbabilities, error) { | ||
return nil, nil | ||
} | ||
|
||
func (s *SamplingStore) createThroughputEntry(throughput []*model.Throughput, startTime uint64) (*badger.Entry, error) { | ||
pK, pV, err := s.createThroughputKV(throughput, startTime) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
e := s.createBadgerEntry(pK, pV) | ||
|
||
return e, nil | ||
} | ||
|
||
func (s *SamplingStore) createBadgerEntry(key []byte, value []byte) *badger.Entry { | ||
return &badger.Entry{ | ||
Key: key, | ||
Value: value, | ||
} | ||
} | ||
|
||
func (s *SamplingStore) createThroughputKV(throughput []*model.Throughput, startTime uint64) ([]byte, []byte, error) { | ||
|
||
key := make([]byte, 16) | ||
key[0] = throughputKeyPrefix | ||
pos := 1 | ||
binary.BigEndian.PutUint64(key[pos:], startTime) | ||
|
||
var bb []byte | ||
var err error | ||
|
||
bb, err = json.Marshal(throughput) | ||
fmt.Printf("Badger key %v, value %v\n", key, string(bb)) | ||
return key, bb, err | ||
} | ||
|
||
func createPrimaryKeySeekPrefix(startTime uint64) []byte { | ||
key := make([]byte, 16) | ||
key[0] = throughputKeyPrefix | ||
pos := 1 | ||
binary.BigEndian.PutUint64(key[pos:], startTime) | ||
|
||
return key | ||
} | ||
|
||
func decodeValue(val []byte) ([]*model.Throughput, error) { | ||
var throughput []*model.Throughput | ||
|
||
err := json.Unmarshal(val, &throughput) | ||
if err != nil { | ||
fmt.Println("Error while unmarshalling") | ||
return nil, err | ||
} | ||
fmt.Printf("Throughput %v\n", throughput) | ||
return throughput, nil | ||
} | ||
|
||
func initalStartTime(timeBytes []byte) (time.Time, error) { | ||
var usec int64 | ||
|
||
buf := bytes.NewReader(timeBytes) | ||
|
||
if err := binary.Read(buf, binary.BigEndian, &usec); err != nil { | ||
panic(nil) | ||
} | ||
|
||
t := time.UnixMicro(usec) | ||
return t, nil | ||
} |
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,68 @@ | ||
package samplingstore | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/dgraph-io/badger/v3" | ||
samplemodel "github.com/jaegertracing/jaeger/cmd/collector/app/sampling/model" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
type samplingStoreTest struct { | ||
store *SamplingStore | ||
} | ||
|
||
func NewtestSamplingStore(db *badger.DB) *samplingStoreTest { | ||
return &samplingStoreTest{ | ||
store: NewSamplingStore(db), | ||
} | ||
} | ||
|
||
func TestInsertThroughput(t *testing.T) { | ||
runWithBadger(t, func(s *samplingStoreTest, t *testing.T) { | ||
throughputs := []*samplemodel.Throughput{ | ||
{Service: "my-svc", Operation: "op"}, | ||
{Service: "our-svc", Operation: "op2"}, | ||
} | ||
err := s.store.InsertThroughput(throughputs) | ||
assert.NoError(t, err) | ||
}) | ||
} | ||
|
||
func TestGetThroughput(t *testing.T) { | ||
runWithBadger(t, func(s *samplingStoreTest, t *testing.T) { | ||
start := time.Now() | ||
|
||
expected := 2 | ||
throughputs := []*samplemodel.Throughput{ | ||
{Service: "my-svc", Operation: "op"}, | ||
{Service: "our-svc", Operation: "op2"}, | ||
} | ||
err := s.store.InsertThroughput(throughputs) | ||
assert.NoError(t, err) | ||
|
||
actual, err := s.store.GetThroughput(start, start.Add(time.Second*time.Duration(10))) | ||
assert.NoError(t, err) | ||
assert.Equal(t, expected, len(actual)) | ||
}) | ||
} | ||
|
||
func runWithBadger(t *testing.T, test func(s *samplingStoreTest, t *testing.T)) { | ||
opts := badger.DefaultOptions("") | ||
|
||
opts.SyncWrites = false | ||
dir := t.TempDir() | ||
opts.Dir = dir | ||
opts.ValueDir = dir | ||
|
||
store, err := badger.Open(opts) | ||
defer func() { | ||
store.Close() | ||
}() | ||
ss := NewtestSamplingStore(store) | ||
|
||
assert.NoError(t, err) | ||
|
||
test(ss, t) | ||
} |
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