Skip to content

Commit

Permalink
moretests
Browse files Browse the repository at this point in the history
  • Loading branch information
thampiotr committed Jan 31, 2025
1 parent 054ce6d commit e8b9ad8
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 50 deletions.
55 changes: 28 additions & 27 deletions internal/component/discovery/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,6 @@ var (
_ equality.CustomEquality = Target{}
)

func ComponentTargetsToPromTargetGroups(jobName string, tgs []Target) map[string][]*targetgroup.Group {
targetsWithCommonGroupLabels := map[uint64][]Target{}
for _, t := range tgs {
fp := t.groupLabelsHash() // TODO(thampiotr): could use a cache if it's on exactly the same slice
targetsWithCommonGroupLabels[fp] = append(targetsWithCommonGroupLabels[fp], t)
}

allGroups := make([]*targetgroup.Group, 0, len(targetsWithCommonGroupLabels))

groupIndex := 0
for _, targetsInGroup := range targetsWithCommonGroupLabels {
sharedLabels := targetsInGroup[0].group // all have the same group labels.
individualLabels := make([]commonlabels.LabelSet, len(targetsInGroup))
for i, target := range targetsInGroup {
individualLabels[i] = target.own
}
promGroup := &targetgroup.Group{
Source: fmt.Sprintf("%s_part_%d", jobName, groupIndex),
Labels: sharedLabels,
Targets: individualLabels,
}
allGroups = append(allGroups, promGroup)
}
return map[string][]*targetgroup.Group{jobName: allGroups}
}

var EmptyTarget = Target{
group: commonlabels.LabelSet{},
own: commonlabels.LabelSet{},
Expand Down Expand Up @@ -302,7 +276,7 @@ func (t Target) hashLabelsInOrder(order []string) uint64 {
b := make([]byte, 0, 1024)
mustGet := func(label string) string {
val, ok := t.Get(label)
if !ok {
if !ok { // should never happen as Target is immutable
panic("label concurrently modified - this is a bug - please report an issue")
}
return val
Expand Down Expand Up @@ -330,3 +304,30 @@ func (t Target) hashLabelsInOrder(order []string) uint64 {
}
return xxhash.Sum64(b)
}

func ComponentTargetsToPromTargetGroups(jobName string, tgs []Target) map[string][]*targetgroup.Group {
targetsWithCommonGroupLabels := map[uint64][]Target{}
for _, t := range tgs {
fp := t.groupLabelsHash() // TODO(thampiotr): could use a cache if it's on exactly the same slice
targetsWithCommonGroupLabels[fp] = append(targetsWithCommonGroupLabels[fp], t)
}

allGroups := make([]*targetgroup.Group, 0, len(targetsWithCommonGroupLabels))

groupIndex := 0
for _, targetsInGroup := range targetsWithCommonGroupLabels {
sharedLabels := targetsInGroup[0].group // all have the same group labels.
individualLabels := make([]commonlabels.LabelSet, len(targetsInGroup))
for i, target := range targetsInGroup {
individualLabels[i] = target.own
}
promGroup := &targetgroup.Group{
Source: fmt.Sprintf("%s_part_%d", jobName, groupIndex),
Labels: sharedLabels,
Targets: individualLabels,
}
allGroups = append(allGroups, promGroup)
groupIndex++
}
return map[string][]*targetgroup.Group{jobName: allGroups}
}
2 changes: 0 additions & 2 deletions internal/component/discovery/target_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,6 @@ func (t targetBuilder) Target() Target {
)

if modifyOwn {
// TODO(thampiotr): further benchmarking is needed here, but if this is causing a lot of allocation, we could
// try implementing Target with toAdd and toDel overlays instead.
newOwn = make(commonlabels.LabelSet, len(t.own)+len(t.toAdd))
for k, v := range t.own {
if _, ok := t.toDel[string(k)]; ok {
Expand Down
151 changes: 130 additions & 21 deletions internal/component/discovery/target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package discovery

import (
"fmt"
"reflect"
"slices"
"strings"
"testing"

"github.com/Masterminds/goutils"
"github.com/grafana/ckit/peer"
"github.com/grafana/ckit/shard"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/grafana/alloy/internal/runtime/equality"
Expand Down Expand Up @@ -69,33 +70,47 @@ func TestConvertFromNative(t *testing.T) {
require.True(t, equality.DeepEqual(expected, toAlloyTargets(map[string]*targetgroup.Group{"test": nativeGroup})))
}

func TestEquals_Basic(t *testing.T) {
// NOTE: if we start caching anything as a field, the equality may break. We should test it.
t1 := NewTargetFromMap(map[string]string{"hip": "hop", "boom": "bap"})
require.Equal(t, 2, t1.Len())
tb := NewTargetBuilderFrom(t1)
tb.Set("boom", "bap")
t2 := tb.Target()
// This is a way commonly used in tests.
require.Equal(t, t1, t2)
// This is the way exports are compared in BuiltinComponentNode.setExports, and it's important for performance that
// Targets equality is working correctly.
require.True(t, reflect.DeepEqual(t1, t2))
}

// TODO(thampiotr): will need a lot more tests like this and with a builder
func TestEquals_Custom(t *testing.T) {
t1 := NewTargetFromSpecificAndBaseLabelSet(
eq1 := NewTargetFromSpecificAndBaseLabelSet(
model.LabelSet{"foo": "bar"},
model.LabelSet{"hip": "hop"},
)
t2 := NewTargetFromSpecificAndBaseLabelSet(
eq2 := NewTargetFromSpecificAndBaseLabelSet(
nil,
model.LabelSet{"hip": "hop", "foo": "bar"},
)
require.NotEqual(t, t1, t2)
require.True(t, t1.Equals(&t2))
require.True(t, t1.EqualsTarget(&t2))
eq3 := NewTargetFromSpecificAndBaseLabelSet(
model.LabelSet{"hip": "hop", "foo": "bar"},
nil,
)
ne1 := NewTargetFromSpecificAndBaseLabelSet(
model.LabelSet{"foo": "bar"},
nil,
)
ne2 := NewTargetFromSpecificAndBaseLabelSet(
nil,
model.LabelSet{"foo": "bar"},
)

equalTargets := []Target{eq1, eq2, eq3}
for _, t1 := range equalTargets {
for _, t2 := range equalTargets {
require.True(t, t1.Equals(&t2))
require.True(t, t1.EqualsTarget(&t2))
require.True(t, t2.Equals(&t1))
require.True(t, t2.EqualsTarget(&t1))
}
}

notEqualTargets := []Target{ne1, ne2}
for _, t1 := range notEqualTargets {
for _, t2 := range equalTargets {
require.False(t, t1.Equals(&t2))
require.False(t, t1.EqualsTarget(&t2))
require.False(t, t2.Equals(&t1))
require.False(t, t2.EqualsTarget(&t1))
}
}
}

func Benchmark_Targets_TypicalPipeline(b *testing.B) {
Expand Down Expand Up @@ -186,3 +201,97 @@ func (f *randomCluster) Lookup(key shard.Key, _ int, _ shard.Op) ([]peer.Peer, e
func (f *randomCluster) Peers() []peer.Peer {
return f.peers
}

func TestComponentTargetsToPromTargetGroups(t *testing.T) {
type testTarget struct {
own map[string]string
group map[string]string
}
type args struct {
jobName string
tgs []testTarget
}
tests := []struct {
name string
args args
expected map[string][]*targetgroup.Group
}{
{
name: "empty targets",
args: args{jobName: "job"},
expected: map[string][]*targetgroup.Group{"job": {}},
},
{
name: "targets all in same group",
args: args{
jobName: "job",
tgs: []testTarget{
{group: map[string]string{"hip": "hop"}, own: map[string]string{"boom": "bap"}},
{group: map[string]string{"hip": "hop"}, own: map[string]string{"tiki": "ta"}},
},
},
expected: map[string][]*targetgroup.Group{"job": {
{
Source: "job_part_0",
Labels: mapToLabelSet(map[string]string{"hip": "hop"}),
Targets: []model.LabelSet{
mapToLabelSet(map[string]string{"boom": "bap"}),
mapToLabelSet(map[string]string{"tiki": "ta"}),
},
},
}},
},
{
name: "two groups",
args: args{
jobName: "job",
tgs: []testTarget{
{group: map[string]string{"hip": "hop"}, own: map[string]string{"boom": "bap"}},
{group: map[string]string{"kung": "foo"}, own: map[string]string{"tiki": "ta"}},
{group: map[string]string{"hip": "hop"}, own: map[string]string{"hoo": "rey"}},
{group: map[string]string{"kung": "foo"}, own: map[string]string{"bibim": "bap"}},
},
},
expected: map[string][]*targetgroup.Group{"job": {
{
Source: "job_part_0",
Labels: mapToLabelSet(map[string]string{"hip": "hop"}),
Targets: []model.LabelSet{
mapToLabelSet(map[string]string{"boom": "bap"}),
mapToLabelSet(map[string]string{"hoo": "rey"}),
},
},
{
Source: "job_part_1",
Labels: mapToLabelSet(map[string]string{"kung": "foo"}),
Targets: []model.LabelSet{
mapToLabelSet(map[string]string{"tiki": "ta"}),
mapToLabelSet(map[string]string{"bibim": "bap"}),
},
},
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
targets := make([]Target, 0, len(tt.args.tgs))
for _, tg := range tt.args.tgs {
targets = append(targets, NewTargetFromSpecificAndBaseLabelSet(mapToLabelSet(tg.own), mapToLabelSet(tg.group)))
}
actual := ComponentTargetsToPromTargetGroups(tt.args.jobName, targets)
assert.Contains(t, actual, tt.args.jobName)
slices.SortFunc(actual[tt.args.jobName], func(a *targetgroup.Group, b *targetgroup.Group) int {
return strings.Compare(a.Source, b.Source)
})
assert.Equal(t, tt.expected, actual, "ComponentTargetsToPromTargetGroups(%v, %v)", tt.args.jobName, tt.args.tgs)
})
}
}

func mapToLabelSet(m map[string]string) model.LabelSet {
r := make(model.LabelSet, len(m))
for k, v := range m {
r[model.LabelName(k)] = model.LabelValue(v)
}
return r
}

0 comments on commit e8b9ad8

Please sign in to comment.