From 36d330fea044597a6b3eb3ac9356432d3ea3588a Mon Sep 17 00:00:00 2001 From: Cameron Sparr Date: Tue, 12 Apr 2016 14:59:19 -0600 Subject: [PATCH] docker plugin schema refactor - renaming cont_name and cont_image to container_name and container_image. - cont_id is now a field, called container_id - docker_cpu, docker_mem, docker_net measurements have been renamed to docker_container_cpu, docker_container_mem, and docker_container_net closes #1014 closes #1052 --- CHANGELOG.md | 14 +++++++ plugins/inputs/docker/docker.go | 47 ++++++++++++---------- plugins/inputs/docker/docker_test.go | 59 ++++++++++++++-------------- 3 files changed, 71 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5ea0625..9d869325c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ ## v0.13 [unreleased] ### Release Notes +- **Breaking Change**: docker plugin tags. The cont_id tag no longer exists, it +will now be a field, and be called container_id. Additionally, cont_image and +cont_name are being renamed to container_image and container_name. +- **Breaking Change**: docker plugin measurements. The `docker_cpu`, `docker_mem`, +and `docker_net` measurements are being renamed to `docker_container_cpu`, +`docker_container_mem`, and `docker_container_net`. Why? Because these metrics are +specifically tracking per-container stats. The problem with per-container stats, +in some use-cases, is that if containers are short-lived AND names are not +kept consistent, then the series cardinality will balloon very quickly. +So adding "container" to each metric will: +(1) make it more clear that these metrics are per-container, and +(2) allow users to easily drop per-container metrics if cardinality is an +issue (`namedrop = ["docker_container_*"]`) - `tagexclude` and `tagexclude` are now available, which can be used to remove tags from measurements on inputs and outputs. See [the configuration doc](https://github.com/influxdata/telegraf/blob/master/docs/CONFIGURATION.md) @@ -12,6 +25,7 @@ based on _prefix_ in addition to globs. This means that a filter like ### Features - [#1017](https://github.com/influxdata/telegraf/pull/1017): taginclude and tagexclude arguments. +- [#1015](https://github.com/influxdata/telegraf/pull/1015): Docker plugin schema refactor. ### Bugfixes - [#921](https://github.com/influxdata/telegraf/pull/921): mqtt_consumer stops gathering metrics. Thanks @chaton78! diff --git a/plugins/inputs/docker/docker.go b/plugins/inputs/docker/docker.go index 094bad8ca..897d4f1a5 100644 --- a/plugins/inputs/docker/docker.go +++ b/plugins/inputs/docker/docker.go @@ -111,7 +111,8 @@ func (d *Docker) Gather(acc telegraf.Accumulator) error { defer wg.Done() err := d.gatherContainer(c, acc) if err != nil { - fmt.Println(err.Error()) + log.Printf("Error gathering container %s stats: %s\n", + c.Names, err.Error()) } }(container) } @@ -200,9 +201,8 @@ func (d *Docker) gatherContainer( } tags := map[string]string{ - "cont_id": container.ID, - "cont_name": cname, - "cont_image": container.Image, + "container_name": cname, + "container_image": container.Image, } if len(d.ContainerNames) > 0 { if !sliceContains(cname, d.ContainerNames) { @@ -217,15 +217,18 @@ func (d *Docker) gatherContainer( defer r.Close() dec := json.NewDecoder(r) if err = dec.Decode(&v); err != nil { - log.Printf("Error decoding: %s\n", err.Error()) + if err == io.EOF { + return nil + } + return fmt.Errorf("Error decoding: %s", err.Error()) } // Add labels to tags - for k, v := range container.Labels { - tags[k] = v + for k, label := range container.Labels { + tags[k] = label } - gatherContainerStats(v, acc, tags) + gatherContainerStats(v, acc, tags, container.ID) return nil } @@ -234,6 +237,7 @@ func gatherContainerStats( stat *types.StatsJSON, acc telegraf.Accumulator, tags map[string]string, + id string, ) { now := stat.Read @@ -272,8 +276,9 @@ func gatherContainerStats( "inactive_file": stat.MemoryStats.Stats["inactive_file"], "total_pgpgin": stat.MemoryStats.Stats["total_pgpgin"], "usage_percent": calculateMemPercent(stat), + "container_id": id, } - acc.AddFields("docker_mem", memfields, tags, now) + acc.AddFields("docker_container_mem", memfields, tags, now) cpufields := map[string]interface{}{ "usage_total": stat.CPUStats.CPUUsage.TotalUsage, @@ -284,32 +289,34 @@ func gatherContainerStats( "throttling_throttled_periods": stat.CPUStats.ThrottlingData.ThrottledPeriods, "throttling_throttled_time": stat.CPUStats.ThrottlingData.ThrottledTime, "usage_percent": calculateCPUPercent(stat), + "container_id": id, } cputags := copyTags(tags) cputags["cpu"] = "cpu-total" - acc.AddFields("docker_cpu", cpufields, cputags, now) + acc.AddFields("docker_container_cpu", cpufields, cputags, now) for i, percpu := range stat.CPUStats.CPUUsage.PercpuUsage { percputags := copyTags(tags) percputags["cpu"] = fmt.Sprintf("cpu%d", i) - acc.AddFields("docker_cpu", map[string]interface{}{"usage_total": percpu}, percputags, now) + acc.AddFields("docker_container_cpu", map[string]interface{}{"usage_total": percpu}, percputags, now) } for network, netstats := range stat.Networks { netfields := map[string]interface{}{ - "rx_dropped": netstats.RxDropped, - "rx_bytes": netstats.RxBytes, - "rx_errors": netstats.RxErrors, - "tx_packets": netstats.TxPackets, - "tx_dropped": netstats.TxDropped, - "rx_packets": netstats.RxPackets, - "tx_errors": netstats.TxErrors, - "tx_bytes": netstats.TxBytes, + "rx_dropped": netstats.RxDropped, + "rx_bytes": netstats.RxBytes, + "rx_errors": netstats.RxErrors, + "tx_packets": netstats.TxPackets, + "tx_dropped": netstats.TxDropped, + "rx_packets": netstats.RxPackets, + "tx_errors": netstats.TxErrors, + "tx_bytes": netstats.TxBytes, + "container_id": id, } // Create a new network tag dictionary for the "network" tag nettags := copyTags(tags) nettags["network"] = network - acc.AddFields("docker_net", netfields, nettags, now) + acc.AddFields("docker_container_net", netfields, nettags, now) } gatherBlockIOMetrics(stat, acc, tags, now) diff --git a/plugins/inputs/docker/docker_test.go b/plugins/inputs/docker/docker_test.go index c9fe6cea1..05069ba53 100644 --- a/plugins/inputs/docker/docker_test.go +++ b/plugins/inputs/docker/docker_test.go @@ -21,26 +21,26 @@ func TestDockerGatherContainerStats(t *testing.T) { stats := testStats() tags := map[string]string{ - "cont_id": "foobarbaz", - "cont_name": "redis", - "cont_image": "redis/image", + "container_name": "redis", + "container_image": "redis/image", } - gatherContainerStats(stats, &acc, tags) + gatherContainerStats(stats, &acc, tags, "123456789") - // test docker_net measurement + // test docker_container_net measurement netfields := map[string]interface{}{ - "rx_dropped": uint64(1), - "rx_bytes": uint64(2), - "rx_errors": uint64(3), - "tx_packets": uint64(4), - "tx_dropped": uint64(1), - "rx_packets": uint64(2), - "tx_errors": uint64(3), - "tx_bytes": uint64(4), + "rx_dropped": uint64(1), + "rx_bytes": uint64(2), + "rx_errors": uint64(3), + "tx_packets": uint64(4), + "tx_dropped": uint64(1), + "rx_packets": uint64(2), + "tx_errors": uint64(3), + "tx_bytes": uint64(4), + "container_id": "123456789", } nettags := copyTags(tags) nettags["network"] = "eth0" - acc.AssertContainsTaggedFields(t, "docker_net", netfields, nettags) + acc.AssertContainsTaggedFields(t, "docker_container_net", netfields, nettags) // test docker_blkio measurement blkiotags := copyTags(tags) @@ -51,7 +51,7 @@ func TestDockerGatherContainerStats(t *testing.T) { } acc.AssertContainsTaggedFields(t, "docker_blkio", blkiofields, blkiotags) - // test docker_mem measurement + // test docker_container_mem measurement memfields := map[string]interface{}{ "max_usage": uint64(1001), "usage": uint64(1111), @@ -87,11 +87,12 @@ func TestDockerGatherContainerStats(t *testing.T) { "inactive_file": uint64(3), "total_pgpgin": uint64(4), "usage_percent": float64(55.55), + "container_id": "123456789", } - acc.AssertContainsTaggedFields(t, "docker_mem", memfields, tags) + acc.AssertContainsTaggedFields(t, "docker_container_mem", memfields, tags) - // test docker_cpu measurement + // test docker_container_cpu measurement cputags := copyTags(tags) cputags["cpu"] = "cpu-total" cpufields := map[string]interface{}{ @@ -103,20 +104,21 @@ func TestDockerGatherContainerStats(t *testing.T) { "throttling_throttled_periods": uint64(0), "throttling_throttled_time": uint64(0), "usage_percent": float64(400.0), + "container_id": "123456789", } - acc.AssertContainsTaggedFields(t, "docker_cpu", cpufields, cputags) + acc.AssertContainsTaggedFields(t, "docker_container_cpu", cpufields, cputags) cputags["cpu"] = "cpu0" cpu0fields := map[string]interface{}{ "usage_total": uint64(1), } - acc.AssertContainsTaggedFields(t, "docker_cpu", cpu0fields, cputags) + acc.AssertContainsTaggedFields(t, "docker_container_cpu", cpu0fields, cputags) cputags["cpu"] = "cpu1" cpu1fields := map[string]interface{}{ "usage_total": uint64(1002), } - acc.AssertContainsTaggedFields(t, "docker_cpu", cpu1fields, cputags) + acc.AssertContainsTaggedFields(t, "docker_container_cpu", cpu1fields, cputags) } func testStats() *types.StatsJSON { @@ -367,19 +369,18 @@ func TestDockerGatherInfo(t *testing.T) { }, ) acc.AssertContainsTaggedFields(t, - "docker_cpu", + "docker_container_cpu", map[string]interface{}{ "usage_total": uint64(1231652), }, map[string]string{ - "cont_id": "b7dfbb9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296e2173", - "cont_name": "etcd2", - "cont_image": "quay.io/coreos/etcd:v2.2.2", - "cpu": "cpu3", + "container_name": "etcd2", + "container_image": "quay.io/coreos/etcd:v2.2.2", + "cpu": "cpu3", }, ) acc.AssertContainsTaggedFields(t, - "docker_mem", + "docker_container_mem", map[string]interface{}{ "total_pgpgout": uint64(0), "usage_percent": float64(0), @@ -415,11 +416,11 @@ func TestDockerGatherInfo(t *testing.T) { "pgfault": uint64(0), "usage": uint64(0), "limit": uint64(18935443456), + "container_id": "b7dfbb9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296e2173", }, map[string]string{ - "cont_id": "b7dfbb9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296e2173", - "cont_name": "etcd2", - "cont_image": "quay.io/coreos/etcd:v2.2.2", + "container_name": "etcd2", + "container_image": "quay.io/coreos/etcd:v2.2.2", }, )