Skip to content
This repository was archived by the owner on Jul 19, 2023. It is now read-only.

Commit 041f58e

Browse files
authored
Adds __service_name__ labels to improve data locality (#782)
* Adds __service_name__ labels to improve data locality * Lint
1 parent c5ea3b1 commit 041f58e

File tree

3 files changed

+122
-46
lines changed

3 files changed

+122
-46
lines changed

pkg/phlaredb/head.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"os"
77
"path/filepath"
88
"sort"
9-
"strings"
109
"sync"
1110
"time"
1211

@@ -419,51 +418,6 @@ func (h *Head) Ingest(ctx context.Context, p *profilev1.Profile, id uuid.UUID, e
419418
return nil
420419
}
421420

422-
func labelsForProfile(p *profilev1.Profile, externalLabels ...*typesv1.LabelPair) ([]phlaremodel.Labels, []model.Fingerprint) {
423-
// build label set per sample type before references are rewritten
424-
var (
425-
sb strings.Builder
426-
lbls = phlaremodel.NewLabelsBuilder(externalLabels)
427-
sampleType, sampleUnit, periodType, periodUnit string
428-
metricName = phlaremodel.Labels(externalLabels).Get(model.MetricNameLabel)
429-
)
430-
431-
// set common labels
432-
if p.PeriodType != nil {
433-
periodType = p.StringTable[p.PeriodType.Type]
434-
lbls.Set(phlaremodel.LabelNamePeriodType, periodType)
435-
periodUnit = p.StringTable[p.PeriodType.Unit]
436-
lbls.Set(phlaremodel.LabelNamePeriodUnit, periodUnit)
437-
}
438-
439-
profilesLabels := make([]phlaremodel.Labels, len(p.SampleType))
440-
seriesRefs := make([]model.Fingerprint, len(p.SampleType))
441-
for pos := range p.SampleType {
442-
sampleType = p.StringTable[p.SampleType[pos].Type]
443-
lbls.Set(phlaremodel.LabelNameType, sampleType)
444-
sampleUnit = p.StringTable[p.SampleType[pos].Unit]
445-
lbls.Set(phlaremodel.LabelNameUnit, sampleUnit)
446-
447-
sb.Reset()
448-
_, _ = sb.WriteString(metricName)
449-
_, _ = sb.WriteRune(':')
450-
_, _ = sb.WriteString(sampleType)
451-
_, _ = sb.WriteRune(':')
452-
_, _ = sb.WriteString(sampleUnit)
453-
_, _ = sb.WriteRune(':')
454-
_, _ = sb.WriteString(periodType)
455-
_, _ = sb.WriteRune(':')
456-
_, _ = sb.WriteString(periodUnit)
457-
t := sb.String()
458-
lbls.Set(phlaremodel.LabelNameProfileType, t)
459-
lbs := lbls.Labels().Clone()
460-
profilesLabels[pos] = lbs
461-
seriesRefs[pos] = model.Fingerprint(lbs.Hash())
462-
463-
}
464-
return profilesLabels, seriesRefs
465-
}
466-
467421
// LabelValues returns the possible label values for a given label name.
468422
func (h *Head) LabelValues(ctx context.Context, req *connect.Request[typesv1.LabelValuesRequest]) (*connect.Response[typesv1.LabelValuesResponse], error) {
469423
selectors, err := parseSelectors(req.Msg.Matchers)

pkg/phlaredb/labels.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package phlaredb
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/prometheus/common/model"
8+
9+
profilev1 "github.com/grafana/phlare/api/gen/proto/go/google/v1"
10+
typesv1 "github.com/grafana/phlare/api/gen/proto/go/types/v1"
11+
phlaremodel "github.com/grafana/phlare/pkg/model"
12+
)
13+
14+
var labelNameServiceName = fmt.Sprintf("__%s__", phlaremodel.LabelNameServiceName)
15+
16+
func labelsForProfile(p *profilev1.Profile, externalLabels ...*typesv1.LabelPair) ([]phlaremodel.Labels, []model.Fingerprint) {
17+
// build label set per sample type before references are rewritten
18+
var (
19+
sb strings.Builder
20+
lbls = phlaremodel.NewLabelsBuilder(externalLabels)
21+
sampleType, sampleUnit, periodType, periodUnit string
22+
metricName = phlaremodel.Labels(externalLabels).Get(model.MetricNameLabel)
23+
)
24+
25+
// Inject into labels the __service_name__ label if it exists
26+
// This allows better locality of the data in parquet files (row group are sorted by).
27+
if serviceName := lbls.Labels().Get(phlaremodel.LabelNameServiceName); serviceName != "" {
28+
lbls.Set(labelNameServiceName, serviceName)
29+
}
30+
31+
// set common labels
32+
if p.PeriodType != nil {
33+
periodType = p.StringTable[p.PeriodType.Type]
34+
lbls.Set(phlaremodel.LabelNamePeriodType, periodType)
35+
periodUnit = p.StringTable[p.PeriodType.Unit]
36+
lbls.Set(phlaremodel.LabelNamePeriodUnit, periodUnit)
37+
}
38+
39+
profilesLabels := make([]phlaremodel.Labels, len(p.SampleType))
40+
seriesRefs := make([]model.Fingerprint, len(p.SampleType))
41+
for pos := range p.SampleType {
42+
sampleType = p.StringTable[p.SampleType[pos].Type]
43+
lbls.Set(phlaremodel.LabelNameType, sampleType)
44+
sampleUnit = p.StringTable[p.SampleType[pos].Unit]
45+
lbls.Set(phlaremodel.LabelNameUnit, sampleUnit)
46+
47+
sb.Reset()
48+
_, _ = sb.WriteString(metricName)
49+
_, _ = sb.WriteRune(':')
50+
_, _ = sb.WriteString(sampleType)
51+
_, _ = sb.WriteRune(':')
52+
_, _ = sb.WriteString(sampleUnit)
53+
_, _ = sb.WriteRune(':')
54+
_, _ = sb.WriteString(periodType)
55+
_, _ = sb.WriteRune(':')
56+
_, _ = sb.WriteString(periodUnit)
57+
t := sb.String()
58+
lbls.Set(phlaremodel.LabelNameProfileType, t)
59+
lbs := lbls.Labels().Clone()
60+
profilesLabels[pos] = lbs
61+
seriesRefs[pos] = model.Fingerprint(lbs.Hash())
62+
63+
}
64+
return profilesLabels, seriesRefs
65+
}

pkg/phlaredb/labels_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package phlaredb
2+
3+
import (
4+
"sort"
5+
"testing"
6+
7+
"github.com/prometheus/common/model"
8+
"github.com/stretchr/testify/require"
9+
10+
phlaremodel "github.com/grafana/phlare/pkg/model"
11+
)
12+
13+
func TestLabelsForProfiles(t *testing.T) {
14+
for _, tt := range []struct {
15+
name string
16+
in phlaremodel.Labels
17+
expected phlaremodel.Labels
18+
}{
19+
{
20+
"default",
21+
phlaremodel.Labels{{Name: model.MetricNameLabel, Value: "cpu"}},
22+
phlaremodel.Labels{
23+
{Name: model.MetricNameLabel, Value: "cpu"},
24+
{Name: phlaremodel.LabelNameUnit, Value: "unit"},
25+
{Name: phlaremodel.LabelNameProfileType, Value: "cpu:type:unit:type:unit"},
26+
{Name: phlaremodel.LabelNameType, Value: "type"},
27+
{Name: phlaremodel.LabelNamePeriodType, Value: "type"},
28+
{Name: phlaremodel.LabelNamePeriodUnit, Value: "unit"},
29+
},
30+
},
31+
{
32+
"with service_name",
33+
phlaremodel.Labels{
34+
{Name: model.MetricNameLabel, Value: "cpu"},
35+
{Name: phlaremodel.LabelNameServiceName, Value: "service_name"},
36+
},
37+
phlaremodel.Labels{
38+
{Name: model.MetricNameLabel, Value: "cpu"},
39+
{Name: phlaremodel.LabelNameUnit, Value: "unit"},
40+
{Name: phlaremodel.LabelNameProfileType, Value: "cpu:type:unit:type:unit"},
41+
{Name: phlaremodel.LabelNameType, Value: "type"},
42+
{Name: phlaremodel.LabelNamePeriodType, Value: "type"},
43+
{Name: phlaremodel.LabelNamePeriodUnit, Value: "unit"},
44+
{Name: labelNameServiceName, Value: "service_name"},
45+
{Name: phlaremodel.LabelNameServiceName, Value: "service_name"},
46+
},
47+
},
48+
} {
49+
tt := tt
50+
t.Run(tt.name, func(t *testing.T) {
51+
sort.Sort(tt.expected)
52+
result, fps := labelsForProfile(newProfileFoo(), tt.in...)
53+
require.Equal(t, tt.expected, result[0])
54+
require.Equal(t, model.Fingerprint(tt.expected.Hash()), fps[0])
55+
})
56+
}
57+
}

0 commit comments

Comments
 (0)