mirror of
https://github.com/hanzoai/traces.git
synced 2026-10-30 18:20:41 +00:00
* Copy vparquet3 to vparquet4 folder * Create initial vParquet4 encoding * vParquet4: handle unsupported / dropped attributes (#3123) * Count dropped attributes and store them in separate column * Remove current support for arrays and kv-lists * Store per-trace service statistics in vparquet4 blocks (#2941) * Add support for attributes with array values (#3221) * Implement single values as arrays and introduce type column * Add support for array attributes * Tests more array values and fix attribute conversion * Use a combination of snappy and delta for ValueType * Vendor module google/go-cmp/cmp/cmpopts * Use all types of array attributes in TestTraceToParquet * Improve TestFieldsAreCleared * links and events schema changes (#3163) * Add attributes to instrumentation scope (#3322) * Fix typo in vParquet4 event name enconding (#3336) * Precalculate and reuse the vParquet4 schema before opening blocks * Convert block in vparquet4/test-data directory * CHANGELOG.md * Update test cases in BenchmarkBackendBlockTraceQL * Unsupported attribute values are no longer dropped * Replace ValueType column with IsArray column * Skip service stats map allocation when none are present --------- Signed-off-by: Andreas Gerstmayr <[email protected]> Co-authored-by: Andreas Gerstmayr <[email protected]> Co-authored-by: Jennie Pham <[email protected]> Co-authored-by: Andreas Gerstmayr <[email protected]>
97 lines
2.2 KiB
Go
97 lines
2.2 KiB
Go
package vparquet4
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/tempo/tempodb/encoding/common"
|
|
)
|
|
|
|
type intIterator []*uint8 // making this a pointer makes the below code a little gross but allows multiblockiterator to treat all types as nillable
|
|
|
|
func (i *intIterator) Next(_ context.Context) (common.ID, *uint8, error) {
|
|
s := *i
|
|
if len(s) == 0 {
|
|
return nil, nil, io.EOF
|
|
}
|
|
ret := s[0]
|
|
*i = s[1:]
|
|
return []byte{*ret}, ret, nil
|
|
}
|
|
|
|
func (i *intIterator) Close() {}
|
|
|
|
func (i *intIterator) peekNextID(_ context.Context) (common.ID, error) { //nolint:unused //this is being marked as unused, but it's literally used about 30 lines south
|
|
s := *i
|
|
if len(s) == 0 {
|
|
return nil, io.EOF
|
|
}
|
|
|
|
return []byte{*s[0]}, nil
|
|
}
|
|
|
|
func TestMultiBlockIterator(t *testing.T) {
|
|
ptr := func(n uint8) *uint8 {
|
|
return &n
|
|
}
|
|
|
|
tcs := []struct {
|
|
iters []*intIterator
|
|
expected []uint8
|
|
}{
|
|
{
|
|
iters: []*intIterator{{}},
|
|
expected: []uint8{},
|
|
},
|
|
{
|
|
iters: []*intIterator{{}, {}},
|
|
expected: []uint8{},
|
|
},
|
|
{
|
|
iters: []*intIterator{{ptr(1), ptr(2), ptr(3)}, {ptr(4), ptr(5), ptr(6)}},
|
|
expected: []uint8{1, 2, 3, 4, 5, 6},
|
|
},
|
|
{
|
|
iters: []*intIterator{{ptr(1), ptr(3), ptr(5)}, {ptr(2), ptr(4), ptr(6)}},
|
|
expected: []uint8{1, 2, 3, 4, 5, 6},
|
|
},
|
|
{
|
|
iters: []*intIterator{{ptr(1), ptr(3)}, {ptr(2), ptr(6)}, {ptr(4), ptr(5)}},
|
|
expected: []uint8{1, 2, 3, 4, 5, 6},
|
|
},
|
|
{
|
|
iters: []*intIterator{{ptr(1), ptr(3)}, {ptr(1), ptr(6)}, {ptr(4), ptr(6)}},
|
|
expected: []uint8{1, 3, 4, 6},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tcs {
|
|
bookmarks := make([]*bookmark[*uint8], 0, len(tc.iters))
|
|
for _, iter := range tc.iters {
|
|
bookmarks = append(bookmarks, newBookmark[*uint8](iter))
|
|
}
|
|
|
|
mbi := newMultiblockIterator(bookmarks, func(i []*uint8) (*uint8, error) {
|
|
return i[0], nil
|
|
})
|
|
defer mbi.Close()
|
|
|
|
ctx := context.Background()
|
|
for {
|
|
id, val, err := mbi.Next(ctx)
|
|
if errors.Is(err, io.EOF) {
|
|
break
|
|
}
|
|
require.NoError(t, err)
|
|
require.Equal(t, common.ID([]byte{tc.expected[0]}), id)
|
|
require.Equal(t, tc.expected[0], *val)
|
|
tc.expected = tc.expected[1:]
|
|
}
|
|
require.Len(t, tc.expected, 0)
|
|
}
|
|
}
|