Skip to content

Commit

Permalink
loki.source.docker: deduplicate matching container IDs (grafana#6055)
Browse files Browse the repository at this point in the history
Signed-off-by: Paschalis Tsilias <[email protected]>
Co-authored-by: Clayton Cornell <[email protected]>
  • Loading branch information
2 people authored and BarunKGP committed Feb 20, 2024
1 parent 8a1c688 commit 361e1ce
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,15 @@ v0.39.0 (2024-01-09)
- Add `max_cache_size` to `prometheus.relabel` to allow configurability instead of hard coded 100,000. (@mattdurham)

- Add support for `http_sd_config` within a `scrape_config` for prometheus to flow config conversion. (@erikbaranowski)

- `discovery.lightsail` now supports additional parameters for configuring HTTP client settings. (@ptodev)
- Add `sample_age_limit` to remote_write config to drop samples older than a specified duration. (@marctc)

- Handle paths in the Kubelet URL for `discovery.kubelet`. (@petewall)

- `loki.source.docker` now deduplicates targets which report the same container
ID. (@tpaschalis)

### Bugfixes

- Update `pyroscope.ebpf` to fix a logical bug causing to profile to many kthreads instead of regular processes https://github.com/grafana/pyroscope/pull/2778 (@korniltsev)
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ lint: agentlint
# more without -race for packages that have known race detection issues.
test:
$(GO_ENV) go test $(GO_FLAGS) -race $(shell go list ./... | grep -v /integration-tests/)
$(GO_ENV) go test $(GO_FLAGS) ./pkg/integrations/node_exporter ./pkg/logs ./pkg/operator ./pkg/util/k8s ./component/otelcol/processor/tail_sampling ./component/loki/source/file
$(GO_ENV) go test $(GO_FLAGS) ./pkg/integrations/node_exporter ./pkg/logs ./pkg/operator ./pkg/util/k8s ./component/otelcol/processor/tail_sampling ./component/loki/source/file ./component/loki/source/docker

test-packages:
docker pull $(BUILD_IMAGE)
Expand Down
5 changes: 5 additions & 0 deletions component/loki/source/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,18 @@ func (c *Component) Update(args component.Arguments) error {

// Convert input targets into targets to give to tailer.
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]
if !ok {
level.Debug(c.opts.Logger).Log("msg", "docker target did not include container ID label:"+dockerLabelContainerID)
continue
}
if _, seen := seenTargets[containerID]; seen {
continue
}
seenTargets[containerID] = struct{}{}

var labels = make(model.LabelSet)
for k, v := range target {
Expand Down
40 changes: 40 additions & 0 deletions component/loki/source/docker/docker_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
//go:build !race

package docker

import (
"context"
"testing"
"time"

"github.com/grafana/agent/component"
"github.com/grafana/agent/pkg/flow/componenttest"
"github.com/grafana/agent/pkg/util"
"github.com/grafana/river"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)

Expand All @@ -33,3 +37,39 @@ func Test(t *testing.T) {

require.NoError(t, ctrl.WaitRunning(time.Minute))
}

func TestDuplicateTargets(t *testing.T) {
// Use host that works on all platforms (including Windows).
var cfg = `
host = "tcp://127.0.0.1:9376"
targets = [
{__meta_docker_container_id = "foo", __meta_docker_port_private = "8080"},
{__meta_docker_container_id = "foo", __meta_docker_port_private = "8081"},
]
forward_to = []
`

var args Arguments
err := river.Unmarshal([]byte(cfg), &args)
require.NoError(t, err)

ctrl, err := componenttest.NewControllerFromID(util.TestLogger(t), "loki.source.docker")
require.NoError(t, err)

go func() {
err := ctrl.Run(context.Background(), args)
require.NoError(t, err)
}()

require.NoError(t, ctrl.WaitRunning(time.Minute))

cmp, err := New(component.Options{
ID: "loki.source.docker.test",
Logger: util.TestFlowLogger(t),
Registerer: prometheus.NewRegistry(),
DataPath: t.TempDir(),
}, args)
require.NoError(t, err)

require.Len(t, cmp.manager.tasks, 1)
}
8 changes: 8 additions & 0 deletions docs/sources/flow/reference/components/loki.source.docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ fully qualified name) to store its _positions file_. The positions file
stores the read offsets so that if there is a component or Agent restart,
`loki.source.docker` can pick up tailing from the same spot.

If the target's argument contains multiple entries with the same container
ID (for example as a result of `discovery.docker` picking up multiple exposed
ports or networks), `loki.source.docker` will deduplicate them, and only keep
the first of each container ID instances, based on the
`__meta_docker_container_id` label. As such, the Docker daemon is queried
for each container ID only once, and only one target will be available in the
component's debug info.

## Example

This example collects log entries from the files specified in the `targets`
Expand Down

0 comments on commit 361e1ce

Please sign in to comment.