Skip to content

Commit 2ae1ead

Browse files
authored
chore(metric_extraction): Optimize labels result (#15068)
1 parent cbdd36a commit 2ae1ead

File tree

2 files changed

+64
-5
lines changed

2 files changed

+64
-5
lines changed

pkg/logql/log/labels.go

+25-5
Original file line numberDiff line numberDiff line change
@@ -583,16 +583,36 @@ func (b *LabelsBuilder) LabelsResult() LabelsResult {
583583
return b.currentResult
584584
}
585585

586-
stream := b.labels(StreamLabel).Copy()
587-
structuredMetadata := b.labels(StructuredMetadataLabel).Copy()
588-
parsed := b.labels(ParsedLabel).Copy()
589-
b.buf = flattenLabels(b.buf, stream, structuredMetadata, parsed)
586+
// Get all labels at once and sort them
587+
b.buf = b.UnsortedLabels(b.buf)
588+
sort.Sort(b.buf)
590589
hash := b.hasher.Hash(b.buf)
590+
591591
if cached, ok := b.resultCache[hash]; ok {
592592
return cached
593593
}
594594

595-
result := NewLabelsResult(b.buf.String(), hash, stream, structuredMetadata, parsed)
595+
// Now segregate the sorted labels into their categories
596+
var stream, meta, parsed []labels.Label
597+
598+
for _, l := range b.buf {
599+
// Skip error labels for stream and meta categories
600+
if l.Name == logqlmodel.ErrorLabel || l.Name == logqlmodel.ErrorDetailsLabel {
601+
parsed = append(parsed, l)
602+
continue
603+
}
604+
605+
// Check which category this label belongs to
606+
if labelsContain(b.add[ParsedLabel], l.Name) {
607+
parsed = append(parsed, l)
608+
} else if labelsContain(b.add[StructuredMetadataLabel], l.Name) {
609+
meta = append(meta, l)
610+
} else {
611+
stream = append(stream, l)
612+
}
613+
}
614+
615+
result := NewLabelsResult(b.buf.String(), hash, labels.New(stream...), labels.New(meta...), labels.New(parsed...))
596616
b.resultCache[hash] = result
597617

598618
return result

pkg/logql/log/labels_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package log
33
import (
44
"sort"
55
"testing"
6+
"time"
67

78
"github.com/prometheus/prometheus/model/labels"
89
"github.com/stretchr/testify/assert"
@@ -463,3 +464,41 @@ func assertLabelResult(t *testing.T, lbs labels.Labels, res LabelsResult) {
463464
res.String(),
464465
)
465466
}
467+
468+
// benchmark streamLineSampleExtractor.Process method
469+
func BenchmarkStreamLineSampleExtractor_Process(b *testing.B) {
470+
// Setup some test data
471+
baseLabels := labels.FromStrings(
472+
"namespace", "prod",
473+
"cluster", "us-east-1",
474+
"pod", "my-pod-123",
475+
"container", "main",
476+
"stream", "stdout",
477+
)
478+
479+
structuredMeta := []labels.Label{
480+
{Name: "level", Value: "info"},
481+
{Name: "caller", Value: "http.go:42"},
482+
{Name: "user", Value: "john"},
483+
{Name: "trace_id", Value: "abc123"},
484+
}
485+
486+
testLine := []byte(`{"timestamp":"2024-01-01T00:00:00Z","level":"info","message":"test message","duration_ms":150}`)
487+
488+
// JSON parsing + filtering + label extraction
489+
matcher := labels.MustNewMatcher(labels.MatchEqual, "level", "info")
490+
filter := NewStringLabelFilter(matcher)
491+
stages := []Stage{
492+
NewJSONParser(),
493+
filter,
494+
}
495+
ex, err := NewLineSampleExtractor(CountExtractor, stages, []string{}, false, false)
496+
require.NoError(b, err)
497+
streamEx := ex.ForStream(baseLabels)
498+
b.ReportAllocs()
499+
b.ResetTimer()
500+
501+
for i := 0; i < b.N; i++ {
502+
_, _, _ = streamEx.Process(time.Now().UnixNano(), testLine, structuredMeta...)
503+
}
504+
}

0 commit comments

Comments
 (0)