Like Prometheus, but for logs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
loki/pkg/dataobj/planner/internal/tree/printer_test.go

52 lines
1.5 KiB

chore: Add tree printer for physical plan (#16716) This PR adds a generic tree printer (similar to the Unix utility `tree`). Additionally it provides an implementation to convert the DAG of the physical plan into the generic tree used by the tree printer. This allows to print plans like this (note, these examples do not make sense, they are only for demonstrating the visual output of the printer). Simple DAG with single child node: ``` Limit #limit offset=0 limit=0 └── Filter #filter predicates=() └── SortMerge #merge column=<nil> order=UNDEFINED ├── DataObjScan #scan1 location= stream_ids=() projections=() predicates=() direction=0 limit=0 └── DataObjScan #scan2 location= stream_ids=() projections=() predicates=() direction=0 limit=0 ``` DAG with multple root nodes: ``` Limit #limit1 offset=0 limit=0 └── DataObjScan #scan1 location= stream_ids=() projections=() predicates=() direction=0 limit=0 Limit #limit2 offset=0 limit=0 └── DataObjScan #scan2 location= stream_ids=() projections=() predicates=() direction=0 limit=0 ``` DAG with parent node that share the same child node: ``` Limit #limit offset=0 limit=0 ├── Limit #filter1 offset=0 limit=0 │ └── DataObjScan #scan location= stream_ids=() projections=() predicates=() direction=0 limit=0 └── Limit #filter2 offset=0 limit=0 └── DataObjScan #scan location= stream_ids=() projections=() predicates=() direction=0 limit=0 ``` --- Signed-off-by: Christian Haudum <christian.haudum@gmail.com>
9 months ago
package tree
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
)
func TestPrinter(t *testing.T) {
root := NewNode("Root", "")
lvl1 := root.AddChild("Merge", "foo", []Property{
{Key: "key_a", Values: []any{"value_a"}, IsMultiValue: true},
{Key: "key_b", Values: []any{"value_b", "value_c"}, IsMultiValue: true},
})
lvl2 := lvl1.AddChild("Product", "foobar", []Property{
{Key: "relations", Values: []any{"foo", "bar"}, IsMultiValue: true},
})
rel := lvl2.AddComment("Relation", "foo", nil)
rel.AddChild("Shard", "0", nil)
rel.AddChild("Shard", "1", nil)
rel.AddChild("Shard", "2", nil)
lvl2.AddComment("Relation", "bar", nil)
lvl2.AddChild("Scan", "foo", []Property{
{Key: "selector", Values: []any{`{env="prod", region=".+"}`}},
})
lvl2.AddChild("Scan", "bar", []Property{
{Key: "selector", Values: []any{`{env="dev", region=".+"}`}},
})
_ = lvl1.AddChild("Scan", "baz", []Property{})
b := &strings.Builder{}
p := NewPrinter(b)
p.Print(root)
t.Log("\n" + b.String())
expected := `
Root
Merge #foo key_a=(value_a) key_b=(value_b, value_c)
Product #foobar relations=(foo, bar)
Relation #foo
Shard #0
Shard #1
Shard #2
Relation #bar
Scan #foo selector={env="prod", region=".+"}
Scan #bar selector={env="dev", region=".+"}
Scan #baz
`
require.Equal(t, expected, "\n"+b.String())
}