Files
traces/tempodb/encoding/vparquet3/dedicated_columns_test.go
A. StoewerandGitHub e181a50c19 vParquet5: remove well-known attribute columns (#5696)
* Define default dedicated attribute columns

* Use default dedicated columns in block config

* vp4 ignores well-known attrs in dedicated columns

* vp3 ignores well-known attrs in dedicated columns

* Improve tenantindex benchmarks

* Use LRU cache for unmarshaled JSON columns

* Set version to vParquet5-preview3

* Remove well-known attribute columns on span level

* Remove well-known attribute columns on resource level

* Convert vp5 test-data and re-enable find by ID test

* Generate manifest.md

* vp3 and vp4 ignore all unsupported attributes

* vp5 ignores unsupported attributes

* CHANGELOG.md
2025-10-17 15:05:26 +10:00

325 lines
13 KiB
Go

package vparquet3
import (
"testing"
"github.com/stretchr/testify/assert"
v1 "github.com/grafana/tempo/pkg/tempopb/common/v1"
"github.com/grafana/tempo/tempodb/backend"
)
func TestDedicatedColumnsToColumnMapping(t *testing.T) {
tests := []struct {
name string
columns backend.DedicatedColumns
scopes []backend.DedicatedColumnScope
expectedMapping dedicatedColumnMapping
}{
{
name: "scope span",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "span.one", Type: "string"},
{Scope: "resource", Name: "res.one", Type: "string"},
{Scope: "span", Name: "span.two", Type: "string"},
},
scopes: []backend.DedicatedColumnScope{"span"},
expectedMapping: dedicatedColumnMapping{
mapping: map[string]dedicatedColumn{
"span.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String01"},
"span.two": {Type: "string", ColumnIndex: 1, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String02"},
},
keys: []string{"span.one", "span.two"},
},
},
{
name: "scope resource",
columns: backend.DedicatedColumns{
{Scope: "resource", Name: "res.one", Type: "string"},
{Scope: "span", Name: "span.one", Type: "string"},
{Scope: "span", Name: "span.two", Type: "string"},
{Scope: "resource", Name: "res.two", Type: "string"},
},
scopes: []backend.DedicatedColumnScope{"resource"},
expectedMapping: dedicatedColumnMapping{
mapping: map[string]dedicatedColumn{
"res.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.Resource.DedicatedAttributes.String01"},
"res.two": {Type: "string", ColumnIndex: 1, ColumnPath: "rs.list.element.Resource.DedicatedAttributes.String02"},
},
keys: []string{"res.one", "res.two"},
},
},
{
name: "all scopes explicit",
columns: backend.DedicatedColumns{
{Scope: "resource", Name: "res.one", Type: "string"},
{Scope: "span", Name: "span.one", Type: "string"},
{Scope: "span", Name: "span.two", Type: "string"},
{Scope: "resource", Name: "res.two", Type: "string"},
},
scopes: []backend.DedicatedColumnScope{"resource", "span"},
expectedMapping: dedicatedColumnMapping{
mapping: map[string]dedicatedColumn{
"res.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.Resource.DedicatedAttributes.String01"},
"res.two": {Type: "string", ColumnIndex: 1, ColumnPath: "rs.list.element.Resource.DedicatedAttributes.String02"},
"span.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String01"},
"span.two": {Type: "string", ColumnIndex: 1, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String02"},
},
keys: []string{"res.one", "res.two", "span.one", "span.two"},
},
},
{
name: "all scopes implicit",
columns: backend.DedicatedColumns{
{Scope: "resource", Name: "res.one", Type: "string"},
{Scope: "span", Name: "span.one", Type: "string"},
{Scope: "span", Name: "span.two", Type: "string"},
{Scope: "resource", Name: "res.two", Type: "string"},
},
scopes: []backend.DedicatedColumnScope{},
expectedMapping: dedicatedColumnMapping{
mapping: map[string]dedicatedColumn{
"res.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.Resource.DedicatedAttributes.String01"},
"res.two": {Type: "string", ColumnIndex: 1, ColumnPath: "rs.list.element.Resource.DedicatedAttributes.String02"},
"span.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String01"},
"span.two": {Type: "string", ColumnIndex: 1, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String02"},
},
keys: []string{"res.one", "res.two", "span.one", "span.two"},
},
},
{
name: "wrong type",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "span.one", Type: "string"},
{Scope: "resource", Name: "res.one", Type: "string"},
{Scope: "span", Name: "span.two", Type: "integer"}, // ignored
},
scopes: []backend.DedicatedColumnScope{"span"},
expectedMapping: dedicatedColumnMapping{
mapping: map[string]dedicatedColumn{
"span.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String01"},
},
keys: []string{"span.one"},
},
},
{
name: "too many columns",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "span.one", Type: "string"},
{Scope: "span", Name: "span.two", Type: "string"},
{Scope: "span", Name: "span.three", Type: "string"},
{Scope: "span", Name: "span.four", Type: "string"},
{Scope: "span", Name: "span.five", Type: "string"},
{Scope: "span", Name: "span.six", Type: "string"},
{Scope: "span", Name: "span.seven", Type: "string"},
{Scope: "span", Name: "span.eight", Type: "string"},
{Scope: "span", Name: "span.nine", Type: "string"},
{Scope: "span", Name: "span.ten", Type: "string"},
{Scope: "span", Name: "span.eleven", Type: "string"}, // ignored
},
scopes: []backend.DedicatedColumnScope{"span"},
expectedMapping: dedicatedColumnMapping{
mapping: map[string]dedicatedColumn{
"span.one": {Type: "string", ColumnIndex: 0, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String01"},
"span.two": {Type: "string", ColumnIndex: 1, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String02"},
"span.three": {Type: "string", ColumnIndex: 2, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String03"},
"span.four": {Type: "string", ColumnIndex: 3, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String04"},
"span.five": {Type: "string", ColumnIndex: 4, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String05"},
"span.six": {Type: "string", ColumnIndex: 5, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String06"},
"span.seven": {Type: "string", ColumnIndex: 6, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String07"},
"span.eight": {Type: "string", ColumnIndex: 7, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String08"},
"span.nine": {Type: "string", ColumnIndex: 8, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String09"},
"span.ten": {Type: "string", ColumnIndex: 9, ColumnPath: "rs.list.element.ss.list.element.Spans.list.element.DedicatedAttributes.String10"},
},
keys: []string{"span.one", "span.two", "span.three", "span.four", "span.five", "span.six", "span.seven", "span.eight", "span.nine", "span.ten"},
},
},
}
for _, tc := range tests {
meta := backend.BlockMeta{DedicatedColumns: tc.columns}
mapping := dedicatedColumnsToColumnMapping(meta.DedicatedColumns, tc.scopes...)
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expectedMapping, mapping)
})
}
}
func TestDedicatedColumn_readValue(t *testing.T) {
strPtr := func(s string) *string { return &s }
attrComplete := DedicatedAttributes{
strPtr("one"), strPtr("two"), strPtr("three"), strPtr("four"), strPtr("five"),
strPtr("six"), strPtr("seven"), strPtr("eight"), strPtr("nine"), strPtr("ten"),
}
tests := []struct {
name string
dedicatedColumn dedicatedColumn
attr DedicatedAttributes
want *v1.AnyValue
}{
{
name: "not nil",
dedicatedColumn: dedicatedColumn{Type: "string", ColumnIndex: 0},
attr: attrComplete,
want: &v1.AnyValue{Value: &v1.AnyValue_StringValue{StringValue: "one"}},
},
{
name: "nil",
dedicatedColumn: dedicatedColumn{Type: "string", ColumnIndex: 0},
attr: DedicatedAttributes{},
want: nil,
},
{
name: "index too high",
dedicatedColumn: dedicatedColumn{Type: "string", ColumnIndex: 10},
attr: attrComplete,
want: nil,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
val := tc.dedicatedColumn.readValue(&tc.attr)
assert.Equal(t, tc.want, val)
})
}
}
func TestDedicatedColumn_writeValue(t *testing.T) {
strPtr := func(s string) *string { return &s }
tests := []struct {
name string
dedicatedColumn dedicatedColumn
value *v1.AnyValue
expectedWritten bool
expectedAttr DedicatedAttributes
}{
{
name: "string",
dedicatedColumn: dedicatedColumn{Type: "string", ColumnIndex: 4},
value: &v1.AnyValue{Value: &v1.AnyValue_StringValue{StringValue: "five"}},
expectedWritten: true,
expectedAttr: DedicatedAttributes{String05: strPtr("five")},
},
{
name: "wrong type",
dedicatedColumn: dedicatedColumn{Type: "string", ColumnIndex: 1},
value: &v1.AnyValue{Value: &v1.AnyValue_IntValue{IntValue: 2}},
},
{
name: "index too high",
dedicatedColumn: dedicatedColumn{Type: "string", ColumnIndex: 10},
value: &v1.AnyValue{Value: &v1.AnyValue_StringValue{StringValue: "eleven"}},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
var attr DedicatedAttributes
written := tc.dedicatedColumn.writeValue(&attr, tc.value)
assert.Equal(t, tc.expectedWritten, written)
assert.Equal(t, tc.expectedAttr, attr)
})
}
}
func TestFilterDedicatedColumns(t *testing.T) {
tests := []struct {
name string
columns backend.DedicatedColumns
expected backend.DedicatedColumns
}{
{
name: "empty columns",
columns: backend.DedicatedColumns{},
expected: backend.DedicatedColumns{},
},
{
name: "empty result span",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "http.url", Type: "string"},
},
expected: backend.DedicatedColumns{},
},
{
name: "empty result resource",
columns: backend.DedicatedColumns{
{Scope: "resource", Name: "cluster", Type: "string"},
{Scope: "resource", Name: "k8s.namespace.name", Type: "string"},
{Scope: "resource", Name: "service.name", Type: "string"},
},
expected: backend.DedicatedColumns{},
},
{
name: "filtered result",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "http.method", Type: "string"},
{Scope: "span", Name: "span-two", Type: "string"},
{Scope: "resource", Name: "k8s.cluster.name", Type: "string"},
{Scope: "resource", Name: "res-one", Type: "string"},
{Scope: "resource", Name: "res-two", Type: "string"},
},
expected: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "span-two", Type: "string"},
{Scope: "resource", Name: "res-one", Type: "string"},
{Scope: "resource", Name: "res-two", Type: "string"},
},
},
{
name: "non-filtered result",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "span-two", Type: "string"},
{Scope: "resource", Name: "res-one", Type: "string"},
{Scope: "resource", Name: "res-two", Type: "string"},
},
expected: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "span-two", Type: "string"},
{Scope: "resource", Name: "res-one", Type: "string"},
{Scope: "resource", Name: "res-two", Type: "string"},
},
},
{
name: "non-filtered wrong-type",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "http.status_code", Type: "string"},
},
expected: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "http.status_code", Type: "string"},
},
},
{
name: "non-filtered wrong-scope",
columns: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "k8s.cluster.name", Type: "string"},
{Scope: "span", Name: "span-two", Type: "string"},
{Scope: "resource", Name: "http.method", Type: "string"},
{Scope: "resource", Name: "res-one", Type: "string"},
{Scope: "resource", Name: "res-two", Type: "string"},
},
expected: backend.DedicatedColumns{
{Scope: "span", Name: "span-one", Type: "string"},
{Scope: "span", Name: "k8s.cluster.name", Type: "string"},
{Scope: "span", Name: "span-two", Type: "string"},
{Scope: "resource", Name: "http.method", Type: "string"},
{Scope: "resource", Name: "res-one", Type: "string"},
{Scope: "resource", Name: "res-two", Type: "string"},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := filterDedicatedColumns(tt.columns)
assert.Equal(t, tt.expected, result)
})
}
}