Skip to content

Commit

Permalink
fix loki.source.docker to handle targets with multiple networks confi…
Browse files Browse the repository at this point in the history
…gured (#1017)
  • Loading branch information
wildum authored Jun 12, 2024
1 parent 96aa51c commit 80bb355
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ Main (unreleased)

- Fix panic when `import.git` is given a revision that does not exist on the remote repo. (@hainenber)

- Fixed an issue with `loki.source.docker` where collecting logs from targets configured with multiple networks would result in errors. (@wildum)

### Other changes

- `pyroscope.ebpf`, `pyroscope.java`, `pyroscope.scrape`, `pyroscope.write` and `discovery.process` components are now GA. (@korniltsev)
Expand Down
38 changes: 27 additions & 11 deletions internal/component/loki/source/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"path/filepath"
"reflect"
"sort"
"sync"
"time"

Expand Down Expand Up @@ -179,6 +180,11 @@ func (c *Component) Run(ctx context.Context) error {
}
}

type promTarget struct {
labels model.LabelSet
fingerPrint model.Fingerprint
}

// Update implements component.Component.
func (c *Component) Update(args component.Arguments) error {
newArgs := args.(Arguments)
Expand Down Expand Up @@ -219,29 +225,39 @@ func (c *Component) Update(args component.Arguments) error {
targets := make([]*dt.Target, 0, len(newArgs.Targets))
seenTargets := make(map[string]struct{}, len(newArgs.Targets))

for _, target := range newArgs.Targets {
containerID, ok := target[dockerLabelContainerID]
promTargets := make([]promTarget, len(newArgs.Targets))
for i, target := range newArgs.Targets {
var labels = make(model.LabelSet)
for k, v := range target {
labels[model.LabelName(k)] = model.LabelValue(v)
}
promTargets[i] = promTarget{labels: labels, fingerPrint: labels.Fingerprint()}
}

// Sorting the targets before filtering ensures consistent filtering of targets
// when multiple targets share the same containerID.
sort.Slice(promTargets, func(i, j int) bool {
return promTargets[i].fingerPrint < promTargets[j].fingerPrint
})

for _, markedTarget := range promTargets {
containerID, ok := markedTarget.labels[dockerLabelContainerID]
if !ok {
level.Debug(c.opts.Logger).Log("msg", "docker target did not include container ID label:"+dockerLabelContainerID)
continue
}
if _, seen := seenTargets[containerID]; seen {
if _, seen := seenTargets[string(containerID)]; seen {
continue
}
seenTargets[containerID] = struct{}{}

var labels = make(model.LabelSet)
for k, v := range target {
labels[model.LabelName(k)] = model.LabelValue(v)
}
seenTargets[string(containerID)] = struct{}{}

tgt, err := dt.NewTarget(
c.metrics,
log.With(c.opts.Logger, "target", fmt.Sprintf("docker/%s", containerID)),
c.manager.opts.handler,
c.manager.opts.positions,
containerID,
labels.Merge(c.defaultLabels),
string(containerID),
markedTarget.labels.Merge(c.defaultLabels),
c.rcs,
c.manager.opts.client,
)
Expand Down
16 changes: 16 additions & 0 deletions internal/component/loki/source/docker/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,22 @@ func TestDuplicateTargets(t *testing.T) {
require.NoError(t, err)

require.Len(t, cmp.manager.tasks, 1)
require.Equal(t, cmp.manager.tasks[0].target.LabelsStr(), "{__meta_docker_container_id=\"foo\", __meta_docker_port_private=\"8080\"}")

var newCfg = `
host = "tcp://127.0.0.1:9376"
targets = [
{__meta_docker_container_id = "foo", __meta_docker_port_private = "8081"},
{__meta_docker_container_id = "foo", __meta_docker_port_private = "8080"},
]
forward_to = []
`
err = syntax.Unmarshal([]byte(newCfg), &args)
require.NoError(t, err)
cmp.Update(args)
require.Len(t, cmp.manager.tasks, 1)
// Although the order of the targets changed, the filtered target stays the same.
require.Equal(t, cmp.manager.tasks[0].target.LabelsStr(), "{__meta_docker_container_id=\"foo\", __meta_docker_port_private=\"8080\"}")
}

func TestRestart(t *testing.T) {
Expand Down

0 comments on commit 80bb355

Please sign in to comment.