Skip to content

Commit

Permalink
optionally disable metrics reporting for non-running containers. Solves
Browse files Browse the repository at this point in the history
adding wildcard support for container inclusion/exclusion. Solves influxdata#2734.
  • Loading branch information
Matteo Cerutti committed May 16, 2017
1 parent a47aa0d commit 162684c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 27 deletions.
11 changes: 11 additions & 0 deletions plugins/inputs/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,32 @@ for the stat structure can be found
## To use TCP, set endpoint = "tcp://[ip]:[port]"
## To use environment variables (ie, docker-machine), set endpoint = "ENV"
endpoint = "unix:///var/run/docker.sock"
## Only collect metrics for these containers, collect all if empty
container_names = []
## Containers to include and exclude. Globs accepted.
## Note that an empty array for both will include all containers
container_name_include = []
container_name_exclude = []
## Timeout for docker list, info, and stats commands
timeout = "5s"
## Whether to report for each container per-device blkio (8:0, 8:1...) and
## network (eth0, eth1, ...) stats or not
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 = []
## disable metrics collection for non-running containers
only_running = true
```

Expand Down
97 changes: 70 additions & 27 deletions plugins/inputs/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,34 @@ type DockerLabelFilter struct {
labelExclude filter.Filter
}

type DockerContainerFilter struct {
containerInclude filter.Filter
containerExclude filter.Filter
}

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

LabelFilter DockerLabelFilter
ContainerInclude []string `toml:"container_name_include"`
ContainerExclude []string `toml:"container_name_exclude"`
ContainerFilter DockerContainerFilter

Timeout internal.Duration
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
labelFiltersCreated bool
testing bool

onlyRunning bool `toml:"only_running"`
}

// infoWrapper wraps client.Client.List for testing.
Expand Down Expand Up @@ -97,8 +108,15 @@ var sampleConfig = `
## To use TCP, set endpoint = "tcp://[ip]:[port]"
## To use environment variables (ie, docker-machine), set endpoint = "ENV"
endpoint = "unix:///var/run/docker.sock"
## Only collect metrics for these containers, collect all if empty
container_names = []
## Containers to include and exclude. Globs accepted.
## Note that an empty array for both will include all containers
container_name_include = []
container_name_exclude = []
## Timeout for docker list, info, and stats commands
timeout = "5s"
Expand All @@ -112,6 +130,10 @@ var sampleConfig = `
## Note that an empty array for both will include all labels as tags
docker_label_include = []
docker_label_exclude = []
## Only monitor running containers
only_running = true
`

// Description returns input description
Expand Down Expand Up @@ -146,14 +168,6 @@ 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 All @@ -176,10 +190,12 @@ func (d *Docker) Gather(acc telegraf.Accumulator) error {
for _, container := range containers {
go func(c types.Container) {
defer wg.Done()
err := d.gatherContainer(c, acc)
if err != nil {
acc.AddError(fmt.Errorf("E! Error gathering container %s stats: %s\n",
c.Names, err.Error()))
if (d.onlyRunning && c.State == "running") || (!d.onlyRunning) {
err := d.gatherContainer(c, acc)
if err != nil {
acc.AddError(fmt.Errorf("E! Error gathering container %s stats: %s\n",
c.Names, err.Error()))
}
}
}(container)
}
Expand Down Expand Up @@ -296,6 +312,11 @@ func (d *Docker) gatherContainer(
return nil
}
}
if len(d.ContainerInclude) == 0 || d.ContainerFilter.containerInclude.Match(cname) {
if len(d.ContainerExclude) > 0 && d.ContainerFilter.containerExclude.Match(cname) {
return nil
}
}

ctx, cancel := context.WithTimeout(context.Background(), d.Timeout.Duration)
defer cancel()
Expand Down Expand Up @@ -624,16 +645,36 @@ func parseSize(sizeStr string) (int64, error) {
return int64(size), nil
}

func (d *Docker) createContainerFilters() error {
if len(d.ContainerInclude) != 0 {
var err error
d.ContainerFilter.containerInclude, err = filter.Compile(d.ContainerInclude)
if err != nil {
return err
}
}

if len(d.ContainerExclude) != 0 {
var err error
d.ContainerFilter.containerExclude, err = filter.Compile(d.ContainerExclude)
if err != nil {
return err
}
}

return nil
}

func (d *Docker) createLabelFilters() error {
if len(d.LabelInclude) != 0 && d.LabelFilter.labelInclude == nil {
if len(d.LabelInclude) != 0 {
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 {
if len(d.LabelExclude) != 0 {
var err error
d.LabelFilter.labelExclude, err = filter.Compile(d.LabelExclude)
if err != nil {
Expand All @@ -645,11 +686,13 @@ func (d *Docker) createLabelFilters() error {
}

func init() {
d := Docker{}
d.PerDevice = true
d.Timeout = internal.Duration{Duration: time.Second * 5}
d.createContainerFilters()
d.createLabelFilters()

inputs.Add("docker", func() telegraf.Input {
return &Docker{
PerDevice: true,
Timeout: internal.Duration{Duration: time.Second * 5},
labelFiltersCreated: false,
}
return &d
})
}
4 changes: 4 additions & 0 deletions plugins/inputs/docker/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ func TestDockerGatherLabels(t *testing.T) {
client: nil,
testing: true,
}
d.createContainerFilters()
d.createLabelFilters()

for _, label := range tt.include {
d.LabelInclude = append(d.LabelInclude, label)
Expand Down Expand Up @@ -301,6 +303,8 @@ func TestDockerGatherInfo(t *testing.T) {
client: nil,
testing: true,
}
d.createContainerFilters()
d.createLabelFilters()

err := acc.GatherError(d.Gather)
require.NoError(t, err)
Expand Down

0 comments on commit 162684c

Please sign in to comment.