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/consumer/logsobj/builder_test.go

130 lines
3.1 KiB

package logsobj
import (
"context"
"errors"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/grafana/loki/pkg/push"
"github.com/grafana/loki/v3/pkg/dataobj/sections/logs"
"github.com/grafana/loki/v3/pkg/dataobj/sections/streams"
"github.com/grafana/loki/v3/pkg/logproto"
)
var testBuilderConfig = BuilderConfig{
TargetPageSize: 2048,
TargetObjectSize: 1 << 20, // 1 MiB
TargetSectionSize: 1 << 19, // 512 KiB
BufferSize: 2048 * 8,
SectionStripeMergeLimit: 2,
}
func TestBuilder(t *testing.T) {
testStreams := []logproto.Stream{
{
Labels: `{cluster="test",app="foo"}`,
Entries: []push.Entry{
{
Timestamp: time.Unix(10, 0).UTC(),
Line: "hello",
StructuredMetadata: push.LabelsAdapter{
{Name: "trace_id", Value: "123"},
},
},
{
Timestamp: time.Unix(5, 0).UTC(),
Line: "hello again",
StructuredMetadata: push.LabelsAdapter{
{Name: "trace_id", Value: "456"},
{Name: "span_id", Value: "789"},
},
},
},
},
{
Labels: `{cluster="test",app="bar"}`,
Entries: []push.Entry{
{
Timestamp: time.Unix(15, 0).UTC(),
Line: "world",
StructuredMetadata: push.LabelsAdapter{
{Name: "trace_id", Value: "abc"},
},
},
{
Timestamp: time.Unix(20, 0).UTC(),
Line: "world again",
StructuredMetadata: push.LabelsAdapter{
{Name: "trace_id", Value: "def"},
{Name: "span_id", Value: "ghi"},
},
},
},
},
}
t.Run("Build", func(t *testing.T) {
builder, err := NewBuilder(testBuilderConfig, nil)
require.NoError(t, err)
for _, entry := range testStreams {
require.NoError(t, builder.Append("tenant", entry))
}
obj, closer, err := builder.Flush()
require.NoError(t, err)
defer closer.Close()
require.Equal(t, 1, obj.Sections().Count(streams.CheckSection))
require.Equal(t, 1, obj.Sections().Count(logs.CheckSection))
})
}
// TestBuilder_Append ensures that appending to the buffer eventually reports
// that the buffer is full.
func TestBuilder_Append(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
builder, err := NewBuilder(testBuilderConfig, nil)
require.NoError(t, err)
tenant := "test"
for {
require.NoError(t, ctx.Err())
err := builder.Append(tenant, logproto.Stream{
Labels: `{cluster="test",app="foo"}`,
Entries: []push.Entry{{
Timestamp: time.Now().UTC(),
Line: strings.Repeat("a", 1024),
}},
})
if errors.Is(err, ErrBuilderFull) {
break
}
require.NoError(t, err)
}
obj, closer, err := builder.Flush()
require.NoError(t, err)
defer closer.Close()
// When a section builder is reset, which happens on ErrBuilderFull, the
// tenant is reset too. We must check that the tenant is added back
// to the section builder otherwise tenant will be absent from successive
// sections.
secs := obj.Sections()
require.Equal(t, 1, secs.Count(streams.CheckSection))
require.Greater(t, secs.Count(logs.CheckSection), 1)
for _, section := range secs.Filter(logs.CheckSection) {
require.Equal(t, tenant, section.Tenant)
}
}