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
This commit is contained in:
parent
4d46589d39
commit
36d330fea0
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,6 +1,19 @@
|
||||||
## v0.13 [unreleased]
|
## v0.13 [unreleased]
|
||||||
|
|
||||||
### Release Notes
|
### 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
|
- `tagexclude` and `tagexclude` are now available, which can be used to remove
|
||||||
tags from measurements on inputs and outputs. See
|
tags from measurements on inputs and outputs. See
|
||||||
[the configuration doc](https://github.com/influxdata/telegraf/blob/master/docs/CONFIGURATION.md)
|
[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
|
### Features
|
||||||
- [#1017](https://github.com/influxdata/telegraf/pull/1017): taginclude and tagexclude arguments.
|
- [#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
|
### Bugfixes
|
||||||
- [#921](https://github.com/influxdata/telegraf/pull/921): mqtt_consumer stops gathering metrics. Thanks @chaton78!
|
- [#921](https://github.com/influxdata/telegraf/pull/921): mqtt_consumer stops gathering metrics. Thanks @chaton78!
|
||||||
|
|
|
@ -111,7 +111,8 @@ func (d *Docker) Gather(acc telegraf.Accumulator) error {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := d.gatherContainer(c, acc)
|
err := d.gatherContainer(c, acc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
log.Printf("Error gathering container %s stats: %s\n",
|
||||||
|
c.Names, err.Error())
|
||||||
}
|
}
|
||||||
}(container)
|
}(container)
|
||||||
}
|
}
|
||||||
|
@ -200,9 +201,8 @@ func (d *Docker) gatherContainer(
|
||||||
}
|
}
|
||||||
|
|
||||||
tags := map[string]string{
|
tags := map[string]string{
|
||||||
"cont_id": container.ID,
|
"container_name": cname,
|
||||||
"cont_name": cname,
|
"container_image": container.Image,
|
||||||
"cont_image": container.Image,
|
|
||||||
}
|
}
|
||||||
if len(d.ContainerNames) > 0 {
|
if len(d.ContainerNames) > 0 {
|
||||||
if !sliceContains(cname, d.ContainerNames) {
|
if !sliceContains(cname, d.ContainerNames) {
|
||||||
|
@ -217,15 +217,18 @@ func (d *Docker) gatherContainer(
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
dec := json.NewDecoder(r)
|
dec := json.NewDecoder(r)
|
||||||
if err = dec.Decode(&v); err != nil {
|
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
|
// Add labels to tags
|
||||||
for k, v := range container.Labels {
|
for k, label := range container.Labels {
|
||||||
tags[k] = v
|
tags[k] = label
|
||||||
}
|
}
|
||||||
|
|
||||||
gatherContainerStats(v, acc, tags)
|
gatherContainerStats(v, acc, tags, container.ID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -234,6 +237,7 @@ func gatherContainerStats(
|
||||||
stat *types.StatsJSON,
|
stat *types.StatsJSON,
|
||||||
acc telegraf.Accumulator,
|
acc telegraf.Accumulator,
|
||||||
tags map[string]string,
|
tags map[string]string,
|
||||||
|
id string,
|
||||||
) {
|
) {
|
||||||
now := stat.Read
|
now := stat.Read
|
||||||
|
|
||||||
|
@ -272,8 +276,9 @@ func gatherContainerStats(
|
||||||
"inactive_file": stat.MemoryStats.Stats["inactive_file"],
|
"inactive_file": stat.MemoryStats.Stats["inactive_file"],
|
||||||
"total_pgpgin": stat.MemoryStats.Stats["total_pgpgin"],
|
"total_pgpgin": stat.MemoryStats.Stats["total_pgpgin"],
|
||||||
"usage_percent": calculateMemPercent(stat),
|
"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{}{
|
cpufields := map[string]interface{}{
|
||||||
"usage_total": stat.CPUStats.CPUUsage.TotalUsage,
|
"usage_total": stat.CPUStats.CPUUsage.TotalUsage,
|
||||||
|
@ -284,15 +289,16 @@ func gatherContainerStats(
|
||||||
"throttling_throttled_periods": stat.CPUStats.ThrottlingData.ThrottledPeriods,
|
"throttling_throttled_periods": stat.CPUStats.ThrottlingData.ThrottledPeriods,
|
||||||
"throttling_throttled_time": stat.CPUStats.ThrottlingData.ThrottledTime,
|
"throttling_throttled_time": stat.CPUStats.ThrottlingData.ThrottledTime,
|
||||||
"usage_percent": calculateCPUPercent(stat),
|
"usage_percent": calculateCPUPercent(stat),
|
||||||
|
"container_id": id,
|
||||||
}
|
}
|
||||||
cputags := copyTags(tags)
|
cputags := copyTags(tags)
|
||||||
cputags["cpu"] = "cpu-total"
|
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 {
|
for i, percpu := range stat.CPUStats.CPUUsage.PercpuUsage {
|
||||||
percputags := copyTags(tags)
|
percputags := copyTags(tags)
|
||||||
percputags["cpu"] = fmt.Sprintf("cpu%d", i)
|
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 {
|
for network, netstats := range stat.Networks {
|
||||||
|
@ -305,11 +311,12 @@ func gatherContainerStats(
|
||||||
"rx_packets": netstats.RxPackets,
|
"rx_packets": netstats.RxPackets,
|
||||||
"tx_errors": netstats.TxErrors,
|
"tx_errors": netstats.TxErrors,
|
||||||
"tx_bytes": netstats.TxBytes,
|
"tx_bytes": netstats.TxBytes,
|
||||||
|
"container_id": id,
|
||||||
}
|
}
|
||||||
// Create a new network tag dictionary for the "network" tag
|
// Create a new network tag dictionary for the "network" tag
|
||||||
nettags := copyTags(tags)
|
nettags := copyTags(tags)
|
||||||
nettags["network"] = network
|
nettags["network"] = network
|
||||||
acc.AddFields("docker_net", netfields, nettags, now)
|
acc.AddFields("docker_container_net", netfields, nettags, now)
|
||||||
}
|
}
|
||||||
|
|
||||||
gatherBlockIOMetrics(stat, acc, tags, now)
|
gatherBlockIOMetrics(stat, acc, tags, now)
|
||||||
|
|
|
@ -21,13 +21,12 @@ func TestDockerGatherContainerStats(t *testing.T) {
|
||||||
stats := testStats()
|
stats := testStats()
|
||||||
|
|
||||||
tags := map[string]string{
|
tags := map[string]string{
|
||||||
"cont_id": "foobarbaz",
|
"container_name": "redis",
|
||||||
"cont_name": "redis",
|
"container_image": "redis/image",
|
||||||
"cont_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{}{
|
netfields := map[string]interface{}{
|
||||||
"rx_dropped": uint64(1),
|
"rx_dropped": uint64(1),
|
||||||
"rx_bytes": uint64(2),
|
"rx_bytes": uint64(2),
|
||||||
|
@ -37,10 +36,11 @@ func TestDockerGatherContainerStats(t *testing.T) {
|
||||||
"rx_packets": uint64(2),
|
"rx_packets": uint64(2),
|
||||||
"tx_errors": uint64(3),
|
"tx_errors": uint64(3),
|
||||||
"tx_bytes": uint64(4),
|
"tx_bytes": uint64(4),
|
||||||
|
"container_id": "123456789",
|
||||||
}
|
}
|
||||||
nettags := copyTags(tags)
|
nettags := copyTags(tags)
|
||||||
nettags["network"] = "eth0"
|
nettags["network"] = "eth0"
|
||||||
acc.AssertContainsTaggedFields(t, "docker_net", netfields, nettags)
|
acc.AssertContainsTaggedFields(t, "docker_container_net", netfields, nettags)
|
||||||
|
|
||||||
// test docker_blkio measurement
|
// test docker_blkio measurement
|
||||||
blkiotags := copyTags(tags)
|
blkiotags := copyTags(tags)
|
||||||
|
@ -51,7 +51,7 @@ func TestDockerGatherContainerStats(t *testing.T) {
|
||||||
}
|
}
|
||||||
acc.AssertContainsTaggedFields(t, "docker_blkio", blkiofields, blkiotags)
|
acc.AssertContainsTaggedFields(t, "docker_blkio", blkiofields, blkiotags)
|
||||||
|
|
||||||
// test docker_mem measurement
|
// test docker_container_mem measurement
|
||||||
memfields := map[string]interface{}{
|
memfields := map[string]interface{}{
|
||||||
"max_usage": uint64(1001),
|
"max_usage": uint64(1001),
|
||||||
"usage": uint64(1111),
|
"usage": uint64(1111),
|
||||||
|
@ -87,11 +87,12 @@ func TestDockerGatherContainerStats(t *testing.T) {
|
||||||
"inactive_file": uint64(3),
|
"inactive_file": uint64(3),
|
||||||
"total_pgpgin": uint64(4),
|
"total_pgpgin": uint64(4),
|
||||||
"usage_percent": float64(55.55),
|
"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 := copyTags(tags)
|
||||||
cputags["cpu"] = "cpu-total"
|
cputags["cpu"] = "cpu-total"
|
||||||
cpufields := map[string]interface{}{
|
cpufields := map[string]interface{}{
|
||||||
|
@ -103,20 +104,21 @@ func TestDockerGatherContainerStats(t *testing.T) {
|
||||||
"throttling_throttled_periods": uint64(0),
|
"throttling_throttled_periods": uint64(0),
|
||||||
"throttling_throttled_time": uint64(0),
|
"throttling_throttled_time": uint64(0),
|
||||||
"usage_percent": float64(400.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"
|
cputags["cpu"] = "cpu0"
|
||||||
cpu0fields := map[string]interface{}{
|
cpu0fields := map[string]interface{}{
|
||||||
"usage_total": uint64(1),
|
"usage_total": uint64(1),
|
||||||
}
|
}
|
||||||
acc.AssertContainsTaggedFields(t, "docker_cpu", cpu0fields, cputags)
|
acc.AssertContainsTaggedFields(t, "docker_container_cpu", cpu0fields, cputags)
|
||||||
|
|
||||||
cputags["cpu"] = "cpu1"
|
cputags["cpu"] = "cpu1"
|
||||||
cpu1fields := map[string]interface{}{
|
cpu1fields := map[string]interface{}{
|
||||||
"usage_total": uint64(1002),
|
"usage_total": uint64(1002),
|
||||||
}
|
}
|
||||||
acc.AssertContainsTaggedFields(t, "docker_cpu", cpu1fields, cputags)
|
acc.AssertContainsTaggedFields(t, "docker_container_cpu", cpu1fields, cputags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testStats() *types.StatsJSON {
|
func testStats() *types.StatsJSON {
|
||||||
|
@ -367,19 +369,18 @@ func TestDockerGatherInfo(t *testing.T) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
acc.AssertContainsTaggedFields(t,
|
acc.AssertContainsTaggedFields(t,
|
||||||
"docker_cpu",
|
"docker_container_cpu",
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"usage_total": uint64(1231652),
|
"usage_total": uint64(1231652),
|
||||||
},
|
},
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"cont_id": "b7dfbb9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296e2173",
|
"container_name": "etcd2",
|
||||||
"cont_name": "etcd2",
|
"container_image": "quay.io/coreos/etcd:v2.2.2",
|
||||||
"cont_image": "quay.io/coreos/etcd:v2.2.2",
|
|
||||||
"cpu": "cpu3",
|
"cpu": "cpu3",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
acc.AssertContainsTaggedFields(t,
|
acc.AssertContainsTaggedFields(t,
|
||||||
"docker_mem",
|
"docker_container_mem",
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"total_pgpgout": uint64(0),
|
"total_pgpgout": uint64(0),
|
||||||
"usage_percent": float64(0),
|
"usage_percent": float64(0),
|
||||||
|
@ -415,11 +416,11 @@ func TestDockerGatherInfo(t *testing.T) {
|
||||||
"pgfault": uint64(0),
|
"pgfault": uint64(0),
|
||||||
"usage": uint64(0),
|
"usage": uint64(0),
|
||||||
"limit": uint64(18935443456),
|
"limit": uint64(18935443456),
|
||||||
|
"container_id": "b7dfbb9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296e2173",
|
||||||
},
|
},
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"cont_id": "b7dfbb9478a6ae55e237d4d74f8bbb753f0817192b5081334dc78476296e2173",
|
"container_name": "etcd2",
|
||||||
"cont_name": "etcd2",
|
"container_image": "quay.io/coreos/etcd:v2.2.2",
|
||||||
"cont_image": "quay.io/coreos/etcd:v2.2.2",
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue