Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker: optionally add labels as tags #2425

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ be deprecated eventually.
- [#2332](https://github.com/influxdata/telegraf/pull/2332): Add Elasticsearch 5.x output
- [#2587](https://github.com/influxdata/telegraf/pull/2587): Add json timestamp units configurability
- [#2597](https://github.com/influxdata/telegraf/issues/2597): Add support for Linux sysctl-fs metrics.
- [#2425](https://github.com/influxdata/telegraf/pull/2425): Support to include/exclude docker container labels as tags

### Bugfixes

Expand Down
24 changes: 16 additions & 8 deletions plugins/inputs/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ for the stat structure can be found
perdevice = true
## Whether to report for each container total blkio and network stats or not
total = false

## docker labels to include and exclude as tags. Globs accepted.
## Note that an empty array for both will include all labels as tags
docker_label_include = []
docker_label_exclude = []

```

### Measurements & Fields:
Expand Down Expand Up @@ -130,30 +136,32 @@ based on the availability of per-cpu stats on your system.


### Tags:

#### Docker Engine tags
- docker (memory_total)
- unit=bytes
- engine_host
- docker (pool_blocksize)
- unit=bytes
- engine_host
- docker_data
- unit=bytes
- engine_host
- docker_metadata
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this one also has engine_host

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. I'll add it.

- unit=bytes
- engine_host

- docker_container_mem specific:
#### Docker Container tags
- Tags on all containers:
- engine_host
- container_image
- container_name
- container_version
- docker_container_mem specific:
- docker_container_cpu specific:
- container_image
- container_name
- cpu
- docker_container_net specific:
- container_image
- container_name
- network
- docker_container_blkio specific:
- container_image
- container_name
- device

### Example Output:
Expand Down
61 changes: 54 additions & 7 deletions plugins/inputs/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,34 @@ import (

"github.com/docker/docker/api/types"
"github.com/docker/docker/client"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/filter"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/plugins/inputs"
)

type DockerLabelFilter struct {
labelInclude filter.Filter
labelExclude filter.Filter
}

// Docker object
type Docker struct {
Endpoint string
ContainerNames []string
Timeout internal.Duration
PerDevice bool `toml:"perdevice"`
Total bool `toml:"total"`
PerDevice bool `toml:"perdevice"`
Total bool `toml:"total"`
LabelInclude []string `toml:"docker_label_include"`
LabelExclude []string `toml:"docker_label_exclude"`

LabelFilter DockerLabelFilter

client *client.Client
engine_host string

testing bool
testing bool
labelFiltersCreated bool
}

// infoWrapper wraps client.Client.List for testing.
Expand Down Expand Up @@ -99,6 +109,10 @@ var sampleConfig = `
## Whether to report for each container total blkio and network stats or not
total = false

## docker labels to include and exclude as tags. Globs accepted.
## Note that an empty array for both will include all labels as tags
docker_label_include = []
docker_label_exclude = []
`

// Description returns input description
Expand Down Expand Up @@ -133,6 +147,14 @@ func (d *Docker) Gather(acc telegraf.Accumulator) error {
}
d.client = c
}
// Create label filters if not already created
if !d.labelFiltersCreated {
err := d.createLabelFilters()
if err != nil {
return err
}
d.labelFiltersCreated = true
}

// Get daemon info
err := d.gatherInfo(acc)
Expand Down Expand Up @@ -293,7 +315,11 @@ func (d *Docker) gatherContainer(

// Add labels to tags
for k, label := range container.Labels {
tags[k] = label
if len(d.LabelInclude) == 0 || d.LabelFilter.labelInclude.Match(k) {
if len(d.LabelExclude) == 0 || !d.LabelFilter.labelExclude.Match(k) {
tags[k] = label
}
}
}

gatherContainerStats(v, acc, tags, container.ID, d.PerDevice, d.Total)
Expand Down Expand Up @@ -599,11 +625,32 @@ func parseSize(sizeStr string) (int64, error) {
return int64(size), nil
}

func (d *Docker) createLabelFilters() error {
if len(d.LabelInclude) != 0 && d.LabelFilter.labelInclude == nil {
var err error
d.LabelFilter.labelInclude, err = filter.Compile(d.LabelInclude)
if err != nil {
return err
}
}

if len(d.LabelExclude) != 0 && d.LabelFilter.labelExclude == nil {
var err error
d.LabelFilter.labelExclude, err = filter.Compile(d.LabelExclude)
if err != nil {
return err
}
}

return nil
}

func init() {
inputs.Add("docker", func() telegraf.Input {
return &Docker{
PerDevice: true,
Timeout: internal.Duration{Duration: time.Second * 5},
PerDevice: true,
Timeout: internal.Duration{Duration: time.Second * 5},
labelFiltersCreated: false,
}
})
}
55 changes: 55 additions & 0 deletions plugins/inputs/docker/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,57 @@ func testStats() *types.StatsJSON {
return stats
}

var gatherLabelsTests = []struct {
include []string
exclude []string
expected []string
notexpected []string
}{
{[]string{}, []string{}, []string{"label1", "label2"}, []string{}},
{[]string{"*"}, []string{}, []string{"label1", "label2"}, []string{}},
{[]string{"lab*"}, []string{}, []string{"label1", "label2"}, []string{}},
{[]string{"label1"}, []string{}, []string{"label1"}, []string{"label2"}},
{[]string{"label1*"}, []string{}, []string{"label1"}, []string{"label2"}},
{[]string{}, []string{"*"}, []string{}, []string{"label1", "label2"}},
{[]string{}, []string{"lab*"}, []string{}, []string{"label1", "label2"}},
{[]string{}, []string{"label1"}, []string{"label2"}, []string{"label1"}},
{[]string{"*"}, []string{"*"}, []string{}, []string{"label1", "label2"}},
}

func TestDockerGatherLabels(t *testing.T) {
for _, tt := range gatherLabelsTests {
var acc testutil.Accumulator
d := Docker{
client: nil,
testing: true,
}

for _, label := range tt.include {
d.LabelInclude = append(d.LabelInclude, label)
}
for _, label := range tt.exclude {
d.LabelExclude = append(d.LabelExclude, label)
}

err := d.Gather(&acc)
require.NoError(t, err)

for _, label := range tt.expected {
if !acc.HasTag("docker_container_cpu", label) {
t.Errorf("Didn't get expected label of %s. Test was: Include: %s Exclude %s",
label, tt.include, tt.exclude)
}
}

for _, label := range tt.notexpected {
if acc.HasTag("docker_container_cpu", label) {
t.Errorf("Got unexpected label of %s. Test was: Include: %s Exclude %s",
label, tt.include, tt.exclude)
}
}
}
}

func TestDockerGatherInfo(t *testing.T) {
var acc testutil.Accumulator
d := Docker{
Expand Down Expand Up @@ -294,6 +345,8 @@ func TestDockerGatherInfo(t *testing.T) {
"cpu": "cpu3",
"container_version": "v2.2.2",
"engine_host": "absol",
"label1": "test_value_1",
"label2": "test_value_2",
},
)
acc.AssertContainsTaggedFields(t,
Expand Down Expand Up @@ -340,6 +393,8 @@ func TestDockerGatherInfo(t *testing.T) {
"container_name": "etcd2",
"container_image": "quay.io:4443/coreos/etcd",
"container_version": "v2.2.2",
"label1": "test_value_1",
"label2": "test_value_2",
},
)

Expand Down
8 changes: 8 additions & 0 deletions plugins/inputs/docker/fake_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ func (d FakeDockerClient) ContainerList(octx context.Context, options types.Cont
IP: "0.0.0.0",
},
},
Labels: map[string]string{
"label1": "test_value_1",
"label2": "test_value_2",
},
SizeRw: 0,
SizeRootFs: 0,
}
Expand Down Expand Up @@ -125,6 +129,10 @@ func (d FakeDockerClient) ContainerList(octx context.Context, options types.Cont
IP: "0.0.0.0",
},
},
Labels: map[string]string{
"label1": "test_value_1",
"label2": "test_value_2",
},
SizeRw: 0,
SizeRootFs: 0,
}
Expand Down