mirror of
https://github.com/wahyd4/telegraf.git
synced 2026-08-09 04:36:05 +10:00
Merge branch 'master' into bench/6124
This commit is contained in:
+48
-52
@@ -4,20 +4,17 @@ defaults:
|
||||
working_directory: '/go/src/github.com/influxdata/telegraf'
|
||||
environment:
|
||||
GOFLAGS: -p=8
|
||||
go-1_10: &go-1_10
|
||||
docker:
|
||||
- image: 'quay.io/influxdb/telegraf-ci:1.10.8'
|
||||
go-1_11: &go-1_11
|
||||
docker:
|
||||
- image: 'quay.io/influxdb/telegraf-ci:1.11.13'
|
||||
go-1_12: &go-1_12
|
||||
docker:
|
||||
- image: 'quay.io/influxdb/telegraf-ci:1.12.9'
|
||||
- image: 'quay.io/influxdb/telegraf-ci:1.12.10'
|
||||
go-1_13: &go-1_13
|
||||
docker:
|
||||
- image: 'quay.io/influxdb/telegraf-ci:1.13.1'
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
deps:
|
||||
<<: [ *defaults, *go-1_12 ]
|
||||
<<: [ *defaults, *go-1_13 ]
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
@@ -34,28 +31,13 @@ jobs:
|
||||
paths:
|
||||
- '*'
|
||||
|
||||
test-go-1.10:
|
||||
<<: [ *defaults, *go-1_10 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
# disabled due to gofmt differences (1.10 vs 1.11).
|
||||
#- run: 'make check'
|
||||
- run: 'make test'
|
||||
test-go-1.11:
|
||||
<<: [ *defaults, *go-1_11 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
- run: 'make check'
|
||||
- run: 'make test'
|
||||
test-go-1.12:
|
||||
<<: [ *defaults, *go-1_12 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
- run: 'GOARCH=386 make check'
|
||||
- run: 'GOARCH=386 make test'
|
||||
- run: 'make check'
|
||||
- run: 'make test'
|
||||
test-go-1.12-386:
|
||||
<<: [ *defaults, *go-1_12 ]
|
||||
steps:
|
||||
@@ -63,9 +45,23 @@ jobs:
|
||||
at: '/go/src'
|
||||
- run: 'GOARCH=386 make check'
|
||||
- run: 'GOARCH=386 make test'
|
||||
test-go-1.13:
|
||||
<<: [ *defaults, *go-1_13 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
- run: 'make check'
|
||||
- run: 'make test'
|
||||
test-go-1.13-386:
|
||||
<<: [ *defaults, *go-1_13 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
- run: 'GOARCH=386 make check'
|
||||
- run: 'GOARCH=386 make test'
|
||||
|
||||
package:
|
||||
<<: [ *defaults, *go-1_12 ]
|
||||
<<: [ *defaults, *go-1_13 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
@@ -74,7 +70,7 @@ jobs:
|
||||
path: './build'
|
||||
destination: 'build'
|
||||
release:
|
||||
<<: [ *defaults, *go-1_12 ]
|
||||
<<: [ *defaults, *go-1_13 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
@@ -83,7 +79,7 @@ jobs:
|
||||
path: './build'
|
||||
destination: 'build'
|
||||
nightly:
|
||||
<<: [ *defaults, *go-1_12 ]
|
||||
<<: [ *defaults, *go-1_13 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
@@ -100,18 +96,6 @@ workflows:
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- 'test-go-1.10':
|
||||
requires:
|
||||
- 'deps'
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- 'test-go-1.11':
|
||||
requires:
|
||||
- 'deps'
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- 'test-go-1.12':
|
||||
requires:
|
||||
- 'deps'
|
||||
@@ -124,18 +108,30 @@ workflows:
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- 'test-go-1.13':
|
||||
requires:
|
||||
- 'deps'
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- 'test-go-1.13-386':
|
||||
requires:
|
||||
- 'deps'
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- 'package':
|
||||
requires:
|
||||
- 'test-go-1.10'
|
||||
- 'test-go-1.11'
|
||||
- 'test-go-1.12'
|
||||
- 'test-go-1.12-386'
|
||||
- 'test-go-1.13'
|
||||
- 'test-go-1.13-386'
|
||||
- 'release':
|
||||
requires:
|
||||
- 'test-go-1.10'
|
||||
- 'test-go-1.11'
|
||||
- 'test-go-1.12'
|
||||
- 'test-go-1.12-386'
|
||||
- 'test-go-1.13'
|
||||
- 'test-go-1.13-386'
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
@@ -144,24 +140,24 @@ workflows:
|
||||
nightly:
|
||||
jobs:
|
||||
- 'deps'
|
||||
- 'test-go-1.10':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'test-go-1.11':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'test-go-1.12':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'test-go-1.12-386':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'test-go-1.13':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'test-go-1.13-386':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'nightly':
|
||||
requires:
|
||||
- 'test-go-1.10'
|
||||
- 'test-go-1.11'
|
||||
- 'test-go-1.12'
|
||||
- 'test-go-1.12-386'
|
||||
- 'test-go-1.13'
|
||||
- 'test-go-1.13-386'
|
||||
triggers:
|
||||
- schedule:
|
||||
cron: "0 7 * * *"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
cla-checker:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Check CLA"
|
||||
steps:
|
||||
- name: "Lookup PR Author"
|
||||
uses: influxdata/clasee@v1
|
||||
with:
|
||||
spreadsheet: "1jnRZYSw83oa6hcEBb1lxK6nNvXrWnOzPT8Bz9iR4Q8s"
|
||||
range: "Form Responses!E:E"
|
||||
env:
|
||||
CLASEE_SECRET: ${{ secrets.CLASEE_SECRET }}
|
||||
+29
-1
@@ -1,8 +1,17 @@
|
||||
## v1.13 [unreleased]
|
||||
|
||||
#### Release Notes
|
||||
|
||||
- Official packages are built with Go 1.13.1.
|
||||
|
||||
#### New Inputs
|
||||
|
||||
- [azure_storage_queue](/plugins/inputs/azure_storage_queue/README.md) - Contributed by @mjiderhamn
|
||||
- [suricata](/plugins/inputs/suricata/README.md) - Contributed by @satta
|
||||
|
||||
#### New Aggregators
|
||||
|
||||
- [merge](/plugins/aggregators/merge/README.md) - Contributed by @influxdata
|
||||
|
||||
#### Features
|
||||
|
||||
@@ -10,14 +19,33 @@
|
||||
- [#6361](https://github.com/influxdata/telegraf/pull/6361): Add ability to read query from file to postgresql_extensible input.
|
||||
- [#5921](https://github.com/influxdata/telegraf/pull/5921): Add replication metrics to the redis input.
|
||||
- [#6177](https://github.com/influxdata/telegraf/pull/6177): Support NX-OS telemetry extensions in cisco_telemetry_mdt.
|
||||
- [#6415](https://github.com/influxdata/telegraf/pull/6415): Allow graphite parser to create Inf and NaN values.
|
||||
- [#6434](https://github.com/influxdata/telegraf/pull/6434): Use prefix base detection for ints in grok parser.
|
||||
- [#6465](https://github.com/influxdata/telegraf/pull/6465): Add more performance counter metrics to sqlserver input.
|
||||
- [#6476](https://github.com/influxdata/telegraf/pull/6476): Add millisecond unix time support to grok parser.
|
||||
- [#6473](https://github.com/influxdata/telegraf/pull/6473): Add container id as optional source tag to docker and docker_log input.
|
||||
|
||||
## v1.12.2 [unreleased]
|
||||
## v1.12.3 [2019-10-07]
|
||||
|
||||
#### Bugfixes
|
||||
|
||||
- [#6445](https://github.com/influxdata/telegraf/issues/6445): Use batch serialization format in exec output.
|
||||
- [#6455](https://github.com/influxdata/telegraf/issues/6455): Build official packages with Go 1.12.10.
|
||||
- [#6464](https://github.com/influxdata/telegraf/pull/6464): Use case insensitive serial numer match in smart input.
|
||||
- [#6469](https://github.com/influxdata/telegraf/pull/6469): Add auth header only when env var is set.
|
||||
- [#6468](https://github.com/influxdata/telegraf/pull/6468): Fix running multiple mysql and sqlserver plugin instances.
|
||||
- [#6471](https://github.com/influxdata/telegraf/issues/6471): Fix database routing on retry with exclude_database_tag.
|
||||
- [#6488](https://github.com/influxdata/telegraf/issues/6488): Fix logging panic in exec input with nagios data format.
|
||||
|
||||
## v1.12.2 [2019-09-24]
|
||||
|
||||
#### Bugfixes
|
||||
|
||||
- [#6386](https://github.com/influxdata/telegraf/issues/6386): Fix detection of layout timestamps in csv and json parser.
|
||||
- [#6394](https://github.com/influxdata/telegraf/issues/6394): Fix parsing of BATTDATE in apcupsd input.
|
||||
- [#6398](https://github.com/influxdata/telegraf/issues/6398): Keep boolean values listed in json_string_fields.
|
||||
- [#6393](https://github.com/influxdata/telegraf/issues/6393): Disable Go plugin support in official builds.
|
||||
- [#6391](https://github.com/influxdata/telegraf/issues/6391): Fix path handling issues in cisco_telemetry_gnmi.
|
||||
|
||||
## v1.12.1 [2019-09-10]
|
||||
|
||||
|
||||
@@ -129,17 +129,12 @@ plugin-%:
|
||||
@echo "Starting dev environment for $${$(@)} input plugin..."
|
||||
@docker-compose -f plugins/inputs/$${$(@)}/dev/docker-compose.yml up
|
||||
|
||||
.PHONY: ci-1.13
|
||||
ci-1.13:
|
||||
docker build -t quay.io/influxdb/telegraf-ci:1.13.1 - < scripts/ci-1.13.docker
|
||||
docker push quay.io/influxdb/telegraf-ci:1.13.1
|
||||
|
||||
.PHONY: ci-1.12
|
||||
ci-1.12:
|
||||
docker build -t quay.io/influxdb/telegraf-ci:1.12.9 - < scripts/ci-1.12.docker
|
||||
docker push quay.io/influxdb/telegraf-ci:1.12.9
|
||||
|
||||
.PHONY: ci-1.11
|
||||
ci-1.11:
|
||||
docker build -t quay.io/influxdb/telegraf-ci:1.11.13 - < scripts/ci-1.11.docker
|
||||
docker push quay.io/influxdb/telegraf-ci:1.11.13
|
||||
|
||||
.PHONY: ci-1.10
|
||||
ci-1.10:
|
||||
docker build -t quay.io/influxdb/telegraf-ci:1.10.8 - < scripts/ci-1.10.docker
|
||||
docker push quay.io/influxdb/telegraf-ci:1.10.8
|
||||
docker build -t quay.io/influxdb/telegraf-ci:1.12.10 - < scripts/ci-1.12.docker
|
||||
docker push quay.io/influxdb/telegraf-ci:1.12.10
|
||||
|
||||
@@ -40,9 +40,9 @@ Ansible role: https://github.com/rossmcdonald/telegraf
|
||||
|
||||
### From Source:
|
||||
|
||||
Telegraf requires golang version 1.10 or newer, the Makefile requires GNU make.
|
||||
Telegraf requires golang version 1.12 or newer, the Makefile requires GNU make.
|
||||
|
||||
1. [Install Go](https://golang.org/doc/install) >=1.10 (1.12 recommended)
|
||||
1. [Install Go](https://golang.org/doc/install) >=1.12 (1.13 recommended)
|
||||
2. [Install dep](https://golang.github.io/dep/docs/installation.html) ==v0.5.0
|
||||
3. Download Telegraf source:
|
||||
```
|
||||
@@ -276,6 +276,7 @@ For documentation on the latest development code see the [documentation index][d
|
||||
* [sql server](./plugins/inputs/sqlserver) (microsoft)
|
||||
* [stackdriver](./plugins/inputs/stackdriver)
|
||||
* [statsd](./plugins/inputs/statsd)
|
||||
* [suricata](./plugins/inputs/suricata)
|
||||
* [swap](./plugins/inputs/swap)
|
||||
* [syslog](./plugins/inputs/syslog)
|
||||
* [sysstat](./plugins/inputs/sysstat)
|
||||
@@ -353,6 +354,7 @@ For documentation on the latest development code see the [documentation index][d
|
||||
* [basicstats](./plugins/aggregators/basicstats)
|
||||
* [final](./plugins/aggregators/final)
|
||||
* [histogram](./plugins/aggregators/histogram)
|
||||
* [merge](./plugins/aggregators/merge)
|
||||
* [minmax](./plugins/aggregators/minmax)
|
||||
* [valuecounter](./plugins/aggregators/valuecounter)
|
||||
|
||||
|
||||
+2
-2
@@ -13,11 +13,11 @@ platform: x64
|
||||
|
||||
install:
|
||||
- IF NOT EXIST "C:\Cache" mkdir C:\Cache
|
||||
- IF NOT EXIST "C:\Cache\go1.12.9.msi" curl -o "C:\Cache\go1.12.9.msi" https://storage.googleapis.com/golang/go1.12.9.windows-amd64.msi
|
||||
- IF NOT EXIST "C:\Cache\go1.13.1.msi" curl -o "C:\Cache\go1.13.1.msi" https://storage.googleapis.com/golang/go1.13.1.windows-amd64.msi
|
||||
- IF NOT EXIST "C:\Cache\gnuwin32-bin.zip" curl -o "C:\Cache\gnuwin32-bin.zip" https://dl.influxdata.com/telegraf/ci/make-3.81-bin.zip
|
||||
- IF NOT EXIST "C:\Cache\gnuwin32-dep.zip" curl -o "C:\Cache\gnuwin32-dep.zip" https://dl.influxdata.com/telegraf/ci/make-3.81-dep.zip
|
||||
- IF EXIST "C:\Go" rmdir /S /Q C:\Go
|
||||
- msiexec.exe /i "C:\Cache\go1.12.9.msi" /quiet
|
||||
- msiexec.exe /i "C:\Cache\go1.13.1.msi" /quiet
|
||||
- 7z x "C:\Cache\gnuwin32-bin.zip" -oC:\GnuWin32 -y
|
||||
- 7z x "C:\Cache\gnuwin32-dep.zip" -oC:\GnuWin32 -y
|
||||
- go get -d github.com/golang/dep
|
||||
|
||||
@@ -10,9 +10,6 @@ import (
|
||||
_ "net/http/pprof" // Comment this line to disable pprof endpoint.
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -21,6 +18,7 @@ import (
|
||||
"github.com/influxdata/telegraf/agent"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/config"
|
||||
"github.com/influxdata/telegraf/internal/goplugin"
|
||||
"github.com/influxdata/telegraf/logger"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/all"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
@@ -116,36 +114,6 @@ func reloadLoop(
|
||||
}
|
||||
}
|
||||
|
||||
// loadExternalPlugins loads external plugins from shared libraries (.so, .dll, etc.)
|
||||
// in the specified directory.
|
||||
func loadExternalPlugins(rootDir string) error {
|
||||
return filepath.Walk(rootDir, func(pth string, info os.FileInfo, err error) error {
|
||||
// Stop if there was an error.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ignore directories.
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ignore files that aren't shared libraries.
|
||||
ext := strings.ToLower(path.Ext(pth))
|
||||
if ext != ".so" && ext != ".dll" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load plugin.
|
||||
_, err = plugin.Open(pth)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading %s: %s", pth, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func runAgent(ctx context.Context,
|
||||
inputFilters []string,
|
||||
outputFilters []string,
|
||||
@@ -317,7 +285,7 @@ func main() {
|
||||
// Load external plugins, if requested.
|
||||
if *fPlugins != "" {
|
||||
log.Printf("I! Loading external plugins from: %s", *fPlugins)
|
||||
if err := loadExternalPlugins(*fPlugins); err != nil {
|
||||
if err := goplugin.LoadExternalPlugins(*fPlugins); err != nil {
|
||||
log.Fatal("E! " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +188,7 @@ driven operation.
|
||||
|
||||
Parameters that can be used with any input plugin:
|
||||
|
||||
- **alias**: Name an instance of a plugin.
|
||||
- **interval**: How often to gather this metric. Normal plugins use a single
|
||||
global interval, but if one particular input should be run less or more
|
||||
often, you can configure that here.
|
||||
|
||||
@@ -841,13 +841,14 @@ func loadConfig(config string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func fetchConfig(u *url.URL) ([]byte, error) {
|
||||
v := os.Getenv("INFLUX_TOKEN")
|
||||
|
||||
req, err := http.NewRequest("GET", u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Authorization", "Token "+v)
|
||||
|
||||
if v, exists := os.LookupEnv("INFLUX_TOKEN"); exists {
|
||||
req.Header.Add("Authorization", "Token "+v)
|
||||
}
|
||||
req.Header.Add("Accept", "application/toml")
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
|
||||
@@ -158,6 +158,11 @@ func TestConfig_LoadDirectory(t *testing.T) {
|
||||
MeasurementSuffix: "_myothercollector",
|
||||
}
|
||||
eConfig.Tags = make(map[string]string)
|
||||
|
||||
exec := c.Inputs[1].Input.(*exec.Exec)
|
||||
require.NotNil(t, exec.Log)
|
||||
exec.Log = nil
|
||||
|
||||
assert.Equal(t, ex, c.Inputs[1].Input,
|
||||
"Merged Testdata did not produce a correct exec struct.")
|
||||
assert.Equal(t, eConfig, c.Inputs[1].Config,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// +build !goplugin
|
||||
|
||||
package goplugin
|
||||
|
||||
import "errors"
|
||||
|
||||
func LoadExternalPlugins(rootDir string) error {
|
||||
return errors.New("go plugin support is not enabled")
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// +build goplugin
|
||||
|
||||
package goplugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// loadExternalPlugins loads external plugins from shared libraries (.so, .dll, etc.)
|
||||
// in the specified directory.
|
||||
func LoadExternalPlugins(rootDir string) error {
|
||||
return filepath.Walk(rootDir, func(pth string, info os.FileInfo, err error) error {
|
||||
// Stop if there was an error.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ignore directories.
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ignore files that aren't shared libraries.
|
||||
ext := strings.ToLower(path.Ext(pth))
|
||||
if ext != ".so" && ext != ".dll" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load plugin.
|
||||
_, err = plugin.Open(pth)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading %s: %s", pth, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func (r *RunningAggregator) Add(m telegraf.Metric) bool {
|
||||
defer r.Unlock()
|
||||
|
||||
if m.Time().Before(r.periodStart.Add(-r.Config.Grace)) || m.Time().After(r.periodEnd.Add(r.Config.Delay)) {
|
||||
r.log.Debugf("metric is outside aggregation window; discarding. %s: m: %s e: %s g: %s",
|
||||
r.log.Debugf("Metric is outside aggregation window; discarding. %s: m: %s e: %s g: %s",
|
||||
m.Time(), r.periodStart, r.periodEnd, r.Config.Grace)
|
||||
r.MetricsDropped.Incr(1)
|
||||
return r.Config.DropOriginal
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/basicstats"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/final"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/histogram"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/merge"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/minmax"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/valuecounter"
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@ emitting the aggregate every `period` seconds.
|
||||
[[aggregators.basicstats]]
|
||||
## The period on which to flush & clear the aggregator.
|
||||
period = "30s"
|
||||
|
||||
## If true, the original metric will be dropped by the
|
||||
## aggregator and will not get sent to the output plugins.
|
||||
drop_original = false
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package basicstats
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
@@ -10,6 +9,7 @@ import (
|
||||
|
||||
type BasicStats struct {
|
||||
Stats []string `toml:"stats"`
|
||||
Log telegraf.Logger
|
||||
|
||||
cache map[uint64]aggregate
|
||||
statsConfig *configuredStats
|
||||
@@ -28,9 +28,9 @@ type configuredStats struct {
|
||||
}
|
||||
|
||||
func NewBasicStats() *BasicStats {
|
||||
mm := &BasicStats{}
|
||||
mm.Reset()
|
||||
return mm
|
||||
return &BasicStats{
|
||||
cache: make(map[uint64]aggregate),
|
||||
}
|
||||
}
|
||||
|
||||
type aggregate struct {
|
||||
@@ -53,6 +53,7 @@ type basicstats struct {
|
||||
var sampleConfig = `
|
||||
## The period on which to flush & clear the aggregator.
|
||||
period = "30s"
|
||||
|
||||
## If true, the original metric will be dropped by the
|
||||
## aggregator and will not get sent to the output plugins.
|
||||
drop_original = false
|
||||
@@ -61,17 +62,17 @@ var sampleConfig = `
|
||||
# stats = ["count", "min", "max", "mean", "stdev", "s2", "sum"]
|
||||
`
|
||||
|
||||
func (m *BasicStats) SampleConfig() string {
|
||||
func (*BasicStats) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (m *BasicStats) Description() string {
|
||||
func (*BasicStats) Description() string {
|
||||
return "Keep the aggregate basicstats of each metric passing through."
|
||||
}
|
||||
|
||||
func (m *BasicStats) Add(in telegraf.Metric) {
|
||||
func (b *BasicStats) Add(in telegraf.Metric) {
|
||||
id := in.HashID()
|
||||
if _, ok := m.cache[id]; !ok {
|
||||
if _, ok := b.cache[id]; !ok {
|
||||
// hit an uncached metric, create caches for first time:
|
||||
a := aggregate{
|
||||
name: in.Name(),
|
||||
@@ -92,13 +93,13 @@ func (m *BasicStats) Add(in telegraf.Metric) {
|
||||
}
|
||||
}
|
||||
}
|
||||
m.cache[id] = a
|
||||
b.cache[id] = a
|
||||
} else {
|
||||
for _, field := range in.FieldList() {
|
||||
if fv, ok := convert(field.Value); ok {
|
||||
if _, ok := m.cache[id].fields[field.Key]; !ok {
|
||||
if _, ok := b.cache[id].fields[field.Key]; !ok {
|
||||
// hit an uncached field of a cached metric
|
||||
m.cache[id].fields[field.Key] = basicstats{
|
||||
b.cache[id].fields[field.Key] = basicstats{
|
||||
count: 1,
|
||||
min: fv,
|
||||
max: fv,
|
||||
@@ -111,7 +112,7 @@ func (m *BasicStats) Add(in telegraf.Metric) {
|
||||
continue
|
||||
}
|
||||
|
||||
tmp := m.cache[id].fields[field.Key]
|
||||
tmp := b.cache[id].fields[field.Key]
|
||||
//https://en.m.wikipedia.org/wiki/Algorithms_for_calculating_variance
|
||||
//variable initialization
|
||||
x := fv
|
||||
@@ -138,32 +139,30 @@ func (m *BasicStats) Add(in telegraf.Metric) {
|
||||
//diff compute
|
||||
tmp.diff = fv - tmp.LAST
|
||||
//store final data
|
||||
m.cache[id].fields[field.Key] = tmp
|
||||
b.cache[id].fields[field.Key] = tmp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *BasicStats) Push(acc telegraf.Accumulator) {
|
||||
config := getConfiguredStats(m)
|
||||
|
||||
for _, aggregate := range m.cache {
|
||||
func (b *BasicStats) Push(acc telegraf.Accumulator) {
|
||||
for _, aggregate := range b.cache {
|
||||
fields := map[string]interface{}{}
|
||||
for k, v := range aggregate.fields {
|
||||
|
||||
if config.count {
|
||||
if b.statsConfig.count {
|
||||
fields[k+"_count"] = v.count
|
||||
}
|
||||
if config.min {
|
||||
if b.statsConfig.min {
|
||||
fields[k+"_min"] = v.min
|
||||
}
|
||||
if config.max {
|
||||
if b.statsConfig.max {
|
||||
fields[k+"_max"] = v.max
|
||||
}
|
||||
if config.mean {
|
||||
if b.statsConfig.mean {
|
||||
fields[k+"_mean"] = v.mean
|
||||
}
|
||||
if config.sum {
|
||||
if b.statsConfig.sum {
|
||||
fields[k+"_sum"] = v.sum
|
||||
}
|
||||
|
||||
@@ -171,16 +170,16 @@ func (m *BasicStats) Push(acc telegraf.Accumulator) {
|
||||
if v.count > 1 {
|
||||
variance := v.M2 / (v.count - 1)
|
||||
|
||||
if config.variance {
|
||||
if b.statsConfig.variance {
|
||||
fields[k+"_s2"] = variance
|
||||
}
|
||||
if config.stdev {
|
||||
if b.statsConfig.stdev {
|
||||
fields[k+"_stdev"] = math.Sqrt(variance)
|
||||
}
|
||||
if config.diff {
|
||||
if b.statsConfig.diff {
|
||||
fields[k+"_diff"] = v.diff
|
||||
}
|
||||
if config.non_negative_diff && v.diff >= 0 {
|
||||
if b.statsConfig.non_negative_diff && v.diff >= 0 {
|
||||
fields[k+"_non_negative_diff"] = v.diff
|
||||
}
|
||||
|
||||
@@ -194,14 +193,12 @@ func (m *BasicStats) Push(acc telegraf.Accumulator) {
|
||||
}
|
||||
}
|
||||
|
||||
func parseStats(names []string) *configuredStats {
|
||||
|
||||
// member function for logging.
|
||||
func (b *BasicStats) parseStats() *configuredStats {
|
||||
parsed := &configuredStats{}
|
||||
|
||||
for _, name := range names {
|
||||
|
||||
for _, name := range b.Stats {
|
||||
switch name {
|
||||
|
||||
case "count":
|
||||
parsed.count = true
|
||||
case "min":
|
||||
@@ -222,45 +219,32 @@ func parseStats(names []string) *configuredStats {
|
||||
parsed.non_negative_diff = true
|
||||
|
||||
default:
|
||||
log.Printf("W! Unrecognized basic stat '%s', ignoring", name)
|
||||
b.Log.Warnf("Unrecognized basic stat %q, ignoring", name)
|
||||
}
|
||||
}
|
||||
|
||||
return parsed
|
||||
}
|
||||
|
||||
func defaultStats() *configuredStats {
|
||||
|
||||
defaults := &configuredStats{}
|
||||
|
||||
defaults.count = true
|
||||
defaults.min = true
|
||||
defaults.max = true
|
||||
defaults.mean = true
|
||||
defaults.variance = true
|
||||
defaults.stdev = true
|
||||
defaults.sum = false
|
||||
defaults.non_negative_diff = false
|
||||
|
||||
return defaults
|
||||
}
|
||||
|
||||
func getConfiguredStats(m *BasicStats) *configuredStats {
|
||||
|
||||
if m.statsConfig == nil {
|
||||
|
||||
if m.Stats == nil {
|
||||
m.statsConfig = defaultStats()
|
||||
} else {
|
||||
m.statsConfig = parseStats(m.Stats)
|
||||
func (b *BasicStats) getConfiguredStats() {
|
||||
if b.Stats == nil {
|
||||
b.statsConfig = &configuredStats{
|
||||
count: true,
|
||||
min: true,
|
||||
max: true,
|
||||
mean: true,
|
||||
variance: true,
|
||||
stdev: true,
|
||||
sum: false,
|
||||
non_negative_diff: false,
|
||||
}
|
||||
} else {
|
||||
b.statsConfig = b.parseStats()
|
||||
}
|
||||
|
||||
return m.statsConfig
|
||||
}
|
||||
|
||||
func (m *BasicStats) Reset() {
|
||||
m.cache = make(map[uint64]aggregate)
|
||||
func (b *BasicStats) Reset() {
|
||||
b.cache = make(map[uint64]aggregate)
|
||||
}
|
||||
|
||||
func convert(in interface{}) (float64, bool) {
|
||||
@@ -276,6 +260,12 @@ func convert(in interface{}) (float64, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BasicStats) Init() error {
|
||||
b.getConfiguredStats()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
aggregators.Add("basicstats", func() telegraf.Aggregator {
|
||||
return NewBasicStats()
|
||||
|
||||
@@ -39,6 +39,8 @@ var m2, _ = metric.New("m1",
|
||||
|
||||
func BenchmarkApply(b *testing.B) {
|
||||
minmax := NewBasicStats()
|
||||
minmax.Log = testutil.Logger{}
|
||||
minmax.getConfiguredStats()
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
minmax.Add(m1)
|
||||
@@ -50,6 +52,8 @@ func BenchmarkApply(b *testing.B) {
|
||||
func TestBasicStatsWithPeriod(t *testing.T) {
|
||||
acc := testutil.Accumulator{}
|
||||
minmax := NewBasicStats()
|
||||
minmax.Log = testutil.Logger{}
|
||||
minmax.getConfiguredStats()
|
||||
|
||||
minmax.Add(m1)
|
||||
minmax.Add(m2)
|
||||
@@ -106,6 +110,8 @@ func TestBasicStatsWithPeriod(t *testing.T) {
|
||||
func TestBasicStatsDifferentPeriods(t *testing.T) {
|
||||
acc := testutil.Accumulator{}
|
||||
minmax := NewBasicStats()
|
||||
minmax.Log = testutil.Logger{}
|
||||
minmax.getConfiguredStats()
|
||||
|
||||
minmax.Add(m1)
|
||||
minmax.Push(&acc)
|
||||
@@ -181,6 +187,8 @@ func TestBasicStatsWithOnlyCount(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"count"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -208,6 +216,8 @@ func TestBasicStatsWithOnlyMin(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"min"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -235,6 +245,8 @@ func TestBasicStatsWithOnlyMax(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"max"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -262,6 +274,8 @@ func TestBasicStatsWithOnlyMean(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"mean"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -289,6 +303,8 @@ func TestBasicStatsWithOnlySum(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"sum"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -347,6 +363,8 @@ func TestBasicStatsWithOnlySumFloatingPointErrata(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"sum"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(sum1)
|
||||
aggregator.Add(sum2)
|
||||
@@ -368,6 +386,8 @@ func TestBasicStatsWithOnlyVariance(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"s2"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -393,6 +413,8 @@ func TestBasicStatsWithOnlyStandardDeviation(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"stdev"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -418,6 +440,8 @@ func TestBasicStatsWithMinAndMax(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"min", "max"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -452,6 +476,8 @@ func TestBasicStatsWithDiff(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"diff"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -477,6 +503,8 @@ func TestBasicStatsWithNonNegativeDiff(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"non_negative_diff"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -500,7 +528,9 @@ func TestBasicStatsWithNonNegativeDiff(t *testing.T) {
|
||||
func TestBasicStatsWithAllStats(t *testing.T) {
|
||||
acc := testutil.Accumulator{}
|
||||
minmax := NewBasicStats()
|
||||
minmax.Log = testutil.Logger{}
|
||||
minmax.Stats = []string{"count", "min", "max", "mean", "stdev", "s2", "sum"}
|
||||
minmax.getConfiguredStats()
|
||||
|
||||
minmax.Add(m1)
|
||||
minmax.Add(m2)
|
||||
@@ -564,6 +594,8 @@ func TestBasicStatsWithNoStats(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -579,6 +611,8 @@ func TestBasicStatsWithUnknownStat(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Stats = []string{"crazy"}
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
@@ -596,6 +630,8 @@ func TestBasicStatsWithUnknownStat(t *testing.T) {
|
||||
func TestBasicStatsWithDefaultStats(t *testing.T) {
|
||||
|
||||
aggregator := NewBasicStats()
|
||||
aggregator.Log = testutil.Logger{}
|
||||
aggregator.getConfiguredStats()
|
||||
|
||||
aggregator.Add(m1)
|
||||
aggregator.Add(m2)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Merge Aggregator
|
||||
|
||||
Merge metrics together into a metric with multiple fields into the most memory
|
||||
and network transfer efficient form.
|
||||
|
||||
Use this plugin when fields are split over multiple metrics, with the same
|
||||
measurement, tag set and timestamp. By merging into a single metric they can
|
||||
be handled more efficiently by the output.
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[[aggregators.merge]]
|
||||
# no configuration
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```diff
|
||||
- cpu,host=localhost usage_time=42 1567562620000000000
|
||||
- cpu,host=localhost idle_time=42 1567562620000000000
|
||||
+ cpu,host=localhost idle_time=42,usage_time=42 1567562620000000000
|
||||
```
|
||||
@@ -0,0 +1,62 @@
|
||||
package seriesgrouper
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/metric"
|
||||
"github.com/influxdata/telegraf/plugins/aggregators"
|
||||
)
|
||||
|
||||
const (
|
||||
description = "Merge metrics into multifield metrics by series key"
|
||||
sampleConfig = ""
|
||||
)
|
||||
|
||||
type Merge struct {
|
||||
grouper *metric.SeriesGrouper
|
||||
log telegraf.Logger
|
||||
}
|
||||
|
||||
func (a *Merge) Init() error {
|
||||
a.grouper = metric.NewSeriesGrouper()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Merge) Description() string {
|
||||
return description
|
||||
}
|
||||
|
||||
func (a *Merge) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (a *Merge) Add(m telegraf.Metric) {
|
||||
tags := m.Tags()
|
||||
for _, field := range m.FieldList() {
|
||||
err := a.grouper.Add(m.Name(), tags, m.Time(), field.Key, field.Value)
|
||||
if err != nil {
|
||||
a.log.Errorf("Error adding metric: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Merge) Push(acc telegraf.Accumulator) {
|
||||
// Always use nanosecond precision to avoid rounding metrics that were
|
||||
// produced at a precision higher than the agent default.
|
||||
acc.SetPrecision(time.Nanosecond)
|
||||
|
||||
for _, m := range a.grouper.Metrics() {
|
||||
acc.AddMetric(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Merge) Reset() {
|
||||
a.grouper = metric.NewSeriesGrouper()
|
||||
}
|
||||
|
||||
func init() {
|
||||
aggregators.Add("merge", func() telegraf.Aggregator {
|
||||
return &Merge{}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package seriesgrouper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSimple(t *testing.T) {
|
||||
plugin := &Merge{}
|
||||
|
||||
err := plugin.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
plugin.Add(
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
plugin.Add(
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_guest": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
var acc testutil.Accumulator
|
||||
plugin.Push(&acc)
|
||||
|
||||
expected := []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
"time_guest": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
}
|
||||
|
||||
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
|
||||
}
|
||||
|
||||
func TestNanosecondPrecision(t *testing.T) {
|
||||
plugin := &Merge{}
|
||||
|
||||
err := plugin.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
plugin.Add(
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 1),
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
plugin.Add(
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_guest": 42,
|
||||
},
|
||||
time.Unix(0, 1),
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
var acc testutil.Accumulator
|
||||
acc.SetPrecision(time.Second)
|
||||
plugin.Push(&acc)
|
||||
|
||||
expected := []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
"time_guest": 42,
|
||||
},
|
||||
time.Unix(0, 1),
|
||||
),
|
||||
}
|
||||
|
||||
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
|
||||
}
|
||||
|
||||
func TestReset(t *testing.T) {
|
||||
plugin := &Merge{}
|
||||
|
||||
err := plugin.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
plugin.Add(
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
var acc testutil.Accumulator
|
||||
plugin.Push(&acc)
|
||||
|
||||
plugin.Reset()
|
||||
|
||||
plugin.Add(
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_guest": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
plugin.Push(&acc)
|
||||
|
||||
expected := []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_idle": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
testutil.MustMetric(
|
||||
"cpu",
|
||||
map[string]string{
|
||||
"cpu": "cpu0",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"time_guest": 42,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
}
|
||||
|
||||
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics())
|
||||
}
|
||||
@@ -140,6 +140,7 @@ import (
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/sqlserver"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/stackdriver"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/statsd"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/suricata"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/swap"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/syslog"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/sysstat"
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -55,6 +54,7 @@ type AMQPConsumer struct {
|
||||
tls.ClientConfig
|
||||
|
||||
ContentEncoding string `toml:"content_encoding"`
|
||||
Log telegraf.Logger
|
||||
|
||||
deliveries map[telegraf.TrackingID]amqp.Delivery
|
||||
|
||||
@@ -241,11 +241,11 @@ func (a *AMQPConsumer) Start(acc telegraf.Accumulator) error {
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("I! [inputs.amqp_consumer] connection closed: %s; trying to reconnect", err)
|
||||
a.Log.Infof("Connection closed: %s; trying to reconnect", err)
|
||||
for {
|
||||
msgs, err := a.connect(amqpConf)
|
||||
if err != nil {
|
||||
log.Printf("E! AMQP connection failed: %s", err)
|
||||
a.Log.Errorf("AMQP connection failed: %s", err)
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
}
|
||||
@@ -272,14 +272,14 @@ func (a *AMQPConsumer) connect(amqpConf *amqp.Config) (<-chan amqp.Delivery, err
|
||||
p := rand.Perm(len(brokers))
|
||||
for _, n := range p {
|
||||
broker := brokers[n]
|
||||
log.Printf("D! [inputs.amqp_consumer] connecting to %q", broker)
|
||||
a.Log.Debugf("Connecting to %q", broker)
|
||||
conn, err := amqp.DialConfig(broker, *amqpConf)
|
||||
if err == nil {
|
||||
a.conn = conn
|
||||
log.Printf("D! [inputs.amqp_consumer] connected to %q", broker)
|
||||
a.Log.Debugf("Connected to %q", broker)
|
||||
break
|
||||
}
|
||||
log.Printf("D! [inputs.amqp_consumer] error connecting to %q", broker)
|
||||
a.Log.Debugf("Error connecting to %q", broker)
|
||||
}
|
||||
|
||||
if a.conn == nil {
|
||||
@@ -288,7 +288,7 @@ func (a *AMQPConsumer) connect(amqpConf *amqp.Config) (<-chan amqp.Delivery, err
|
||||
|
||||
ch, err := a.conn.Channel()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to open a channel: %s", err)
|
||||
return nil, fmt.Errorf("Failed to open a channel: %s", err.Error())
|
||||
}
|
||||
|
||||
if a.Exchange != "" {
|
||||
@@ -395,7 +395,7 @@ func declareExchange(
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error declaring exchange: %v", err)
|
||||
return fmt.Errorf("Error declaring exchange: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -437,7 +437,7 @@ func declareQueue(
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error declaring queue: %v", err)
|
||||
return nil, fmt.Errorf("Error declaring queue: %v", err)
|
||||
}
|
||||
return &queue, nil
|
||||
}
|
||||
@@ -486,8 +486,7 @@ func (a *AMQPConsumer) onMessage(acc telegraf.TrackingAccumulator, d amqp.Delive
|
||||
// this message.
|
||||
rejErr := d.Ack(false)
|
||||
if rejErr != nil {
|
||||
log.Printf("E! [inputs.amqp_consumer] Unable to reject message: %d: %v",
|
||||
d.DeliveryTag, rejErr)
|
||||
a.Log.Errorf("Unable to reject message: %d: %v", d.DeliveryTag, rejErr)
|
||||
a.conn.Close()
|
||||
}
|
||||
}
|
||||
@@ -519,15 +518,13 @@ func (a *AMQPConsumer) onDelivery(track telegraf.DeliveryInfo) bool {
|
||||
if track.Delivered() {
|
||||
err := delivery.Ack(false)
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.amqp_consumer] Unable to ack written delivery: %d: %v",
|
||||
delivery.DeliveryTag, err)
|
||||
a.Log.Errorf("Unable to ack written delivery: %d: %v", delivery.DeliveryTag, err)
|
||||
a.conn.Close()
|
||||
}
|
||||
} else {
|
||||
err := delivery.Reject(false)
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.amqp_consumer] Unable to reject failed delivery: %d: %v",
|
||||
delivery.DeliveryTag, err)
|
||||
a.Log.Errorf("Unable to reject failed delivery: %d: %v", delivery.DeliveryTag, err)
|
||||
a.conn.Close()
|
||||
}
|
||||
}
|
||||
@@ -541,7 +538,7 @@ func (a *AMQPConsumer) Stop() {
|
||||
a.wg.Wait()
|
||||
err := a.conn.Close()
|
||||
if err != nil && err != amqp.ErrClosed {
|
||||
log.Printf("E! [inputs.amqp_consumer] Error closing AMQP connection: %s", err)
|
||||
a.Log.Errorf("Error closing AMQP connection: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package activemq
|
||||
package azure_storage_queue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -17,6 +16,7 @@ type AzureStorageQueue struct {
|
||||
StorageAccountName string `toml:"account_name"`
|
||||
StorageAccountKey string `toml:"account_key"`
|
||||
PeekOldestMessageAge bool `toml:"peek_oldest_message_age"`
|
||||
Log telegraf.Logger
|
||||
|
||||
serviceURL *azqueue.ServiceURL
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (a *AzureStorageQueue) Gather(acc telegraf.Accumulator) error {
|
||||
ctx := context.TODO()
|
||||
|
||||
for marker := (azqueue.Marker{}); marker.NotDone(); {
|
||||
log.Printf("D! [inputs.azure_storage_queue] Listing queues of storage account '%s'", a.StorageAccountName)
|
||||
a.Log.Debugf("Listing queues of storage account '%s'", a.StorageAccountName)
|
||||
queuesSegment, err := serviceURL.ListQueuesSegment(ctx, marker,
|
||||
azqueue.ListQueuesSegmentOptions{
|
||||
Detail: azqueue.ListQueuesSegmentDetails{Metadata: false},
|
||||
@@ -103,11 +103,11 @@ func (a *AzureStorageQueue) Gather(acc telegraf.Accumulator) error {
|
||||
marker = queuesSegment.NextMarker
|
||||
|
||||
for _, queueItem := range queuesSegment.QueueItems {
|
||||
log.Printf("D! [inputs.azure_storage_queue] Processing queue '%s' of storage account '%s'", queueItem.Name, a.StorageAccountName)
|
||||
a.Log.Debugf("Processing queue '%s' of storage account '%s'", queueItem.Name, a.StorageAccountName)
|
||||
queueURL := serviceURL.NewQueueURL(queueItem.Name)
|
||||
properties, err := queueURL.GetProperties(ctx)
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.azure_storage_queue] Error getting properties for queue %s: %s", queueItem.Name, err.Error())
|
||||
a.Log.Errorf("Error getting properties for queue %s: %s", queueItem.Name, err.Error())
|
||||
continue
|
||||
}
|
||||
var peekedMessage *azqueue.PeekedMessage
|
||||
@@ -115,7 +115,7 @@ func (a *AzureStorageQueue) Gather(acc telegraf.Accumulator) error {
|
||||
messagesURL := queueURL.NewMessagesURL()
|
||||
messagesResponse, err := messagesURL.Peek(ctx, 1)
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.azure_storage_queue] Error peeking queue %s: %s", queueItem.Name, err.Error())
|
||||
a.Log.Errorf("Error peeking queue %s: %s", queueItem.Name, err.Error())
|
||||
} else if messagesResponse.NumMessages() > 0 {
|
||||
peekedMessage = messagesResponse.Message(0)
|
||||
}
|
||||
|
||||
@@ -101,12 +101,12 @@ func (c *Ceph) gatherAdminSocketStats(acc telegraf.Accumulator) error {
|
||||
for _, s := range sockets {
|
||||
dump, err := perfDump(c.CephBinary, s)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("E! error reading from socket '%s': %v", s.socket, err))
|
||||
acc.AddError(fmt.Errorf("error reading from socket '%s': %v", s.socket, err))
|
||||
continue
|
||||
}
|
||||
data, err := parseDump(dump)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("E! error parsing dump from socket '%s': %v", s.socket, err))
|
||||
acc.AddError(fmt.Errorf("error parsing dump from socket '%s': %v", s.socket, err))
|
||||
continue
|
||||
}
|
||||
for tag, metrics := range data {
|
||||
@@ -287,7 +287,7 @@ func flatten(data interface{}) []*metric {
|
||||
}
|
||||
}
|
||||
default:
|
||||
log.Printf("I! Ignoring unexpected type '%T' for value %v", val, val)
|
||||
log.Printf("I! [inputs.ceph] ignoring unexpected type '%T' for value %v", val, val)
|
||||
}
|
||||
|
||||
return metrics
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -54,6 +54,8 @@ type CiscoTelemetryGNMI struct {
|
||||
acc telegraf.Accumulator
|
||||
cancel context.CancelFunc
|
||||
wg sync.WaitGroup
|
||||
|
||||
Log telegraf.Logger
|
||||
}
|
||||
|
||||
// Subscription for a GNMI client
|
||||
@@ -101,21 +103,27 @@ func (c *CiscoTelemetryGNMI) Start(acc telegraf.Accumulator) error {
|
||||
// Invert explicit alias list and prefill subscription names
|
||||
c.aliases = make(map[string]string, len(c.Subscriptions)+len(c.Aliases))
|
||||
for _, subscription := range c.Subscriptions {
|
||||
var gnmiLongPath, gnmiShortPath *gnmi.Path
|
||||
|
||||
// Build the subscription path without keys
|
||||
gnmiPath, err := parsePath(subscription.Origin, subscription.Path, "")
|
||||
if err != nil {
|
||||
if gnmiLongPath, err = parsePath(subscription.Origin, subscription.Path, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
if gnmiShortPath, err = parsePath("", subscription.Path, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path, _ := c.handlePath(gnmiPath, nil, "")
|
||||
longPath, _ := c.handlePath(gnmiLongPath, nil, "")
|
||||
shortPath, _ := c.handlePath(gnmiShortPath, nil, "")
|
||||
name := subscription.Name
|
||||
|
||||
// If the user didn't provide a measurement name, use last path element
|
||||
if len(name) == 0 {
|
||||
name = path[strings.LastIndexByte(path, '/')+1:]
|
||||
name = path.Base(shortPath)
|
||||
}
|
||||
if len(name) > 0 {
|
||||
c.aliases[path] = name
|
||||
c.aliases[longPath] = name
|
||||
c.aliases[shortPath] = name
|
||||
}
|
||||
}
|
||||
for alias, path := range c.Aliases {
|
||||
@@ -211,8 +219,8 @@ func (c *CiscoTelemetryGNMI) subscribeGNMI(ctx context.Context, address string,
|
||||
return fmt.Errorf("failed to send subscription request: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("D! [inputs.cisco_telemetry_gnmi]: Connection to GNMI device %s established", address)
|
||||
defer log.Printf("D! [inputs.cisco_telemetry_gnmi]: Connection to GNMI device %s closed", address)
|
||||
c.Log.Debugf("Connection to GNMI device %s established", address)
|
||||
defer c.Log.Debugf("Connection to GNMI device %s closed", address)
|
||||
for ctx.Err() == nil {
|
||||
var reply *gnmi.SubscribeResponse
|
||||
if reply, err = subscribeClient.Recv(); err != nil {
|
||||
@@ -267,7 +275,7 @@ func (c *CiscoTelemetryGNMI) handleSubscribeResponse(address string, reply *gnmi
|
||||
if alias, ok := c.aliases[aliasPath]; ok {
|
||||
name = alias
|
||||
} else {
|
||||
log.Printf("D! [inputs.cisco_telemetry_gnmi]: No measurement alias for GNMI path: %s", name)
|
||||
c.Log.Debugf("No measurement alias for GNMI path: %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +303,12 @@ func (c *CiscoTelemetryGNMI) handleTelemetryField(update *gnmi.Update, tags map[
|
||||
var value interface{}
|
||||
var jsondata []byte
|
||||
|
||||
// Make sure a value is actually set
|
||||
if update.Val == nil || update.Val.Value == nil {
|
||||
c.Log.Infof("Discarded empty or legacy type value with path: %q", path)
|
||||
return aliasPath, nil
|
||||
}
|
||||
|
||||
switch val := update.Val.Value.(type) {
|
||||
case *gnmi.TypedValue_AsciiVal:
|
||||
value = val.AsciiVal
|
||||
@@ -346,8 +360,10 @@ func (c *CiscoTelemetryGNMI) handlePath(path *gnmi.Path, tags map[string]string,
|
||||
|
||||
// Parse generic keys from prefix
|
||||
for _, elem := range path.Elem {
|
||||
builder.WriteRune('/')
|
||||
builder.WriteString(elem.Name)
|
||||
if len(elem.Name) > 0 {
|
||||
builder.WriteRune('/')
|
||||
builder.WriteString(elem.Name)
|
||||
}
|
||||
name := builder.String()
|
||||
|
||||
if _, exists := c.aliases[name]; exists {
|
||||
|
||||
@@ -104,8 +104,10 @@ func TestGNMIError(t *testing.T) {
|
||||
acc := &testutil.Accumulator{}
|
||||
gnmi.RegisterGNMIServer(server, &mockGNMIServer{t: t, scenario: 0, server: server, acc: acc})
|
||||
|
||||
c := &CiscoTelemetryGNMI{Addresses: []string{listener.Addr().String()},
|
||||
Username: "theuser", Password: "thepassword", Encoding: "proto",
|
||||
c := &CiscoTelemetryGNMI{
|
||||
Log: testutil.Logger{},
|
||||
Addresses: []string{listener.Addr().String()},
|
||||
Username: "theuser", Password: "thepassword", Encoding: "proto",
|
||||
Redial: internal.Duration{Duration: 1 * time.Second}}
|
||||
|
||||
require.NoError(t, c.Start(acc))
|
||||
@@ -174,8 +176,10 @@ func TestGNMIMultiple(t *testing.T) {
|
||||
acc := &testutil.Accumulator{}
|
||||
gnmi.RegisterGNMIServer(server, &mockGNMIServer{t: t, scenario: 1, server: server, acc: acc})
|
||||
|
||||
c := &CiscoTelemetryGNMI{Addresses: []string{listener.Addr().String()},
|
||||
Username: "theuser", Password: "thepassword", Encoding: "proto",
|
||||
c := &CiscoTelemetryGNMI{
|
||||
Log: testutil.Logger{},
|
||||
Addresses: []string{listener.Addr().String()},
|
||||
Username: "theuser", Password: "thepassword", Encoding: "proto",
|
||||
Redial: internal.Duration{Duration: 1 * time.Second},
|
||||
Subscriptions: []Subscription{{Name: "alias", Origin: "type", Path: "/model", SubscriptionMode: "sample"}},
|
||||
}
|
||||
@@ -215,8 +219,10 @@ func TestGNMIMultipleRedial(t *testing.T) {
|
||||
acc := &testutil.Accumulator{}
|
||||
gnmi.RegisterGNMIServer(server, &mockGNMIServer{t: t, scenario: 2, server: server, acc: acc})
|
||||
|
||||
c := &CiscoTelemetryGNMI{Addresses: []string{listener.Addr().String()},
|
||||
Username: "theuser", Password: "thepassword", Encoding: "proto",
|
||||
c := &CiscoTelemetryGNMI{
|
||||
Log: testutil.Logger{},
|
||||
Addresses: []string{listener.Addr().String()},
|
||||
Username: "theuser", Password: "thepassword", Encoding: "proto",
|
||||
Redial: internal.Duration{Duration: 10 * time.Millisecond},
|
||||
Subscriptions: []Subscription{{Name: "alias", Origin: "type", Path: "/model", SubscriptionMode: "sample"}},
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"path"
|
||||
"strconv"
|
||||
@@ -43,6 +42,8 @@ type CiscoTelemetryMDT struct {
|
||||
Aliases map[string]string `toml:"aliases"`
|
||||
EmbeddedTags []string `toml:"embedded_tags"`
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
// GRPC TLS settings
|
||||
internaltls.ServerConfig
|
||||
|
||||
@@ -146,11 +147,11 @@ func (c *CiscoTelemetryMDT) acceptTCPClients() {
|
||||
// Individual client connection routine
|
||||
c.wg.Add(1)
|
||||
go func() {
|
||||
log.Printf("D! [inputs.cisco_telemetry_mdt]: Accepted Cisco MDT TCP dialout connection from %s", conn.RemoteAddr())
|
||||
c.Log.Debugf("Accepted Cisco MDT TCP dialout connection from %s", conn.RemoteAddr())
|
||||
if err := c.handleTCPClient(conn); err != nil {
|
||||
c.acc.AddError(err)
|
||||
}
|
||||
log.Printf("D! [inputs.cisco_telemetry_mdt]: Closed Cisco MDT TCP dialout connection from %s", conn.RemoteAddr())
|
||||
c.Log.Debugf("Closed Cisco MDT TCP dialout connection from %s", conn.RemoteAddr())
|
||||
|
||||
mutex.Lock()
|
||||
delete(clients, conn)
|
||||
@@ -165,7 +166,7 @@ func (c *CiscoTelemetryMDT) acceptTCPClients() {
|
||||
mutex.Lock()
|
||||
for client := range clients {
|
||||
if err := client.Close(); err != nil {
|
||||
log.Printf("E! [inputs.cisco_telemetry_mdt]: Failed to close TCP dialout client: %v", err)
|
||||
c.Log.Errorf("Failed to close TCP dialout client: %v", err)
|
||||
}
|
||||
}
|
||||
mutex.Unlock()
|
||||
@@ -218,7 +219,7 @@ func (c *CiscoTelemetryMDT) handleTCPClient(conn net.Conn) error {
|
||||
func (c *CiscoTelemetryMDT) MdtDialout(stream dialout.GRPCMdtDialout_MdtDialoutServer) error {
|
||||
peer, peerOK := peer.FromContext(stream.Context())
|
||||
if peerOK {
|
||||
log.Printf("D! [inputs.cisco_telemetry_mdt]: Accepted Cisco MDT GRPC dialout connection from %s", peer.Addr)
|
||||
c.Log.Debugf("Accepted Cisco MDT GRPC dialout connection from %s", peer.Addr)
|
||||
}
|
||||
|
||||
var chunkBuffer bytes.Buffer
|
||||
@@ -252,7 +253,7 @@ func (c *CiscoTelemetryMDT) MdtDialout(stream dialout.GRPCMdtDialout_MdtDialoutS
|
||||
}
|
||||
|
||||
if peerOK {
|
||||
log.Printf("D! [inputs.cisco_telemetry_mdt]: Closed Cisco MDT GRPC dialout connection from %s", peer.Addr)
|
||||
c.Log.Debugf("Closed Cisco MDT GRPC dialout connection from %s", peer.Addr)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -291,7 +292,7 @@ func (c *CiscoTelemetryMDT) handleTelemetry(data []byte) {
|
||||
}
|
||||
|
||||
if keys == nil || content == nil {
|
||||
log.Printf("I! [inputs.cisco_telemetry_mdt]: Message from %s missing keys or content", msg.GetNodeIdStr())
|
||||
c.Log.Infof("Message from %s missing keys or content", msg.GetNodeIdStr())
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -412,7 +413,7 @@ func (c *CiscoTelemetryMDT) parseContentField(grouper *metric.SeriesGrouper, fie
|
||||
} else {
|
||||
c.mutex.Lock()
|
||||
if _, haveWarned := c.warned[path]; !haveWarned {
|
||||
log.Printf("D! [inputs.cisco_telemetry_mdt]: No measurement alias for encoding path: %s", path)
|
||||
c.Log.Debugf("No measurement alias for encoding path: %s", path)
|
||||
c.warned[path] = struct{}{}
|
||||
}
|
||||
c.mutex.Unlock()
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func TestHandleTelemetryTwoSimple(t *testing.T) {
|
||||
c := &CiscoTelemetryMDT{Transport: "dummy", Aliases: map[string]string{"alias": "type:model/some/path"}}
|
||||
c := &CiscoTelemetryMDT{Log: testutil.Logger{}, Transport: "dummy", Aliases: map[string]string{"alias": "type:model/some/path"}}
|
||||
acc := &testutil.Accumulator{}
|
||||
c.Start(acc)
|
||||
|
||||
@@ -93,7 +93,7 @@ func TestHandleTelemetryTwoSimple(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHandleTelemetrySingleNested(t *testing.T) {
|
||||
c := &CiscoTelemetryMDT{Transport: "dummy", Aliases: map[string]string{"nested": "type:model/nested/path"}}
|
||||
c := &CiscoTelemetryMDT{Log: testutil.Logger{}, Transport: "dummy", Aliases: map[string]string{"nested": "type:model/nested/path"}}
|
||||
acc := &testutil.Accumulator{}
|
||||
c.Start(acc)
|
||||
|
||||
@@ -385,7 +385,7 @@ func TestHandleNXDME(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTCPDialoutOverflow(t *testing.T) {
|
||||
c := &CiscoTelemetryMDT{Transport: "tcp", ServiceAddress: "127.0.0.1:57000"}
|
||||
c := &CiscoTelemetryMDT{Log: testutil.Logger{}, Transport: "tcp", ServiceAddress: "127.0.0.1:57000"}
|
||||
acc := &testutil.Accumulator{}
|
||||
assert.Nil(t, c.Start(acc))
|
||||
|
||||
@@ -441,7 +441,7 @@ func mockTelemetryMessage() *telemetry.Telemetry {
|
||||
}
|
||||
|
||||
func TestTCPDialoutMultiple(t *testing.T) {
|
||||
c := &CiscoTelemetryMDT{Transport: "tcp", ServiceAddress: "127.0.0.1:57000", Aliases: map[string]string{
|
||||
c := &CiscoTelemetryMDT{Log: testutil.Logger{}, Transport: "tcp", ServiceAddress: "127.0.0.1:57000", Aliases: map[string]string{
|
||||
"some": "type:model/some/path", "parallel": "type:model/parallel/path", "other": "type:model/other/path"}}
|
||||
acc := &testutil.Accumulator{}
|
||||
assert.Nil(t, c.Start(acc))
|
||||
@@ -500,7 +500,7 @@ func TestTCPDialoutMultiple(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGRPCDialoutError(t *testing.T) {
|
||||
c := &CiscoTelemetryMDT{Transport: "grpc", ServiceAddress: "127.0.0.1:57001"}
|
||||
c := &CiscoTelemetryMDT{Log: testutil.Logger{}, Transport: "grpc", ServiceAddress: "127.0.0.1:57001"}
|
||||
acc := &testutil.Accumulator{}
|
||||
assert.Nil(t, c.Start(acc))
|
||||
|
||||
@@ -519,7 +519,7 @@ func TestGRPCDialoutError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGRPCDialoutMultiple(t *testing.T) {
|
||||
c := &CiscoTelemetryMDT{Transport: "grpc", ServiceAddress: "127.0.0.1:57001", Aliases: map[string]string{
|
||||
c := &CiscoTelemetryMDT{Log: testutil.Logger{}, Transport: "grpc", ServiceAddress: "127.0.0.1:57001", Aliases: map[string]string{
|
||||
"some": "type:model/some/path", "parallel": "type:model/parallel/path", "other": "type:model/other/path"}}
|
||||
acc := &testutil.Accumulator{}
|
||||
assert.Nil(t, c.Start(acc))
|
||||
|
||||
@@ -5,16 +5,16 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"cloud.google.com/go/pubsub"
|
||||
"encoding/base64"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/pubsub"
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/option"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type empty struct{}
|
||||
@@ -43,6 +43,8 @@ type PubSub struct {
|
||||
|
||||
Base64Data bool `toml:"base64_data"`
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
sub subscription
|
||||
stubSub func() subscription
|
||||
|
||||
@@ -134,14 +136,14 @@ func (ps *PubSub) receiveWithRetry(parentCtx context.Context) {
|
||||
err := ps.startReceiver(parentCtx)
|
||||
|
||||
for err != nil && parentCtx.Err() == nil {
|
||||
log.Printf("E! [inputs.cloud_pubsub] Receiver for subscription %s exited with error: %v", ps.sub.ID(), err)
|
||||
ps.Log.Errorf("Receiver for subscription %s exited with error: %v", ps.sub.ID(), err)
|
||||
|
||||
delay := defaultRetryDelaySeconds
|
||||
if ps.RetryReceiveDelaySeconds > 0 {
|
||||
delay = ps.RetryReceiveDelaySeconds
|
||||
}
|
||||
|
||||
log.Printf("I! [inputs.cloud_pubsub] Waiting %d seconds before attempting to restart receiver...", delay)
|
||||
ps.Log.Infof("Waiting %d seconds before attempting to restart receiver...", delay)
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
|
||||
err = ps.startReceiver(parentCtx)
|
||||
@@ -149,7 +151,7 @@ func (ps *PubSub) receiveWithRetry(parentCtx context.Context) {
|
||||
}
|
||||
|
||||
func (ps *PubSub) startReceiver(parentCtx context.Context) error {
|
||||
log.Printf("I! [inputs.cloud_pubsub] Starting receiver for subscription %s...", ps.sub.ID())
|
||||
ps.Log.Infof("Starting receiver for subscription %s...", ps.sub.ID())
|
||||
cctx, ccancel := context.WithCancel(parentCtx)
|
||||
err := ps.sub.Receive(cctx, func(ctx context.Context, msg message) {
|
||||
if err := ps.onMessage(ctx, msg); err != nil {
|
||||
@@ -159,7 +161,7 @@ func (ps *PubSub) startReceiver(parentCtx context.Context) error {
|
||||
if err != nil {
|
||||
ps.acc.AddError(fmt.Errorf("receiver for subscription %s exited: %v", ps.sub.ID(), err))
|
||||
} else {
|
||||
log.Printf("I! [inputs.cloud_pubsub] subscription pull ended (no error, most likely stopped)")
|
||||
ps.Log.Info("Subscription pull ended (no error, most likely stopped)")
|
||||
}
|
||||
ccancel()
|
||||
return err
|
||||
|
||||
@@ -3,10 +3,11 @@ package cloud_pubsub
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,6 +27,7 @@ func TestRunParse(t *testing.T) {
|
||||
sub.receiver = testMessagesReceive(sub)
|
||||
|
||||
ps := &PubSub{
|
||||
Log: testutil.Logger{},
|
||||
parser: testParser,
|
||||
stubSub: func() subscription { return sub },
|
||||
Project: "projectIDontMatterForTests",
|
||||
@@ -69,6 +71,7 @@ func TestRunBase64(t *testing.T) {
|
||||
sub.receiver = testMessagesReceive(sub)
|
||||
|
||||
ps := &PubSub{
|
||||
Log: testutil.Logger{},
|
||||
parser: testParser,
|
||||
stubSub: func() subscription { return sub },
|
||||
Project: "projectIDontMatterForTests",
|
||||
@@ -112,6 +115,7 @@ func TestRunInvalidMessages(t *testing.T) {
|
||||
sub.receiver = testMessagesReceive(sub)
|
||||
|
||||
ps := &PubSub{
|
||||
Log: testutil.Logger{},
|
||||
parser: testParser,
|
||||
stubSub: func() subscription { return sub },
|
||||
Project: "projectIDontMatterForTests",
|
||||
@@ -158,6 +162,7 @@ func TestRunOverlongMessages(t *testing.T) {
|
||||
sub.receiver = testMessagesReceive(sub)
|
||||
|
||||
ps := &PubSub{
|
||||
Log: testutil.Logger{},
|
||||
parser: testParser,
|
||||
stubSub: func() subscription { return sub },
|
||||
Project: "projectIDontMatterForTests",
|
||||
@@ -205,6 +210,7 @@ func TestRunErrorInSubscriber(t *testing.T) {
|
||||
sub.receiver = testMessagesError(sub, errors.New("a fake error"))
|
||||
|
||||
ps := &PubSub{
|
||||
Log: testutil.Logger{},
|
||||
parser: testParser,
|
||||
stubSub: func() subscription { return sub },
|
||||
Project: "projectIDontMatterForTests",
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -33,6 +32,7 @@ type PubSubPush struct {
|
||||
WriteTimeout internal.Duration
|
||||
MaxBodySize internal.Size
|
||||
AddMeta bool
|
||||
Log telegraf.Logger
|
||||
|
||||
MaxUndeliveredMessages int `toml:"max_undelivered_messages"`
|
||||
|
||||
@@ -227,21 +227,21 @@ func (p *PubSubPush) serveWrite(res http.ResponseWriter, req *http.Request) {
|
||||
|
||||
var payload Payload
|
||||
if err = json.Unmarshal(bytes, &payload); err != nil {
|
||||
log.Printf("E! [inputs.cloud_pubsub_push] Error decoding payload %s", err.Error())
|
||||
p.Log.Errorf("Error decoding payload %s", err.Error())
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
sDec, err := base64.StdEncoding.DecodeString(payload.Msg.Data)
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.cloud_pubsub_push] Base64-Decode Failed %s", err.Error())
|
||||
p.Log.Errorf("Base64-decode failed %s", err.Error())
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
metrics, err := p.Parse(sDec)
|
||||
if err != nil {
|
||||
log.Println("D! [inputs.cloud_pubsub_push] " + err.Error())
|
||||
p.Log.Debug(err.Error())
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -295,7 +295,7 @@ func (p *PubSubPush) receiveDelivered() {
|
||||
ch <- true
|
||||
} else {
|
||||
ch <- false
|
||||
log.Println("D! [inputs.cloud_pubsub_push] Metric group failed to process")
|
||||
p.Log.Debug("Metric group failed to process")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/models"
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func TestServeHTTP(t *testing.T) {
|
||||
@@ -118,6 +119,7 @@ func TestServeHTTP(t *testing.T) {
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
pubPush := &PubSubPush{
|
||||
Log: testutil.Logger{},
|
||||
Path: "/",
|
||||
MaxBodySize: internal.Size{
|
||||
Size: test.maxsize,
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
# Telegraf plugin: CPU
|
||||
# CPU Input Plugin
|
||||
|
||||
#### Plugin arguments:
|
||||
- **totalcpu** boolean: If true, include `cpu-total` data
|
||||
- **percpu** boolean: If true, include data on a per-cpu basis `cpu0, cpu1, etc.`
|
||||
The `cpu` plugin gather metrics on the system CPUs.
|
||||
|
||||
|
||||
##### Configuration:
|
||||
```
|
||||
#### Configuration
|
||||
```toml
|
||||
[[inputs.cpu]]
|
||||
## Whether to report per-cpu stats or not
|
||||
percpu = true
|
||||
@@ -18,82 +15,53 @@
|
||||
report_active = false
|
||||
```
|
||||
|
||||
#### Description
|
||||
### Metrics
|
||||
|
||||
The CPU plugin collects standard CPU metrics as defined in `man proc`. All
|
||||
architectures do not support all of these metrics.
|
||||
On Linux, consult `man proc` for details on the meanings of these values.
|
||||
|
||||
- cpu
|
||||
- tags:
|
||||
- cpu (CPU ID or `cpu-total`)
|
||||
- fields:
|
||||
- time_user (float)
|
||||
- time_system (float)
|
||||
- time_idle (float)
|
||||
- time_active (float)
|
||||
- time_nice (float)
|
||||
- time_iowait (float)
|
||||
- time_irq (float)
|
||||
- time_softirq (float)
|
||||
- time_steal (float)
|
||||
- time_guest (float)
|
||||
- time_guest_nice (float)
|
||||
- usage_user (float, percent)
|
||||
- usage_system (float, percent)
|
||||
- usage_idle (float, percent)
|
||||
- usage_active (float)
|
||||
- usage_nice (float, percent)
|
||||
- usage_iowait (float, percent)
|
||||
- usage_irq (float, percent)
|
||||
- usage_softirq (float, percent)
|
||||
- usage_steal (float, percent)
|
||||
- usage_guest (float, percent)
|
||||
- usage_guest_nice (float, percent)
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
On Linux systems the `/proc/stat` file is used to gather CPU times.
|
||||
Percentages are based on the last 2 samples.
|
||||
|
||||
### Example Output
|
||||
|
||||
```
|
||||
cpu 3357 0 4313 1362393
|
||||
The amount of time, measured in units of USER_HZ (1/100ths of a second on
|
||||
most architectures, use sysconf(_SC_CLK_TCK) to obtain the right value),
|
||||
that the system spent in various states:
|
||||
|
||||
user (1) Time spent in user mode.
|
||||
|
||||
nice (2) Time spent in user mode with low priority (nice).
|
||||
|
||||
system (3) Time spent in system mode.
|
||||
|
||||
idle (4) Time spent in the idle task. This value should be USER_HZ times
|
||||
the second entry in the /proc/uptime pseudo-file.
|
||||
|
||||
iowait (since Linux 2.5.41)
|
||||
(5) Time waiting for I/O to complete.
|
||||
|
||||
irq (since Linux 2.6.0-test4)
|
||||
(6) Time servicing interrupts.
|
||||
|
||||
softirq (since Linux 2.6.0-test4)
|
||||
(7) Time servicing softirqs.
|
||||
|
||||
steal (since Linux 2.6.11)
|
||||
(8) Stolen time, which is the time spent in other operating systems
|
||||
when running in a virtualized environment
|
||||
|
||||
guest (since Linux 2.6.24)
|
||||
(9) Time spent running a virtual CPU for guest operating systems
|
||||
under the control of the Linux kernel.
|
||||
|
||||
guest_nice (since Linux 2.6.33)
|
||||
(10) Time spent running a niced guest (virtual CPU for guest operating systems under the control of the Linux kernel).
|
||||
cpu,cpu=cpu0,host=loaner time_active=202224.15999999992,time_guest=30250.35,time_guest_nice=0,time_idle=1527035.04,time_iowait=1352,time_irq=0,time_nice=169.28,time_softirq=6281.4,time_steal=0,time_system=40097.14,time_user=154324.34 1568760922000000000
|
||||
cpu,cpu=cpu0,host=loaner usage_active=31.249999981810106,usage_guest=2.083333333080696,usage_guest_nice=0,usage_idle=68.7500000181899,usage_iowait=0,usage_irq=0,usage_nice=0,usage_softirq=0,usage_steal=0,usage_system=4.166666666161392,usage_user=25.000000002273737 1568760922000000000
|
||||
cpu,cpu=cpu1,host=loaner time_active=201890.02000000002,time_guest=30508.41,time_guest_nice=0,time_idle=264641.18,time_iowait=210.44,time_irq=0,time_nice=181.75,time_softirq=4537.88,time_steal=0,time_system=39480.7,time_user=157479.25 1568760922000000000
|
||||
cpu,cpu=cpu1,host=loaner usage_active=12.500000010610771,usage_guest=2.0833333328280585,usage_guest_nice=0,usage_idle=87.49999998938922,usage_iowait=0,usage_irq=0,usage_nice=0,usage_softirq=2.0833333332070145,usage_steal=0,usage_system=4.166666665656117,usage_user=4.166666666414029 1568760922000000000
|
||||
cpu,cpu=cpu2,host=loaner time_active=201382.78999999998,time_guest=30325.8,time_guest_nice=0,time_idle=264686.63,time_iowait=202.77,time_irq=0,time_nice=162.81,time_softirq=3378.34,time_steal=0,time_system=39270.59,time_user=158368.28 1568760922000000000
|
||||
cpu,cpu=cpu2,host=loaner usage_active=15.999999993480742,usage_guest=1.9999999999126885,usage_guest_nice=0,usage_idle=84.00000000651926,usage_iowait=0,usage_irq=0,usage_nice=0,usage_softirq=2.0000000002764864,usage_steal=0,usage_system=3.999999999825377,usage_user=7.999999998923158 1568760922000000000
|
||||
cpu,cpu=cpu3,host=loaner time_active=198953.51000000007,time_guest=30344.43,time_guest_nice=0,time_idle=265504.09,time_iowait=187.64,time_irq=0,time_nice=197.47,time_softirq=2301.47,time_steal=0,time_system=39313.73,time_user=156953.2 1568760922000000000
|
||||
cpu,cpu=cpu3,host=loaner usage_active=10.41666667424579,usage_guest=0,usage_guest_nice=0,usage_idle=89.58333332575421,usage_iowait=0,usage_irq=0,usage_nice=0,usage_softirq=0,usage_steal=0,usage_system=4.166666666666667,usage_user=6.249999998484175 1568760922000000000
|
||||
cpu,cpu=cpu-total,host=loaner time_active=804450.5299999998,time_guest=121429,time_guest_nice=0,time_idle=2321866.96,time_iowait=1952.86,time_irq=0,time_nice=711.32,time_softirq=16499.1,time_steal=0,time_system=158162.17,time_user=627125.08 1568760922000000000
|
||||
cpu,cpu=cpu-total,host=loaner usage_active=17.616580305880305,usage_guest=1.036269430422946,usage_guest_nice=0,usage_idle=82.3834196941197,usage_iowait=0,usage_irq=0,usage_nice=0,usage_softirq=1.0362694300459534,usage_steal=0,usage_system=4.145077721691784,usage_user=11.398963731636465 1568760922000000000
|
||||
```
|
||||
|
||||
# Measurements:
|
||||
### CPU Time measurements:
|
||||
|
||||
Meta:
|
||||
- units: CPU Time
|
||||
- tags: `cpu=<cpuN> or <cpu-total>`
|
||||
|
||||
Measurement names:
|
||||
- cpu_time_user
|
||||
- cpu_time_system
|
||||
- cpu_time_idle
|
||||
- cpu_time_active (must be explicitly enabled by setting `report_active = true`)
|
||||
- cpu_time_nice
|
||||
- cpu_time_iowait
|
||||
- cpu_time_irq
|
||||
- cpu_time_softirq
|
||||
- cpu_time_steal
|
||||
- cpu_time_guest
|
||||
- cpu_time_guest_nice
|
||||
|
||||
### CPU Usage Percent Measurements:
|
||||
|
||||
Meta:
|
||||
- units: percent (out of 100)
|
||||
- tags: `cpu=<cpuN> or <cpu-total>`
|
||||
|
||||
Measurement names:
|
||||
- cpu_usage_user
|
||||
- cpu_usage_system
|
||||
- cpu_usage_idle
|
||||
- cpu_usage_active (must be explicitly enabled by setting `report_active = true`)
|
||||
- cpu_usage_nice
|
||||
- cpu_usage_iowait
|
||||
- cpu_usage_irq
|
||||
- cpu_usage_softirq
|
||||
- cpu_usage_steal
|
||||
- cpu_usage_guest
|
||||
- cpu_usage_guest_nice
|
||||
|
||||
@@ -2,7 +2,6 @@ package diskio
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@@ -24,6 +23,8 @@ type DiskIO struct {
|
||||
NameTemplates []string
|
||||
SkipSerialNumber bool
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
infoCache map[string]diskInfoCache
|
||||
deviceFilter filter.Filter
|
||||
initialized bool
|
||||
@@ -75,7 +76,7 @@ func (s *DiskIO) init() error {
|
||||
if hasMeta(device) {
|
||||
filter, err := filter.Compile(s.Devices)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error compiling device pattern: %v", err)
|
||||
return fmt.Errorf("error compiling device pattern: %s", err.Error())
|
||||
}
|
||||
s.deviceFilter = filter
|
||||
}
|
||||
@@ -99,7 +100,7 @@ func (s *DiskIO) Gather(acc telegraf.Accumulator) error {
|
||||
|
||||
diskio, err := s.ps.DiskIO(devices)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting disk io info: %s", err)
|
||||
return fmt.Errorf("error getting disk io info: %s", err.Error())
|
||||
}
|
||||
|
||||
for _, io := range diskio {
|
||||
@@ -166,7 +167,7 @@ func (s *DiskIO) diskName(devName string) (string, []string) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Printf("W! Error gathering disk info: %s", err)
|
||||
s.Log.Warnf("Error gathering disk info: %s", err)
|
||||
return devName, devLinks
|
||||
}
|
||||
|
||||
@@ -199,7 +200,7 @@ func (s *DiskIO) diskTags(devName string) map[string]string {
|
||||
|
||||
di, err := s.diskInfo(devName)
|
||||
if err != nil {
|
||||
log.Printf("W! Error gathering disk info: %s", err)
|
||||
s.Log.Warnf("Error gathering disk info: %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ func TestDiskIO(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
diskio := &DiskIO{
|
||||
Log: testutil.Logger{},
|
||||
ps: &mps,
|
||||
Devices: tt.devices,
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ to gather stats from the [Engine API](https://docs.docker.com/engine/api/v1.24/)
|
||||
## Deprecated (1.4.0), use container_name_include
|
||||
container_names = []
|
||||
|
||||
## Set the source tag for the metrics to the container ID hostname, eg first 12 chars
|
||||
source_tag = false
|
||||
|
||||
## Containers to include and exclude. Collect all if empty. Globs accepted.
|
||||
container_name_include = []
|
||||
container_name_exclude = []
|
||||
@@ -93,6 +96,17 @@ volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
```
|
||||
|
||||
#### source tag
|
||||
|
||||
Selecting the containers measurements can be tricky if you have many containers with the same name.
|
||||
To alleviate this issue you can set the below value to `true`
|
||||
|
||||
```toml
|
||||
source_tag = true
|
||||
```
|
||||
|
||||
This will cause all measurements to have the `source` tag be set to the first 12 characters of the container id. The first 12 characters is the common hostname for containers that have no explicit hostname set, as defined by docker.
|
||||
|
||||
#### Kubernetes Labels
|
||||
|
||||
Kubernetes may add many labels to your containers, if they are not needed you
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -45,6 +44,10 @@ type Docker struct {
|
||||
ContainerStateInclude []string `toml:"container_state_include"`
|
||||
ContainerStateExclude []string `toml:"container_state_exclude"`
|
||||
|
||||
IncludeSourceTag bool `toml:"source_tag"`
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
tlsint.ClientConfig
|
||||
|
||||
newEnvClient func() (Client, error)
|
||||
@@ -89,6 +92,9 @@ var sampleConfig = `
|
||||
## Only collect metrics for these containers, collect all if empty
|
||||
container_names = []
|
||||
|
||||
## Set the source tag for the metrics to the container ID hostname, eg first 12 chars
|
||||
source_tag = false
|
||||
|
||||
## Containers to include and exclude. Globs accepted.
|
||||
## Note that an empty array for both will include all containers
|
||||
container_name_include = []
|
||||
@@ -107,8 +113,10 @@ var sampleConfig = `
|
||||
## 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
|
||||
|
||||
## Which environment variables should we use as a tag
|
||||
##tag_env = ["JAVA_HOME", "HEAP_SIZE"]
|
||||
|
||||
@@ -274,7 +282,7 @@ func (d *Docker) gatherSwarmInfo(acc telegraf.Accumulator) error {
|
||||
fields["tasks_running"] = running[service.ID]
|
||||
fields["tasks_desired"] = tasksNoShutdown[service.ID]
|
||||
} else {
|
||||
log.Printf("E! Unknow Replicas Mode")
|
||||
d.Log.Error("Unknown replica mode")
|
||||
}
|
||||
// Add metrics
|
||||
acc.AddFields("docker_swarm",
|
||||
@@ -409,6 +417,13 @@ func (d *Docker) gatherInfo(acc telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func hostnameFromID(id string) string {
|
||||
if len(id) > 12 {
|
||||
return id[0:12]
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func (d *Docker) gatherContainer(
|
||||
container types.Container,
|
||||
acc telegraf.Accumulator,
|
||||
@@ -440,6 +455,10 @@ func (d *Docker) gatherContainer(
|
||||
"container_version": imageVersion,
|
||||
}
|
||||
|
||||
if d.IncludeSourceTag {
|
||||
tags["source"] = hostnameFromID(container.ID)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), d.Timeout.Duration)
|
||||
defer cancel()
|
||||
|
||||
|
||||
@@ -252,6 +252,7 @@ func TestDocker_WindowsMemoryContainerStats(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
d := Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: func(string, *tls.Config) (Client, error) {
|
||||
return &MockClient{
|
||||
InfoF: func(ctx context.Context) (types.Info, error) {
|
||||
@@ -390,6 +391,7 @@ func TestContainerLabels(t *testing.T) {
|
||||
}
|
||||
|
||||
d := Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: newClientFunc,
|
||||
LabelInclude: tt.include,
|
||||
LabelExclude: tt.exclude,
|
||||
@@ -511,6 +513,7 @@ func TestContainerNames(t *testing.T) {
|
||||
}
|
||||
|
||||
d := Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: newClientFunc,
|
||||
ContainerInclude: tt.include,
|
||||
ContainerExclude: tt.exclude,
|
||||
@@ -625,7 +628,11 @@ func TestContainerStatus(t *testing.T) {
|
||||
|
||||
return &client, nil
|
||||
}
|
||||
d = Docker{newClient: newClientFunc}
|
||||
d = Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: newClientFunc,
|
||||
IncludeSourceTag: true,
|
||||
}
|
||||
)
|
||||
|
||||
// mock time
|
||||
@@ -667,6 +674,7 @@ func TestContainerStatus(t *testing.T) {
|
||||
"label2": "test_value_2",
|
||||
"server_version": "17.09.0-ce",
|
||||
"container_status": tt.expect.Status,
|
||||
"source": "e2173b9478a6",
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -675,6 +683,7 @@ func TestContainerStatus(t *testing.T) {
|
||||
func TestDockerGatherInfo(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
d := Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: newClient,
|
||||
TagEnvironment: []string{"ENVVAR1", "ENVVAR2", "ENVVAR3", "ENVVAR5",
|
||||
"ENVVAR6", "ENVVAR7", "ENVVAR8", "ENVVAR9"},
|
||||
@@ -824,6 +833,7 @@ func TestDockerGatherInfo(t *testing.T) {
|
||||
func TestDockerGatherSwarmInfo(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
d := Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: newClient,
|
||||
}
|
||||
|
||||
@@ -931,6 +941,7 @@ func TestContainerStateFilter(t *testing.T) {
|
||||
}
|
||||
|
||||
d := Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: newClientFunc,
|
||||
ContainerStateInclude: tt.include,
|
||||
ContainerStateExclude: tt.exclude,
|
||||
@@ -992,6 +1003,7 @@ func TestContainerName(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
d := Docker{
|
||||
Log: testutil.Logger{},
|
||||
newClient: tt.clientFunc,
|
||||
}
|
||||
var acc testutil.Accumulator
|
||||
@@ -1007,3 +1019,37 @@ func TestContainerName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostnameFromID(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
id string
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
name: "Real ID",
|
||||
id: "565e3a55f5843cfdd4aa5659a1a75e4e78d47f73c3c483f782fe4a26fc8caa07",
|
||||
expect: "565e3a55f584",
|
||||
},
|
||||
{
|
||||
name: "Short ID",
|
||||
id: "shortid123",
|
||||
expect: "shortid123",
|
||||
},
|
||||
{
|
||||
name: "No ID",
|
||||
id: "",
|
||||
expect: "shortid123",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
output := hostnameFromID(test.id)
|
||||
if test.expect != output {
|
||||
t.Logf("Container ID for hostname is wrong. Want: %s, Got: %s", output, test.expect)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ The docker plugin uses the [Official Docker Client][] to gather logs from the
|
||||
# docker_label_include = []
|
||||
# docker_label_exclude = []
|
||||
|
||||
## Set the source tag for the metrics to the container ID hostname, eg first 12 chars
|
||||
source_tag = false
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
@@ -58,6 +61,17 @@ When using the `"ENV"` endpoint, the connection is configured using the
|
||||
|
||||
[env]: https://godoc.org/github.com/moby/moby/client#NewEnvClient
|
||||
|
||||
### source tag
|
||||
|
||||
Selecting the containers can be tricky if you have many containers with the same name.
|
||||
To alleviate this issue you can set the below value to `true`
|
||||
|
||||
```toml
|
||||
source_tag = true
|
||||
```
|
||||
|
||||
This will cause all data points to have the `source` tag be set to the first 12 characters of the container id. The first 12 characters is the common hostname for containers that have no explicit hostname set, as defined by docker.
|
||||
|
||||
### Metrics
|
||||
|
||||
- docker_log
|
||||
@@ -66,6 +80,7 @@ When using the `"ENV"` endpoint, the connection is configured using the
|
||||
- container_version
|
||||
- container_name
|
||||
- stream (stdout, stderr, or tty)
|
||||
- source
|
||||
- fields:
|
||||
- container_id
|
||||
- message
|
||||
|
||||
@@ -49,6 +49,9 @@ var sampleConfig = `
|
||||
# docker_label_include = []
|
||||
# docker_label_exclude = []
|
||||
|
||||
## Set the source tag for the metrics to the container ID hostname, eg first 12 chars
|
||||
source_tag = false
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
@@ -82,6 +85,7 @@ type DockerLogs struct {
|
||||
ContainerExclude []string `toml:"container_name_exclude"`
|
||||
ContainerStateInclude []string `toml:"container_state_include"`
|
||||
ContainerStateExclude []string `toml:"container_state_exclude"`
|
||||
IncludeSourceTag bool `toml:"source_tag"`
|
||||
|
||||
tlsint.ClientConfig
|
||||
|
||||
@@ -258,6 +262,10 @@ func (d *DockerLogs) tailContainerLogs(
|
||||
"container_version": imageVersion,
|
||||
}
|
||||
|
||||
if d.IncludeSourceTag {
|
||||
tags["source"] = hostnameFromID(container.ID)
|
||||
}
|
||||
|
||||
// Add matching container labels as tags
|
||||
for k, label := range container.Labels {
|
||||
if d.labelFilter.Match(k) {
|
||||
@@ -435,3 +443,10 @@ func init() {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func hostnameFromID(id string) string {
|
||||
if len(id) > 12 {
|
||||
return id[0:12]
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ func Test(t *testing.T) {
|
||||
"container_image": "influxdata/telegraf",
|
||||
"container_version": "1.11.0",
|
||||
"stream": "tty",
|
||||
"source": "deadbeef",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"container_id": "deadbeef",
|
||||
@@ -141,6 +142,7 @@ func Test(t *testing.T) {
|
||||
"container_image": "influxdata/telegraf",
|
||||
"container_version": "1.11.0",
|
||||
"stream": "stdout",
|
||||
"source": "deadbeef",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"container_id": "deadbeef",
|
||||
@@ -155,9 +157,10 @@ func Test(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
plugin := &DockerLogs{
|
||||
Timeout: internal.Duration{Duration: time.Second * 5},
|
||||
newClient: func(string, *tls.Config) (Client, error) { return tt.client, nil },
|
||||
containerList: make(map[string]context.CancelFunc),
|
||||
Timeout: internal.Duration{Duration: time.Second * 5},
|
||||
newClient: func(string, *tls.Config) (Client, error) { return tt.client, nil },
|
||||
containerList: make(map[string]context.CancelFunc),
|
||||
IncludeSourceTag: true,
|
||||
}
|
||||
|
||||
err := plugin.Init()
|
||||
|
||||
@@ -17,8 +17,10 @@ the [upgrading steps][upgrading].
|
||||
##
|
||||
## If no servers are specified, then localhost is used as the host.
|
||||
servers = ["localhost:24242"]
|
||||
|
||||
## Type is one of "user", "domain", "ip", or "global"
|
||||
type = "global"
|
||||
|
||||
## Wildcard matches like "*.com". An empty string "" is same as "*"
|
||||
## If type = "ip" filters should be <IP/network>
|
||||
filters = [""]
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
// "log"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -32,8 +31,10 @@ var sampleConfig = `
|
||||
##
|
||||
## If no servers are specified, then localhost is used as the host.
|
||||
servers = ["localhost:24242"]
|
||||
|
||||
## Type is one of "user", "domain", "ip", or "global"
|
||||
type = "global"
|
||||
|
||||
## Wildcard matches like "*.com". An empty string "" is same as "*"
|
||||
## If type = "ip" filters should be <IP/network>
|
||||
filters = [""]
|
||||
@@ -82,12 +83,12 @@ func (d *Dovecot) Gather(acc telegraf.Accumulator) error {
|
||||
func (d *Dovecot) gatherServer(addr string, acc telegraf.Accumulator, qtype string, filter string) error {
|
||||
_, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: %s on url %s\n", err, addr)
|
||||
return fmt.Errorf("%q on url %s", err.Error(), addr)
|
||||
}
|
||||
|
||||
c, err := net.DialTimeout("tcp", addr, defaultTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to connect to dovecot server '%s': %s", addr, err)
|
||||
return fmt.Errorf("enable to connect to dovecot server '%s': %s", addr, err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
|
||||
@@ -10,13 +10,12 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kballard/go-shellquote"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
"github.com/influxdata/telegraf/plugins/parsers/nagios"
|
||||
"github.com/kballard/go-shellquote"
|
||||
)
|
||||
|
||||
const sampleConfig = `
|
||||
@@ -50,7 +49,7 @@ type Exec struct {
|
||||
parser parsers.Parser
|
||||
|
||||
runner Runner
|
||||
log telegraf.Logger
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
}
|
||||
|
||||
func NewExec() *Exec {
|
||||
@@ -161,7 +160,7 @@ func (e *Exec) ProcessCommand(command string, acc telegraf.Accumulator, wg *sync
|
||||
if isNagios {
|
||||
metrics, err = nagios.TryAddState(runErr, metrics)
|
||||
if err != nil {
|
||||
e.log.Errorf("failed to add nagios state: %s", err)
|
||||
e.Log.Errorf("Failed to add nagios state: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ func TestExec(t *testing.T) {
|
||||
MetricName: "exec",
|
||||
})
|
||||
e := &Exec{
|
||||
log: testutil.Logger{},
|
||||
Log: testutil.Logger{},
|
||||
runner: newRunnerMock([]byte(validJson), nil, nil),
|
||||
Commands: []string{"testcommand arg1"},
|
||||
parser: parser,
|
||||
@@ -126,7 +126,7 @@ func TestExecMalformed(t *testing.T) {
|
||||
MetricName: "exec",
|
||||
})
|
||||
e := &Exec{
|
||||
log: testutil.Logger{},
|
||||
Log: testutil.Logger{},
|
||||
runner: newRunnerMock([]byte(malformedJson), nil, nil),
|
||||
Commands: []string{"badcommand arg1"},
|
||||
parser: parser,
|
||||
@@ -143,7 +143,7 @@ func TestCommandError(t *testing.T) {
|
||||
MetricName: "exec",
|
||||
})
|
||||
e := &Exec{
|
||||
log: testutil.Logger{},
|
||||
Log: testutil.Logger{},
|
||||
runner: newRunnerMock(nil, nil, fmt.Errorf("exit status code 1")),
|
||||
Commands: []string{"badcommand"},
|
||||
parser: parser,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package filecount
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
@@ -59,6 +58,7 @@ type FileCount struct {
|
||||
fileFilters []fileFilterFunc
|
||||
globPaths []globpath.GlobPath
|
||||
Fs fileSystem
|
||||
Log telegraf.Logger
|
||||
}
|
||||
|
||||
func (_ *FileCount) Description() string {
|
||||
@@ -210,7 +210,7 @@ func (fc *FileCount) count(acc telegraf.Accumulator, basedir string, glob globpa
|
||||
Unsorted: true,
|
||||
ErrorCallback: func(osPathname string, err error) godirwalk.ErrorAction {
|
||||
if os.IsPermission(errors.Cause(err)) {
|
||||
log.Println("D! [inputs.filecount]", err)
|
||||
fc.Log.Debug(err)
|
||||
return godirwalk.SkipNode
|
||||
}
|
||||
return godirwalk.Halt
|
||||
|
||||
@@ -152,6 +152,7 @@ func TestDirectoryWithTrailingSlash(t *testing.T) {
|
||||
|
||||
func getNoFilterFileCount() FileCount {
|
||||
return FileCount{
|
||||
Log: testutil.Logger{},
|
||||
Directories: []string{getTestdataDir()},
|
||||
Name: "*",
|
||||
Recursive: true,
|
||||
|
||||
@@ -11,6 +11,7 @@ The filestat plugin gathers metrics about file existence, size, and other stats.
|
||||
## These accept standard unix glob matching rules, but with the addition of
|
||||
## ** as a "super asterisk". See https://github.com/gobwas/glob.
|
||||
files = ["/etc/telegraf/telegraf.conf", "/var/log/**.log"]
|
||||
|
||||
## If true, read the entire file and calculate an md5 checksum.
|
||||
md5 = false
|
||||
```
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
@@ -23,6 +22,7 @@ const sampleConfig = `
|
||||
## See https://github.com/gobwas/glob for more examples
|
||||
##
|
||||
files = ["/var/log/**.log"]
|
||||
|
||||
## If true, read the entire file and calculate an md5 checksum.
|
||||
md5 = false
|
||||
`
|
||||
@@ -31,6 +31,8 @@ type FileStat struct {
|
||||
Md5 bool
|
||||
Files []string
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
// maps full file paths to globmatch obj
|
||||
globs map[string]*globpath.GlobPath
|
||||
}
|
||||
@@ -41,11 +43,11 @@ func NewFileStat() *FileStat {
|
||||
}
|
||||
}
|
||||
|
||||
func (_ *FileStat) Description() string {
|
||||
func (*FileStat) Description() string {
|
||||
return "Read stats about given file(s)"
|
||||
}
|
||||
|
||||
func (_ *FileStat) SampleConfig() string { return sampleConfig }
|
||||
func (*FileStat) SampleConfig() string { return sampleConfig }
|
||||
|
||||
func (f *FileStat) Gather(acc telegraf.Accumulator) error {
|
||||
var err error
|
||||
@@ -86,7 +88,7 @@ func (f *FileStat) Gather(acc telegraf.Accumulator) error {
|
||||
}
|
||||
|
||||
if fileInfo == nil {
|
||||
log.Printf("E! Unable to get info for file [%s], possible permissions issue",
|
||||
f.Log.Errorf("Unable to get info for file %q, possible permissions issue",
|
||||
fileName)
|
||||
} else {
|
||||
fields["size_bytes"] = fileInfo.Size()
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
func TestGatherNoMd5(t *testing.T) {
|
||||
dir := getTestdataDir()
|
||||
fs := NewFileStat()
|
||||
fs.Log = testutil.Logger{}
|
||||
fs.Files = []string{
|
||||
dir + "log1.log",
|
||||
dir + "log2.log",
|
||||
@@ -44,6 +45,7 @@ func TestGatherNoMd5(t *testing.T) {
|
||||
func TestGatherExplicitFiles(t *testing.T) {
|
||||
dir := getTestdataDir()
|
||||
fs := NewFileStat()
|
||||
fs.Log = testutil.Logger{}
|
||||
fs.Md5 = true
|
||||
fs.Files = []string{
|
||||
dir + "log1.log",
|
||||
@@ -77,6 +79,7 @@ func TestGatherExplicitFiles(t *testing.T) {
|
||||
func TestGatherGlob(t *testing.T) {
|
||||
dir := getTestdataDir()
|
||||
fs := NewFileStat()
|
||||
fs.Log = testutil.Logger{}
|
||||
fs.Md5 = true
|
||||
fs.Files = []string{
|
||||
dir + "*.log",
|
||||
@@ -103,6 +106,7 @@ func TestGatherGlob(t *testing.T) {
|
||||
func TestGatherSuperAsterisk(t *testing.T) {
|
||||
dir := getTestdataDir()
|
||||
fs := NewFileStat()
|
||||
fs.Log = testutil.Logger{}
|
||||
fs.Md5 = true
|
||||
fs.Files = []string{
|
||||
dir + "**",
|
||||
@@ -136,6 +140,7 @@ func TestGatherSuperAsterisk(t *testing.T) {
|
||||
func TestModificationTime(t *testing.T) {
|
||||
dir := getTestdataDir()
|
||||
fs := NewFileStat()
|
||||
fs.Log = testutil.Logger{}
|
||||
fs.Files = []string{
|
||||
dir + "log1.log",
|
||||
}
|
||||
@@ -153,6 +158,7 @@ func TestModificationTime(t *testing.T) {
|
||||
|
||||
func TestNoModificationTime(t *testing.T) {
|
||||
fs := NewFileStat()
|
||||
fs.Log = testutil.Logger{}
|
||||
fs.Files = []string{
|
||||
"/non/existant/file",
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"crypto/subtle"
|
||||
"crypto/tls"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -48,6 +47,7 @@ type HTTPListenerV2 struct {
|
||||
tlsint.ServerConfig
|
||||
|
||||
TimeFunc
|
||||
Log telegraf.Logger
|
||||
|
||||
wg sync.WaitGroup
|
||||
|
||||
@@ -162,7 +162,7 @@ func (h *HTTPListenerV2) Start(acc telegraf.Accumulator) error {
|
||||
server.Serve(h.listener)
|
||||
}()
|
||||
|
||||
log.Printf("I! [inputs.http_listener_v2] Listening on %s", listener.Addr().String())
|
||||
h.Log.Infof("Listening on %s", listener.Addr().String())
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -219,7 +219,7 @@ func (h *HTTPListenerV2) serveWrite(res http.ResponseWriter, req *http.Request)
|
||||
|
||||
metrics, err := h.Parse(bytes)
|
||||
if err != nil {
|
||||
log.Printf("D! [inputs.http_listener_v2] Parse error: %v", err)
|
||||
h.Log.Debugf("Parse error: %s", err.Error())
|
||||
badRequest(res)
|
||||
return
|
||||
}
|
||||
@@ -239,7 +239,7 @@ func (h *HTTPListenerV2) collectBody(res http.ResponseWriter, req *http.Request)
|
||||
var err error
|
||||
body, err = gzip.NewReader(req.Body)
|
||||
if err != nil {
|
||||
log.Println("D! " + err.Error())
|
||||
h.Log.Debug(err.Error())
|
||||
badRequest(res)
|
||||
return nil, false
|
||||
}
|
||||
@@ -261,7 +261,7 @@ func (h *HTTPListenerV2) collectQuery(res http.ResponseWriter, req *http.Request
|
||||
|
||||
query, err := url.QueryUnescape(rawQuery)
|
||||
if err != nil {
|
||||
log.Printf("D! [inputs.http_listener_v2] Error parsing query: %v", err)
|
||||
h.Log.Debugf("Error parsing query: %s", err.Error())
|
||||
badRequest(res)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ func newTestHTTPListenerV2() *HTTPListenerV2 {
|
||||
parser, _ := parsers.NewInfluxParser()
|
||||
|
||||
listener := &HTTPListenerV2{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
Path: "/write",
|
||||
Methods: []string{"POST"},
|
||||
@@ -68,6 +69,7 @@ func newTestHTTPSListenerV2() *HTTPListenerV2 {
|
||||
parser, _ := parsers.NewInfluxParser()
|
||||
|
||||
listener := &HTTPListenerV2{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
Path: "/write",
|
||||
Methods: []string{"POST"},
|
||||
@@ -231,6 +233,7 @@ func TestWriteHTTPExactMaxBodySize(t *testing.T) {
|
||||
parser, _ := parsers.NewInfluxParser()
|
||||
|
||||
listener := &HTTPListenerV2{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
Path: "/write",
|
||||
Methods: []string{"POST"},
|
||||
@@ -253,6 +256,7 @@ func TestWriteHTTPVerySmallMaxBody(t *testing.T) {
|
||||
parser, _ := parsers.NewInfluxParser()
|
||||
|
||||
listener := &HTTPListenerV2{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
Path: "/write",
|
||||
Methods: []string{"POST"},
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -34,6 +33,8 @@ type HTTPResponse struct {
|
||||
Interface string
|
||||
tls.ClientConfig
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
compiledStringMatch *regexp.Regexp
|
||||
client *http.Client
|
||||
}
|
||||
@@ -242,7 +243,7 @@ func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]
|
||||
// HTTP error codes do not generate errors in the net/http library
|
||||
if err != nil {
|
||||
// Log error
|
||||
log.Printf("D! Network error while polling %s: %s", u, err.Error())
|
||||
h.Log.Debugf("Network error while polling %s: %s", u, err.Error())
|
||||
|
||||
// Get error details
|
||||
netErr := setError(err, fields, tags)
|
||||
@@ -271,7 +272,7 @@ func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]
|
||||
|
||||
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("D! Failed to read body of HTTP Response : %s", err)
|
||||
h.Log.Debugf("Failed to read body of HTTP Response : %s", err.Error())
|
||||
setResult("body_read_error", fields, tags)
|
||||
fields["content_length"] = len(bodyBytes)
|
||||
if h.ResponseStringMatch != "" {
|
||||
@@ -322,7 +323,7 @@ func (h *HTTPResponse) Gather(acc telegraf.Accumulator) error {
|
||||
if h.Address == "" {
|
||||
h.URLs = []string{"http://localhost"}
|
||||
} else {
|
||||
log.Printf("W! [inputs.http_response] 'address' deprecated in telegraf 1.12, please use 'urls'")
|
||||
h.Log.Warn("'address' deprecated in telegraf 1.12, please use 'urls'")
|
||||
h.URLs = []string{h.Address}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ func TestHeaders(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL,
|
||||
Method: "GET",
|
||||
ResponseTimeout: internal.Duration{Duration: time.Second * 2},
|
||||
@@ -185,6 +186,7 @@ func TestFields(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/good",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -246,6 +248,7 @@ func TestInterface(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/good",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -284,6 +287,7 @@ func TestRedirects(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/redirect",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -314,6 +318,7 @@ func TestRedirects(t *testing.T) {
|
||||
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||
|
||||
h = &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/badredirect",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -350,6 +355,7 @@ func TestMethod(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/mustbepostmethod",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "POST",
|
||||
@@ -380,6 +386,7 @@ func TestMethod(t *testing.T) {
|
||||
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||
|
||||
h = &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/mustbepostmethod",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -411,6 +418,7 @@ func TestMethod(t *testing.T) {
|
||||
|
||||
//check that lowercase methods work correctly
|
||||
h = &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/mustbepostmethod",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "head",
|
||||
@@ -447,6 +455,7 @@ func TestBody(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/musthaveabody",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -477,6 +486,7 @@ func TestBody(t *testing.T) {
|
||||
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||
|
||||
h = &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/musthaveabody",
|
||||
Method: "GET",
|
||||
ResponseTimeout: internal.Duration{Duration: time.Second * 20},
|
||||
@@ -510,6 +520,7 @@ func TestStringMatch(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/good",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -547,6 +558,7 @@ func TestStringMatchJson(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/jsonresponse",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -584,6 +596,7 @@ func TestStringMatchFail(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/good",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -626,6 +639,7 @@ func TestTimeout(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/twosecondnap",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -659,6 +673,7 @@ func TestBadRegex(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: ts.URL + "/good",
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -682,6 +697,7 @@ func TestBadRegex(t *testing.T) {
|
||||
func TestNetworkErrors(t *testing.T) {
|
||||
// DNS error
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: "https://nonexistent.nonexistent", // Any non-resolvable URL works here
|
||||
Body: "",
|
||||
Method: "GET",
|
||||
@@ -708,6 +724,7 @@ func TestNetworkErrors(t *testing.T) {
|
||||
|
||||
// Connecton failed
|
||||
h = &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
Address: "https:/nonexistent.nonexistent", // Any non-routable IP works here
|
||||
Body: "",
|
||||
Method: "GET",
|
||||
@@ -739,6 +756,7 @@ func TestContentLength(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
h := &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
URLs: []string{ts.URL + "/good"},
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
@@ -769,6 +787,7 @@ func TestContentLength(t *testing.T) {
|
||||
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||
|
||||
h = &HTTPResponse{
|
||||
Log: testutil.Logger{},
|
||||
URLs: []string{ts.URL + "/musthaveabody"},
|
||||
Body: "{ 'test': 'data'}",
|
||||
Method: "GET",
|
||||
|
||||
@@ -11,10 +11,10 @@ services and hosts. You can read Icinga2's documentation for their remote API
|
||||
```toml
|
||||
# Description
|
||||
[[inputs.icinga2]]
|
||||
## Required Icinga2 server address (default: "https://localhost:5665")
|
||||
## Required Icinga2 server address
|
||||
# server = "https://localhost:5665"
|
||||
|
||||
## Required Icinga2 object type ("services" or "hosts, default "services")
|
||||
## Required Icinga2 object type ("services" or "hosts")
|
||||
# object_type = "services"
|
||||
|
||||
## Credentials for basic HTTP authentication
|
||||
|
||||
@@ -3,7 +3,6 @@ package icinga2
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
@@ -22,6 +21,8 @@ type Icinga2 struct {
|
||||
ResponseTimeout internal.Duration
|
||||
tls.ClientConfig
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
@@ -49,10 +50,10 @@ var levels = []string{"ok", "warning", "critical", "unknown"}
|
||||
type ObjectType string
|
||||
|
||||
var sampleConfig = `
|
||||
## Required Icinga2 server address (default: "https://localhost:5665")
|
||||
## Required Icinga2 server address
|
||||
# server = "https://localhost:5665"
|
||||
|
||||
## Required Icinga2 object type ("services" or "hosts, default "services")
|
||||
|
||||
## Required Icinga2 object type ("services" or "hosts")
|
||||
# object_type = "services"
|
||||
|
||||
## Credentials for basic HTTP authentication
|
||||
@@ -80,25 +81,27 @@ func (i *Icinga2) SampleConfig() string {
|
||||
|
||||
func (i *Icinga2) GatherStatus(acc telegraf.Accumulator, checks []Object) {
|
||||
for _, check := range checks {
|
||||
fields := make(map[string]interface{})
|
||||
tags := make(map[string]string)
|
||||
|
||||
url, err := url.Parse(i.Server)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
i.Log.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
state := int64(check.Attrs.State)
|
||||
|
||||
fields["name"] = check.Attrs.Name
|
||||
fields["state_code"] = state
|
||||
fields := map[string]interface{}{
|
||||
"name": check.Attrs.Name,
|
||||
"state_code": state,
|
||||
}
|
||||
|
||||
tags["display_name"] = check.Attrs.DisplayName
|
||||
tags["check_command"] = check.Attrs.CheckCommand
|
||||
tags["state"] = levels[state]
|
||||
tags["source"] = url.Hostname()
|
||||
tags["scheme"] = url.Scheme
|
||||
tags["port"] = url.Port()
|
||||
tags := map[string]string{
|
||||
"display_name": check.Attrs.DisplayName,
|
||||
"check_command": check.Attrs.CheckCommand,
|
||||
"state": levels[state],
|
||||
"source": url.Hostname(),
|
||||
"scheme": url.Scheme,
|
||||
"port": url.Port(),
|
||||
}
|
||||
|
||||
acc.AddFields(fmt.Sprintf("icinga2_%s", i.ObjectType), fields, tags)
|
||||
}
|
||||
@@ -165,8 +168,9 @@ func (i *Icinga2) Gather(acc telegraf.Accumulator) error {
|
||||
func init() {
|
||||
inputs.Add("icinga2", func() telegraf.Input {
|
||||
return &Icinga2{
|
||||
Server: "https://localhost:5665",
|
||||
ObjectType: "services",
|
||||
Server: "https://localhost:5665",
|
||||
ObjectType: "services",
|
||||
ResponseTimeout: internal.Duration{Duration: time.Second * 5},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ func TestGatherServicesStatus(t *testing.T) {
|
||||
json.Unmarshal([]byte(s), &checks)
|
||||
|
||||
icinga2 := new(Icinga2)
|
||||
icinga2.Log = testutil.Logger{}
|
||||
icinga2.ObjectType = "services"
|
||||
icinga2.Server = "https://localhost:5665"
|
||||
|
||||
@@ -86,6 +87,7 @@ func TestGatherHostsStatus(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
icinga2 := new(Icinga2)
|
||||
icinga2.Log = testutil.Logger{}
|
||||
icinga2.ObjectType = "hosts"
|
||||
icinga2.Server = "https://localhost:5665"
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -75,6 +74,8 @@ type HTTPListener struct {
|
||||
BuffersCreated selfstat.Stat
|
||||
AuthFailures selfstat.Stat
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
longLines selfstat.Stat
|
||||
}
|
||||
|
||||
@@ -202,7 +203,7 @@ func (h *HTTPListener) Start(acc telegraf.Accumulator) error {
|
||||
server.Serve(h.listener)
|
||||
}()
|
||||
|
||||
log.Printf("I! Started HTTP listener service on %s\n", h.ServiceAddress)
|
||||
h.Log.Infof("Started HTTP listener service on %s", h.ServiceAddress)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -215,7 +216,7 @@ func (h *HTTPListener) Stop() {
|
||||
h.listener.Close()
|
||||
h.wg.Wait()
|
||||
|
||||
log.Println("I! Stopped HTTP listener service on ", h.ServiceAddress)
|
||||
h.Log.Infof("Stopped HTTP listener service on %s", h.ServiceAddress)
|
||||
}
|
||||
|
||||
func (h *HTTPListener) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||
@@ -274,7 +275,7 @@ func (h *HTTPListener) serveWrite(res http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
body, err = gzip.NewReader(req.Body)
|
||||
if err != nil {
|
||||
log.Println("D! " + err.Error())
|
||||
h.Log.Debug(err.Error())
|
||||
badRequest(res, err.Error())
|
||||
return
|
||||
}
|
||||
@@ -290,7 +291,7 @@ func (h *HTTPListener) serveWrite(res http.ResponseWriter, req *http.Request) {
|
||||
for {
|
||||
n, err := io.ReadFull(body, buf[bufStart:])
|
||||
if err != nil && err != io.ErrUnexpectedEOF && err != io.EOF {
|
||||
log.Println("D! " + err.Error())
|
||||
h.Log.Debug(err.Error())
|
||||
// problem reading the request body
|
||||
badRequest(res, err.Error())
|
||||
return
|
||||
@@ -327,7 +328,7 @@ func (h *HTTPListener) serveWrite(res http.ResponseWriter, req *http.Request) {
|
||||
// finished reading the request body
|
||||
err = h.parse(buf[:n+bufStart], now, precision, db)
|
||||
if err != nil {
|
||||
log.Println("D! "+err.Error(), bufStart+n)
|
||||
h.Log.Debugf("%s: %s", err.Error(), bufStart+n)
|
||||
return400 = true
|
||||
}
|
||||
if return400 {
|
||||
@@ -349,7 +350,7 @@ func (h *HTTPListener) serveWrite(res http.ResponseWriter, req *http.Request) {
|
||||
if i == -1 {
|
||||
h.longLines.Incr(1)
|
||||
// drop any line longer than the max buffer size
|
||||
log.Printf("D! http_listener received a single line longer than the maximum of %d bytes",
|
||||
h.Log.Debugf("Http_listener received a single line longer than the maximum of %d bytes",
|
||||
len(buf))
|
||||
hangingBytes = true
|
||||
return400 = true
|
||||
@@ -357,7 +358,7 @@ func (h *HTTPListener) serveWrite(res http.ResponseWriter, req *http.Request) {
|
||||
continue
|
||||
}
|
||||
if err := h.parse(buf[:i+1], now, precision, db); err != nil {
|
||||
log.Println("D! " + err.Error())
|
||||
h.Log.Debug(err.Error())
|
||||
return400 = true
|
||||
}
|
||||
// rotate the bit remaining after the last newline to the front of the buffer
|
||||
|
||||
@@ -53,6 +53,7 @@ func init() {
|
||||
|
||||
func newTestHTTPListener() *HTTPListener {
|
||||
listener := &HTTPListener{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
TimeFunc: time.Now,
|
||||
}
|
||||
@@ -68,6 +69,7 @@ func newTestHTTPAuthListener() *HTTPListener {
|
||||
|
||||
func newTestHTTPSListener() *HTTPListener {
|
||||
listener := &HTTPListener{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
ServerConfig: *pki.TLSServerConfig(),
|
||||
TimeFunc: time.Now,
|
||||
@@ -321,6 +323,7 @@ func TestWriteHTTPNoNewline(t *testing.T) {
|
||||
|
||||
func TestWriteHTTPMaxLineSizeIncrease(t *testing.T) {
|
||||
listener := &HTTPListener{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
MaxLineSize: internal.Size{Size: 128 * 1000},
|
||||
TimeFunc: time.Now,
|
||||
@@ -369,6 +372,7 @@ func BenchmarkWriteHTTPMaxLineSizeIncrease(b *testing.B) {
|
||||
|
||||
func TestWriteHTTPVerySmallMaxBody(t *testing.T) {
|
||||
listener := &HTTPListener{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
MaxBodySize: internal.Size{Size: 4096},
|
||||
TimeFunc: time.Now,
|
||||
@@ -386,6 +390,7 @@ func TestWriteHTTPVerySmallMaxBody(t *testing.T) {
|
||||
|
||||
func TestWriteHTTPVerySmallMaxLineSize(t *testing.T) {
|
||||
listener := &HTTPListener{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
MaxLineSize: internal.Size{Size: 70},
|
||||
TimeFunc: time.Now,
|
||||
@@ -413,6 +418,7 @@ func TestWriteHTTPVerySmallMaxLineSize(t *testing.T) {
|
||||
|
||||
func TestWriteHTTPLargeLinesSkipped(t *testing.T) {
|
||||
listener := &HTTPListener{
|
||||
Log: testutil.Logger{},
|
||||
ServiceAddress: "localhost:0",
|
||||
MaxLineSize: internal.Size{Size: 100},
|
||||
TimeFunc: time.Now,
|
||||
|
||||
@@ -5,7 +5,6 @@ package ipvs
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/bits"
|
||||
"strconv"
|
||||
"syscall"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
// IPVS holds the state for this input plugin
|
||||
type IPVS struct {
|
||||
handle *ipvs.Handle
|
||||
Log telegraf.Logger
|
||||
}
|
||||
|
||||
// Description returns a description string
|
||||
@@ -61,7 +61,7 @@ func (i *IPVS) Gather(acc telegraf.Accumulator) error {
|
||||
|
||||
destinations, err := i.handle.GetDestinations(s)
|
||||
if err != nil {
|
||||
log.Println("E! Failed to list destinations for a virtual server")
|
||||
i.Log.Errorf("Failed to list destinations for a virtual server: %s", err.Error())
|
||||
continue // move on to the next virtual server
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -29,6 +28,8 @@ type Jenkins struct {
|
||||
tls.ClientConfig
|
||||
client *client
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
MaxConnections int `toml:"max_connections"`
|
||||
MaxBuildAge internal.Duration `toml:"max_build_age"`
|
||||
MaxSubJobDepth int `toml:"max_subjob_depth"`
|
||||
@@ -304,7 +305,7 @@ func (j *Jenkins) getJobDetail(jr jobRequest, acc telegraf.Accumulator) error {
|
||||
}
|
||||
|
||||
if build.Building {
|
||||
log.Printf("D! Ignore running build on %s, build %v", jr.name, number)
|
||||
j.Log.Debugf("Ignore running build on %s, build %v", jr.name, number)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -206,6 +206,7 @@ func TestGatherNodeData(t *testing.T) {
|
||||
ts := httptest.NewServer(test.input)
|
||||
defer ts.Close()
|
||||
j := &Jenkins{
|
||||
Log: testutil.Logger{},
|
||||
URL: ts.URL,
|
||||
ResponseTimeout: internal.Duration{Duration: time.Microsecond},
|
||||
NodeExclude: []string{"ignore-1", "ignore-2"},
|
||||
@@ -258,6 +259,7 @@ func TestInitialize(t *testing.T) {
|
||||
{
|
||||
name: "bad jenkins config",
|
||||
input: &Jenkins{
|
||||
Log: testutil.Logger{},
|
||||
URL: "http://a bad url",
|
||||
ResponseTimeout: internal.Duration{Duration: time.Microsecond},
|
||||
},
|
||||
@@ -266,6 +268,7 @@ func TestInitialize(t *testing.T) {
|
||||
{
|
||||
name: "has filter",
|
||||
input: &Jenkins{
|
||||
Log: testutil.Logger{},
|
||||
URL: ts.URL,
|
||||
ResponseTimeout: internal.Duration{Duration: time.Microsecond},
|
||||
JobExclude: []string{"job1", "job2"},
|
||||
@@ -275,10 +278,12 @@ func TestInitialize(t *testing.T) {
|
||||
{
|
||||
name: "default config",
|
||||
input: &Jenkins{
|
||||
Log: testutil.Logger{},
|
||||
URL: ts.URL,
|
||||
ResponseTimeout: internal.Duration{Duration: time.Microsecond},
|
||||
},
|
||||
output: &Jenkins{
|
||||
Log: testutil.Logger{},
|
||||
MaxConnections: 5,
|
||||
MaxSubJobPerLayer: 10,
|
||||
},
|
||||
@@ -570,6 +575,7 @@ func TestGatherJobs(t *testing.T) {
|
||||
ts := httptest.NewServer(test.input)
|
||||
defer ts.Close()
|
||||
j := &Jenkins{
|
||||
Log: testutil.Logger{},
|
||||
URL: ts.URL,
|
||||
MaxBuildAge: internal.Duration{Duration: time.Hour},
|
||||
ResponseTimeout: internal.Duration{Duration: time.Microsecond},
|
||||
|
||||
@@ -2,7 +2,6 @@ package jti_openconfig_telemetry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -34,6 +33,8 @@ type OpenConfigTelemetry struct {
|
||||
EnableTLS bool `toml:"enable_tls"`
|
||||
internaltls.ClientConfig
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
sensorsConfig []sensorConfig
|
||||
grpcClientConns []*grpc.ClientConn
|
||||
wg *sync.WaitGroup
|
||||
@@ -243,7 +244,7 @@ func (m *OpenConfigTelemetry) splitSensorConfig() int {
|
||||
}
|
||||
|
||||
if len(spathSplit) == 0 {
|
||||
log.Printf("E! No sensors are specified")
|
||||
m.Log.Error("No sensors are specified")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -257,7 +258,7 @@ func (m *OpenConfigTelemetry) splitSensorConfig() int {
|
||||
}
|
||||
|
||||
if len(spathSplit) == 0 {
|
||||
log.Printf("E! No valid sensors are specified")
|
||||
m.Log.Error("No valid sensors are specified")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -294,13 +295,13 @@ func (m *OpenConfigTelemetry) collectData(ctx context.Context,
|
||||
rpcStatus, _ := status.FromError(err)
|
||||
// If service is currently unavailable and may come back later, retry
|
||||
if rpcStatus.Code() != codes.Unavailable {
|
||||
acc.AddError(fmt.Errorf("E! Could not subscribe to %s: %v", grpcServer,
|
||||
acc.AddError(fmt.Errorf("could not subscribe to %s: %v", grpcServer,
|
||||
err))
|
||||
return
|
||||
} else {
|
||||
// Retry with delay. If delay is not provided, use default
|
||||
if m.RetryDelay.Duration > 0 {
|
||||
log.Printf("D! Retrying %s with timeout %v", grpcServer,
|
||||
m.Log.Debugf("Retrying %s with timeout %v", grpcServer,
|
||||
m.RetryDelay.Duration)
|
||||
time.Sleep(m.RetryDelay.Duration)
|
||||
continue
|
||||
@@ -314,11 +315,11 @@ func (m *OpenConfigTelemetry) collectData(ctx context.Context,
|
||||
if err != nil {
|
||||
// If we encounter error in the stream, break so we can retry
|
||||
// the connection
|
||||
acc.AddError(fmt.Errorf("E! Failed to read from %s: %v", err, grpcServer))
|
||||
acc.AddError(fmt.Errorf("failed to read from %s: %s", grpcServer, err))
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("D! Received from %s: %v", grpcServer, r)
|
||||
m.Log.Debugf("Received from %s: %v", grpcServer, r)
|
||||
|
||||
// Create a point and add to batch
|
||||
tags := make(map[string]string)
|
||||
@@ -329,7 +330,7 @@ func (m *OpenConfigTelemetry) collectData(ctx context.Context,
|
||||
dgroups := m.extractData(r, grpcServer)
|
||||
|
||||
// Print final data collection
|
||||
log.Printf("D! Available collection for %s is: %v", grpcServer, dgroups)
|
||||
m.Log.Debugf("Available collection for %s is: %v", grpcServer, dgroups)
|
||||
|
||||
tnow := time.Now()
|
||||
// Iterate through data groups and add them
|
||||
@@ -349,10 +350,9 @@ func (m *OpenConfigTelemetry) collectData(ctx context.Context,
|
||||
}
|
||||
|
||||
func (m *OpenConfigTelemetry) Start(acc telegraf.Accumulator) error {
|
||||
|
||||
// Build sensors config
|
||||
if m.splitSensorConfig() == 0 {
|
||||
return fmt.Errorf("E! No valid sensor configuration available")
|
||||
return fmt.Errorf("no valid sensor configuration available")
|
||||
}
|
||||
|
||||
// Parse TLS config
|
||||
@@ -376,15 +376,15 @@ func (m *OpenConfigTelemetry) Start(acc telegraf.Accumulator) error {
|
||||
// Extract device address and port
|
||||
grpcServer, grpcPort, err := net.SplitHostPort(server)
|
||||
if err != nil {
|
||||
log.Printf("E! Invalid server address: %v", err)
|
||||
m.Log.Errorf("Invalid server address: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
grpcClientConn, err = grpc.Dial(server, opts...)
|
||||
if err != nil {
|
||||
log.Printf("E! Failed to connect to %s: %v", server, err)
|
||||
m.Log.Errorf("Failed to connect to %s: %s", server, err.Error())
|
||||
} else {
|
||||
log.Printf("D! Opened a new gRPC session to %s on port %s", grpcServer, grpcPort)
|
||||
m.Log.Debugf("Opened a new gRPC session to %s on port %s", grpcServer, grpcPort)
|
||||
}
|
||||
|
||||
// Add to the list of client connections
|
||||
@@ -396,13 +396,13 @@ func (m *OpenConfigTelemetry) Start(acc telegraf.Accumulator) error {
|
||||
&authentication.LoginRequest{UserName: m.Username,
|
||||
Password: m.Password, ClientId: m.ClientID})
|
||||
if loginErr != nil {
|
||||
log.Printf("E! Could not initiate login check for %s: %v", server, loginErr)
|
||||
m.Log.Errorf("Could not initiate login check for %s: %v", server, loginErr)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if the user is authenticated. Bail if auth error
|
||||
if !loginReply.Result {
|
||||
log.Printf("E! Failed to authenticate the user for %s", server)
|
||||
m.Log.Errorf("Failed to authenticate the user for %s", server)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
)
|
||||
|
||||
var cfg = &OpenConfigTelemetry{
|
||||
Log: testutil.Logger{},
|
||||
Servers: []string{"127.0.0.1:50051"},
|
||||
SampleFrequency: internal.Duration{Duration: time.Second * 2},
|
||||
}
|
||||
|
||||
@@ -13,12 +13,16 @@ from the same topic in parallel.
|
||||
[[inputs.kafka_consumer]]
|
||||
## topic(s) to consume
|
||||
topics = ["telegraf"]
|
||||
|
||||
## an array of Zookeeper connection strings
|
||||
zookeeper_peers = ["localhost:2181"]
|
||||
|
||||
## Zookeeper Chroot
|
||||
zookeeper_chroot = ""
|
||||
|
||||
## the name of the consumer group
|
||||
consumer_group = "telegraf_metrics_consumers"
|
||||
|
||||
## Offset (must be either "oldest" or "newest")
|
||||
offset = "oldest"
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package kafka_consumer_legacy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -30,6 +29,8 @@ type Kafka struct {
|
||||
Offset string
|
||||
parser parsers.Parser
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
sync.Mutex
|
||||
|
||||
// channel for all incoming kafka messages
|
||||
@@ -49,12 +50,16 @@ type Kafka struct {
|
||||
var sampleConfig = `
|
||||
## topic(s) to consume
|
||||
topics = ["telegraf"]
|
||||
|
||||
## an array of Zookeeper connection strings
|
||||
zookeeper_peers = ["localhost:2181"]
|
||||
|
||||
## Zookeeper Chroot
|
||||
zookeeper_chroot = ""
|
||||
|
||||
## the name of the consumer group
|
||||
consumer_group = "telegraf_metrics_consumers"
|
||||
|
||||
## Offset (must be either "oldest" or "newest")
|
||||
offset = "oldest"
|
||||
|
||||
@@ -96,7 +101,7 @@ func (k *Kafka) Start(acc telegraf.Accumulator) error {
|
||||
case "newest":
|
||||
config.Offsets.Initial = sarama.OffsetNewest
|
||||
default:
|
||||
log.Printf("I! WARNING: Kafka consumer invalid offset '%s', using 'oldest'\n",
|
||||
k.Log.Infof("WARNING: Kafka consumer invalid offset '%s', using 'oldest'\n",
|
||||
k.Offset)
|
||||
config.Offsets.Initial = sarama.OffsetOldest
|
||||
}
|
||||
@@ -121,7 +126,7 @@ func (k *Kafka) Start(acc telegraf.Accumulator) error {
|
||||
|
||||
// Start the kafka message reader
|
||||
go k.receiver()
|
||||
log.Printf("I! Started the kafka consumer service, peers: %v, topics: %v\n",
|
||||
k.Log.Infof("Started the kafka consumer service, peers: %v, topics: %v\n",
|
||||
k.ZookeeperPeers, k.Topics)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ func TestReadsMetricsFromKafka(t *testing.T) {
|
||||
|
||||
// Start the Kafka Consumer
|
||||
k := &Kafka{
|
||||
Log: testutil.Logger{},
|
||||
ConsumerGroup: "telegraf_test_consumers",
|
||||
Topics: []string{testTopic},
|
||||
ZookeeperPeers: zkPeers,
|
||||
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
func newTestKafka() (*Kafka, chan *sarama.ConsumerMessage) {
|
||||
in := make(chan *sarama.ConsumerMessage, 1000)
|
||||
k := Kafka{
|
||||
Log: testutil.Logger{},
|
||||
ConsumerGroup: "test",
|
||||
Topics: []string{"telegraf"},
|
||||
ZookeeperPeers: []string{"localhost:2181"},
|
||||
|
||||
@@ -3,7 +3,6 @@ package kinesis_consumer
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -40,6 +39,8 @@ type (
|
||||
DynamoDB *DynamoDB `toml:"checkpoint_dynamodb"`
|
||||
MaxUndeliveredMessages int `toml:"max_undelivered_messages"`
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
cons *consumer.Consumer
|
||||
parser parsers.Parser
|
||||
cancel context.CancelFunc
|
||||
@@ -220,7 +221,7 @@ func (k *KinesisConsumer) connect(ac telegraf.Accumulator) error {
|
||||
})
|
||||
if err != nil {
|
||||
k.cancel()
|
||||
log.Printf("E! [inputs.kinesis_consumer] Scan encounterred an error - %s", err.Error())
|
||||
k.Log.Errorf("Scan encounterred an error: %s", err.Error())
|
||||
k.cons = nil
|
||||
}
|
||||
}()
|
||||
@@ -285,7 +286,7 @@ func (k *KinesisConsumer) onDelivery(ctx context.Context) {
|
||||
k.lastSeqNum = strToBint(sequenceNum)
|
||||
k.checkpoint.Set(chk.streamName, chk.shardID, sequenceNum)
|
||||
} else {
|
||||
log.Println("D! [inputs.kinesis_consumer] Metric group failed to process")
|
||||
k.Log.Debug("Metric group failed to process")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,4 +280,3 @@ kubernetes_statefulset,namespace=default,statefulset_name=etcd replicas_updated=
|
||||
[series cardinality]: https://docs.influxdata.com/influxdb/latest/query_language/spec/#show-cardinality
|
||||
[influx-docs]: https://docs.influxdata.com/influxdb/latest/
|
||||
[k8s-telegraf]: https://www.influxdata.com/blog/monitoring-kubernetes-architecture/
|
||||
[tick-charts]: https://github.com/influxdata/tick-charts
|
||||
|
||||
@@ -114,11 +114,11 @@ var availableCollectors = map[string]func(ctx context.Context, acc telegraf.Accu
|
||||
"endpoints": collectEndpoints,
|
||||
"ingress": collectIngress,
|
||||
"nodes": collectNodes,
|
||||
"persistentvolumes": collectPersistentVolumes,
|
||||
"persistentvolumeclaims": collectPersistentVolumeClaims,
|
||||
"pods": collectPods,
|
||||
"services": collectServices,
|
||||
"statefulsets": collectStatefulSets,
|
||||
"persistentvolumes": collectPersistentVolumes,
|
||||
"persistentvolumeclaims": collectPersistentVolumeClaims,
|
||||
}
|
||||
|
||||
func (ki *KubernetesInventory) initClient() (*client, error) {
|
||||
@@ -144,12 +144,12 @@ func atoi(s string) int64 {
|
||||
func convertQuantity(s string, m float64) int64 {
|
||||
q, err := resource.ParseQuantity(s)
|
||||
if err != nil {
|
||||
log.Printf("E! Failed to parse quantity - %v", err)
|
||||
log.Printf("D! [inputs.kube_inventory] failed to parse quantity: %s", err.Error())
|
||||
return 0
|
||||
}
|
||||
f, err := strconv.ParseFloat(fmt.Sprint(q.AsDec()), 64)
|
||||
if err != nil {
|
||||
log.Printf("E! Failed to parse float - %v", err)
|
||||
log.Printf("D! [inputs.kube_inventory] failed to parse float: %s", err.Error())
|
||||
return 0
|
||||
}
|
||||
if m < 1 {
|
||||
|
||||
@@ -48,7 +48,12 @@ avoid cardinality issues:
|
||||
### DaemonSet
|
||||
|
||||
For recommendations on running Telegraf as a DaemonSet see [Monitoring Kubernetes
|
||||
Architecture][k8s-telegraf] or view the [Helm charts][tick-charts].
|
||||
Architecture][k8s-telegraf] or view the Helm charts:
|
||||
|
||||
- [Telegraf][]
|
||||
- [InfluxDB][]
|
||||
- [Chronograf][]
|
||||
- [Kapacitor][]
|
||||
|
||||
### Metrics
|
||||
|
||||
@@ -136,4 +141,7 @@ kubernetes_system_container
|
||||
[series cardinality]: https://docs.influxdata.com/influxdb/latest/query_language/spec/#show-cardinality
|
||||
[influx-docs]: https://docs.influxdata.com/influxdb/latest/
|
||||
[k8s-telegraf]: https://www.influxdata.com/blog/monitoring-kubernetes-architecture/
|
||||
[tick-charts]: https://github.com/influxdata/tick-charts
|
||||
[Telegraf]: https://github.com/helm/charts/tree/master/stable/telegraf
|
||||
[InfluxDB]: https://github.com/helm/charts/tree/master/stable/influxdb
|
||||
[Chronograf]: https://github.com/helm/charts/tree/master/stable/chronograf
|
||||
[Kapacitor]: https://github.com/helm/charts/tree/master/stable/kapacitor
|
||||
|
||||
@@ -105,6 +105,7 @@ Patterns that convert all captures to tags will result in points that can't be w
|
||||
- ts-rfc3339nano ("2006-01-02T15:04:05.999999999Z07:00")
|
||||
- ts-httpd ("02/Jan/2006:15:04:05 -0700")
|
||||
- ts-epoch (seconds since unix epoch, may contain decimal)
|
||||
- ts-epochmilli (milliseconds since unix epoch, may contain decimal)
|
||||
- ts-epochnano (nanoseconds since unix epoch)
|
||||
- ts-syslog ("Jan 02 15:04:05", parsed time is set to the current year)
|
||||
- ts-"CUSTOM"
|
||||
|
||||
@@ -4,7 +4,6 @@ package logparser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -14,7 +13,6 @@ import (
|
||||
"github.com/influxdata/telegraf/internal/globpath"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
// Parsers
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -48,6 +46,8 @@ type LogParserPlugin struct {
|
||||
FromBeginning bool
|
||||
WatchMethod string
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
tailers map[string]*tail.Tail
|
||||
offsets map[string]int64
|
||||
lines chan logEntry
|
||||
@@ -207,7 +207,7 @@ func (l *LogParserPlugin) tailNewfiles(fromBeginning bool) error {
|
||||
for _, filepath := range l.Files {
|
||||
g, err := globpath.Compile(filepath)
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.logparser] Error Glob %s failed to compile, %s", filepath, err)
|
||||
l.Log.Errorf("Glob %q failed to compile: %s", filepath, err)
|
||||
continue
|
||||
}
|
||||
files := g.Match()
|
||||
@@ -221,7 +221,7 @@ func (l *LogParserPlugin) tailNewfiles(fromBeginning bool) error {
|
||||
var seek *tail.SeekInfo
|
||||
if !fromBeginning {
|
||||
if offset, ok := l.offsets[file]; ok {
|
||||
log.Printf("D! [inputs.tail] using offset %d for file: %v", offset, file)
|
||||
l.Log.Debugf("Using offset %d for file: %v", offset, file)
|
||||
seek = &tail.SeekInfo{
|
||||
Whence: 0,
|
||||
Offset: offset,
|
||||
@@ -248,7 +248,7 @@ func (l *LogParserPlugin) tailNewfiles(fromBeginning bool) error {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("D! [inputs.logparser] tail added for file: %v", file)
|
||||
l.Log.Debugf("Tail added for file: %v", file)
|
||||
|
||||
// create a goroutine for each "tailer"
|
||||
l.wg.Add(1)
|
||||
@@ -269,7 +269,7 @@ func (l *LogParserPlugin) receiver(tailer *tail.Tail) {
|
||||
for line = range tailer.Lines {
|
||||
|
||||
if line.Err != nil {
|
||||
log.Printf("E! [inputs.logparser] Error tailing file %s, Error: %s",
|
||||
l.Log.Errorf("Error tailing file %s, Error: %s",
|
||||
tailer.Filename, line.Err)
|
||||
continue
|
||||
}
|
||||
@@ -315,7 +315,7 @@ func (l *LogParserPlugin) parser() {
|
||||
l.acc.AddFields(m.Name(), m.Fields(), tags, m.Time())
|
||||
}
|
||||
} else {
|
||||
log.Println("E! [inputs.logparser] Error parsing log line: " + err.Error())
|
||||
l.Log.Errorf("Error parsing log line: %s", err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -332,7 +332,7 @@ func (l *LogParserPlugin) Stop() {
|
||||
offset, err := t.Tell()
|
||||
if err == nil {
|
||||
l.offsets[t.Filename] = offset
|
||||
log.Printf("D! [inputs.logparser] recording offset %d for file: %v", offset, t.Filename)
|
||||
l.Log.Debugf("Recording offset %d for file: %v", offset, t.Filename)
|
||||
} else {
|
||||
l.acc.AddError(fmt.Errorf("error recording offset for file %s", t.Filename))
|
||||
}
|
||||
@@ -340,10 +340,10 @@ func (l *LogParserPlugin) Stop() {
|
||||
err := t.Stop()
|
||||
|
||||
//message for a stopped tailer
|
||||
log.Printf("D! [inputs.logparser] tail dropped for file: %v", t.Filename)
|
||||
l.Log.Debugf("Tail dropped for file: %v", t.Filename)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.logparser] Error stopping tail on file %s", t.Filename)
|
||||
l.Log.Errorf("Error stopping tail on file %s", t.Filename)
|
||||
}
|
||||
}
|
||||
close(l.done)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
func TestStartNoParsers(t *testing.T) {
|
||||
logparser := &LogParserPlugin{
|
||||
Log: testutil.Logger{},
|
||||
FromBeginning: true,
|
||||
Files: []string{"testdata/*.log"},
|
||||
}
|
||||
@@ -26,6 +27,7 @@ func TestGrokParseLogFilesNonExistPattern(t *testing.T) {
|
||||
thisdir := getCurrentDir()
|
||||
|
||||
logparser := &LogParserPlugin{
|
||||
Log: testutil.Logger{},
|
||||
FromBeginning: true,
|
||||
Files: []string{thisdir + "testdata/*.log"},
|
||||
GrokConfig: GrokConfig{
|
||||
@@ -43,9 +45,10 @@ func TestGrokParseLogFiles(t *testing.T) {
|
||||
thisdir := getCurrentDir()
|
||||
|
||||
logparser := &LogParserPlugin{
|
||||
Log: testutil.Logger{},
|
||||
GrokConfig: GrokConfig{
|
||||
MeasurementName: "logparser_grok",
|
||||
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}"},
|
||||
Patterns: []string{"%{TEST_LOG_A}", "%{TEST_LOG_B}", "%{TEST_LOG_C}"},
|
||||
CustomPatternFiles: []string{thisdir + "testdata/test-patterns"},
|
||||
},
|
||||
FromBeginning: true,
|
||||
@@ -89,6 +92,7 @@ func TestGrokParseLogFilesAppearLater(t *testing.T) {
|
||||
thisdir := getCurrentDir()
|
||||
|
||||
logparser := &LogParserPlugin{
|
||||
Log: testutil.Logger{},
|
||||
FromBeginning: true,
|
||||
Files: []string{emptydir + "/*.log"},
|
||||
GrokConfig: GrokConfig{
|
||||
@@ -128,6 +132,7 @@ func TestGrokParseLogFilesOneBad(t *testing.T) {
|
||||
thisdir := getCurrentDir()
|
||||
|
||||
logparser := &LogParserPlugin{
|
||||
Log: testutil.Logger{},
|
||||
FromBeginning: true,
|
||||
Files: []string{thisdir + "testdata/test_a.log"},
|
||||
GrokConfig: GrokConfig{
|
||||
@@ -157,6 +162,40 @@ func TestGrokParseLogFilesOneBad(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestGrokParseLogFiles_TimestampInEpochMilli(t *testing.T) {
|
||||
thisdir := getCurrentDir()
|
||||
|
||||
logparser := &LogParserPlugin{
|
||||
Log: testutil.Logger{},
|
||||
GrokConfig: GrokConfig{
|
||||
MeasurementName: "logparser_grok",
|
||||
Patterns: []string{"%{TEST_LOG_C}"},
|
||||
CustomPatternFiles: []string{thisdir + "testdata/test-patterns"},
|
||||
},
|
||||
FromBeginning: true,
|
||||
Files: []string{thisdir + "testdata/test_c.log"},
|
||||
}
|
||||
|
||||
acc := testutil.Accumulator{}
|
||||
acc.SetDebug(true)
|
||||
assert.NoError(t, logparser.Start(&acc))
|
||||
acc.Wait(1)
|
||||
|
||||
logparser.Stop()
|
||||
|
||||
acc.AssertContainsTaggedFields(t, "logparser_grok",
|
||||
map[string]interface{}{
|
||||
"clientip": "192.168.1.1",
|
||||
"myfloat": float64(1.25),
|
||||
"response_time": int64(5432),
|
||||
"myint": int64(101),
|
||||
},
|
||||
map[string]string{
|
||||
"response_code": "200",
|
||||
"path": thisdir + "testdata/test_c.log",
|
||||
})
|
||||
}
|
||||
|
||||
func getCurrentDir() string {
|
||||
_, filename, _, _ := runtime.Caller(1)
|
||||
return strings.Replace(filename, "logparser_test.go", "", 1)
|
||||
|
||||
@@ -12,3 +12,7 @@ TEST_LOG_B \[%{TEST_TIMESTAMP:timestamp:ts-"02/01/2006--15:04:05"}\] %{NUMBER:my
|
||||
|
||||
TEST_TIMESTAMP %{MONTHDAY}/%{MONTHNUM}/%{YEAR}--%{TIME}
|
||||
TEST_LOG_BAD \[%{TEST_TIMESTAMP:timestamp:ts-"02/01/2006--15:04:05"}\] %{NUMBER:myfloat:float} %{WORD:mystring:int} %{WORD:dropme:drop} %{WORD:nomodifier}
|
||||
|
||||
# Test C log line:
|
||||
# 1568723594631 1.25 200 192.168.1.1 5.432µs 101
|
||||
TEST_LOG_C %{POSINT:timestamp:ts-epochmilli} %{NUMBER:myfloat:float} %{RESPONSE_CODE} %{IPORHOST:clientip} %{RESPONSE_TIME} %{NUMBER:myint:int}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1568723594631 1.25 200 192.168.1.1 5.432µs 101
|
||||
@@ -134,7 +134,7 @@ func runChimp(api *ChimpAPI, params ReportsParams) ([]byte, error) {
|
||||
req.URL.RawQuery = params.String()
|
||||
req.Header.Set("User-Agent", "Telegraf-MailChimp-Plugin")
|
||||
if api.Debug {
|
||||
log.Printf("D! Request URL: %s", req.URL.String())
|
||||
log.Printf("D! [inputs.mailchimp] request URL: %s", req.URL.String())
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
@@ -148,7 +148,7 @@ func runChimp(api *ChimpAPI, params ReportsParams) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
if api.Debug {
|
||||
log.Printf("D! Response Body:%s", string(body))
|
||||
log.Printf("D! [inputs.mailchimp] response Body: %q", string(body))
|
||||
}
|
||||
|
||||
if err = chimpErrorCheck(body); err != nil {
|
||||
|
||||
@@ -10,8 +10,10 @@ For more information, please check the [Mesos Observability Metrics](http://meso
|
||||
[[inputs.mesos]]
|
||||
## Timeout, in ms.
|
||||
timeout = 100
|
||||
|
||||
## A list of Mesos masters.
|
||||
masters = ["http://localhost:5050"]
|
||||
|
||||
## Master metrics groups to be collected, by default, all enabled.
|
||||
master_collections = [
|
||||
"resources",
|
||||
@@ -26,8 +28,10 @@ For more information, please check the [Mesos Observability Metrics](http://meso
|
||||
"registrar",
|
||||
"allocator",
|
||||
]
|
||||
|
||||
## A list of Mesos slaves, default is []
|
||||
# slaves = []
|
||||
|
||||
## Slave metrics groups to be collected, by default, all enabled.
|
||||
# slave_collections = [
|
||||
# "resources",
|
||||
|
||||
@@ -32,9 +32,10 @@ type Mesos struct {
|
||||
MasterCols []string `toml:"master_collections"`
|
||||
Slaves []string
|
||||
SlaveCols []string `toml:"slave_collections"`
|
||||
//SlaveTasks bool
|
||||
tls.ClientConfig
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
initialized bool
|
||||
client *http.Client
|
||||
masterURLs []*url.URL
|
||||
@@ -49,8 +50,10 @@ var allMetrics = map[Role][]string{
|
||||
var sampleConfig = `
|
||||
## Timeout, in ms.
|
||||
timeout = 100
|
||||
|
||||
## A list of Mesos masters.
|
||||
masters = ["http://localhost:5050"]
|
||||
|
||||
## Master metrics groups to be collected, by default, all enabled.
|
||||
master_collections = [
|
||||
"resources",
|
||||
@@ -65,8 +68,10 @@ var sampleConfig = `
|
||||
"registrar",
|
||||
"allocator",
|
||||
]
|
||||
|
||||
## A list of Mesos slaves, default is []
|
||||
# slaves = []
|
||||
|
||||
## Slave metrics groups to be collected, by default, all enabled.
|
||||
# slave_collections = [
|
||||
# "resources",
|
||||
@@ -110,7 +115,7 @@ func parseURL(s string, role Role) (*url.URL, error) {
|
||||
}
|
||||
|
||||
s = "http://" + host + ":" + port
|
||||
log.Printf("W! [inputs.mesos] Using %q as connection URL; please update your configuration to use an URL", s)
|
||||
log.Printf("W! [inputs.mesos] using %q as connection URL; please update your configuration to use an URL", s)
|
||||
}
|
||||
|
||||
return url.Parse(s)
|
||||
@@ -126,7 +131,7 @@ func (m *Mesos) initialize() error {
|
||||
}
|
||||
|
||||
if m.Timeout == 0 {
|
||||
log.Println("I! [inputs.mesos] Missing timeout value, setting default value (100ms)")
|
||||
m.Log.Info("Missing timeout value, setting default value (100ms)")
|
||||
m.Timeout = 100
|
||||
}
|
||||
|
||||
@@ -191,17 +196,6 @@ func (m *Mesos) Gather(acc telegraf.Accumulator) error {
|
||||
wg.Done()
|
||||
return
|
||||
}(slave)
|
||||
|
||||
// if !m.SlaveTasks {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// wg.Add(1)
|
||||
// go func(c string) {
|
||||
// acc.AddError(m.gatherSlaveTaskMetrics(slave, acc))
|
||||
// wg.Done()
|
||||
// return
|
||||
// }(v)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
@@ -487,7 +481,7 @@ func getMetrics(role Role, group string) []string {
|
||||
ret, ok := m[group]
|
||||
|
||||
if !ok {
|
||||
log.Printf("I! [mesos] Unknown %s metrics group: %s\n", role, group)
|
||||
log.Printf("I! [inputs.mesos] unknown role %q metrics group: %s", role, group)
|
||||
return []string{}
|
||||
}
|
||||
|
||||
|
||||
@@ -349,6 +349,7 @@ func TestMesosMaster(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
m := Mesos{
|
||||
Log: testutil.Logger{},
|
||||
Masters: []string{masterTestServer.Listener.Addr().String()},
|
||||
Timeout: 10,
|
||||
}
|
||||
@@ -364,6 +365,7 @@ func TestMesosMaster(t *testing.T) {
|
||||
|
||||
func TestMasterFilter(t *testing.T) {
|
||||
m := Mesos{
|
||||
Log: testutil.Logger{},
|
||||
MasterCols: []string{
|
||||
"resources", "master", "registrar", "allocator",
|
||||
},
|
||||
@@ -416,6 +418,7 @@ func TestMesosSlave(t *testing.T) {
|
||||
var acc testutil.Accumulator
|
||||
|
||||
m := Mesos{
|
||||
Log: testutil.Logger{},
|
||||
Masters: []string{},
|
||||
Slaves: []string{slaveTestServer.Listener.Addr().String()},
|
||||
// SlaveTasks: true,
|
||||
@@ -433,6 +436,7 @@ func TestMesosSlave(t *testing.T) {
|
||||
|
||||
func TestSlaveFilter(t *testing.T) {
|
||||
m := Mesos{
|
||||
Log: testutil.Logger{},
|
||||
SlaveCols: []string{
|
||||
"resources", "agent", "tasks",
|
||||
},
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -25,6 +24,8 @@ type MongoDB struct {
|
||||
GatherColStats bool
|
||||
ColStatsDbs []string
|
||||
tlsint.ClientConfig
|
||||
|
||||
Log telegraf.Logger
|
||||
}
|
||||
|
||||
type Ssl struct {
|
||||
@@ -82,24 +83,24 @@ func (m *MongoDB) Gather(acc telegraf.Accumulator) error {
|
||||
// Preserve backwards compatibility for hostnames without a
|
||||
// scheme, broken in go 1.8. Remove in Telegraf 2.0
|
||||
serv = "mongodb://" + serv
|
||||
log.Printf("W! [inputs.mongodb] Using %q as connection URL; please update your configuration to use an URL", serv)
|
||||
m.Log.Warnf("Using %q as connection URL; please update your configuration to use an URL", serv)
|
||||
m.Servers[i] = serv
|
||||
}
|
||||
|
||||
u, err := url.Parse(serv)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("Unable to parse address %q: %s", serv, err))
|
||||
m.Log.Errorf("Unable to parse address %q: %s", serv, err.Error())
|
||||
continue
|
||||
}
|
||||
if u.Host == "" {
|
||||
acc.AddError(fmt.Errorf("Unable to parse address %q", serv))
|
||||
m.Log.Errorf("Unable to parse address %q", serv)
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(srv *Server) {
|
||||
defer wg.Done()
|
||||
acc.AddError(m.gatherServer(srv, acc))
|
||||
m.Log.Error(m.gatherServer(srv, acc))
|
||||
}(m.getMongoServer(u))
|
||||
}
|
||||
|
||||
@@ -110,6 +111,7 @@ func (m *MongoDB) Gather(acc telegraf.Accumulator) error {
|
||||
func (m *MongoDB) getMongoServer(url *url.URL) *Server {
|
||||
if _, ok := m.mongos[url.Host]; !ok {
|
||||
m.mongos[url.Host] = &Server{
|
||||
Log: m.Log,
|
||||
Url: url,
|
||||
}
|
||||
}
|
||||
@@ -126,8 +128,7 @@ func (m *MongoDB) gatherServer(server *Server, acc telegraf.Accumulator) error {
|
||||
}
|
||||
dialInfo, err := mgo.ParseURL(dialAddrs[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to parse URL (%s), %s\n",
|
||||
dialAddrs[0], err.Error())
|
||||
return fmt.Errorf("unable to parse URL %q: %s", dialAddrs[0], err.Error())
|
||||
}
|
||||
dialInfo.Direct = true
|
||||
dialInfo.Timeout = 5 * time.Second
|
||||
@@ -169,7 +170,7 @@ func (m *MongoDB) gatherServer(server *Server, acc telegraf.Accumulator) error {
|
||||
|
||||
sess, err := mgo.DialWithInfo(dialInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to connect to MongoDB, %s\n", err.Error())
|
||||
return fmt.Errorf("unable to connect to MongoDB: %s", err.Error())
|
||||
}
|
||||
server.Session = sess
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mongodb
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -15,6 +15,8 @@ type Server struct {
|
||||
Url *url.URL
|
||||
Session *mgo.Session
|
||||
lastResult *MongoStatus
|
||||
|
||||
Log telegraf.Logger
|
||||
}
|
||||
|
||||
func (s *Server) getDefaultTags() map[string]string {
|
||||
@@ -31,11 +33,11 @@ func IsAuthorization(err error) bool {
|
||||
return strings.Contains(err.Error(), "not authorized")
|
||||
}
|
||||
|
||||
func authLogLevel(err error) string {
|
||||
func (s *Server) authLog(err error) {
|
||||
if IsAuthorization(err) {
|
||||
return "D!"
|
||||
s.Log.Debug(err.Error())
|
||||
} else {
|
||||
return "E!"
|
||||
s.Log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,30 +160,30 @@ func (s *Server) gatherCollectionStats(colStatsDbs []string) (*ColStats, error)
|
||||
}
|
||||
|
||||
results := &ColStats{}
|
||||
for _, db_name := range names {
|
||||
if stringInSlice(db_name, colStatsDbs) || len(colStatsDbs) == 0 {
|
||||
for _, dbName := range names {
|
||||
if stringInSlice(dbName, colStatsDbs) || len(colStatsDbs) == 0 {
|
||||
var colls []string
|
||||
colls, err = s.Session.DB(db_name).CollectionNames()
|
||||
colls, err = s.Session.DB(dbName).CollectionNames()
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.mongodb] Error getting collection names: %v", err)
|
||||
s.Log.Errorf("Error getting collection names: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
for _, col_name := range colls {
|
||||
col_stat_line := &ColStatsData{}
|
||||
err = s.Session.DB(db_name).Run(bson.D{
|
||||
for _, colName := range colls {
|
||||
colStatLine := &ColStatsData{}
|
||||
err = s.Session.DB(dbName).Run(bson.D{
|
||||
{
|
||||
Name: "collStats",
|
||||
Value: col_name,
|
||||
Value: colName,
|
||||
},
|
||||
}, col_stat_line)
|
||||
}, colStatLine)
|
||||
if err != nil {
|
||||
log.Printf("%s [inputs.mongodb] Error getting col stats from %q: %v", authLogLevel(err), col_name, err)
|
||||
s.authLog(fmt.Errorf("error getting col stats from %q: %v", colName, err))
|
||||
continue
|
||||
}
|
||||
collection := &Collection{
|
||||
Name: col_name,
|
||||
DbName: db_name,
|
||||
ColStatsData: col_stat_line,
|
||||
Name: colName,
|
||||
DbName: dbName,
|
||||
ColStatsData: colStatLine,
|
||||
}
|
||||
results.Collections = append(results.Collections, *collection)
|
||||
}
|
||||
@@ -203,7 +205,7 @@ func (s *Server) gatherData(acc telegraf.Accumulator, gatherDbStats bool, gather
|
||||
// member of a replica set.
|
||||
replSetStatus, err := s.gatherReplSetStatus()
|
||||
if err != nil {
|
||||
log.Printf("D! [inputs.mongodb] Unable to gather replica set status: %v", err)
|
||||
s.Log.Debugf("Unable to gather replica set status: %s", err.Error())
|
||||
}
|
||||
|
||||
// Gather the oplog if we are a member of a replica set. Non-replica set
|
||||
@@ -218,13 +220,12 @@ func (s *Server) gatherData(acc telegraf.Accumulator, gatherDbStats bool, gather
|
||||
|
||||
clusterStatus, err := s.gatherClusterStatus()
|
||||
if err != nil {
|
||||
log.Printf("D! [inputs.mongodb] Unable to gather cluster status: %v", err)
|
||||
s.Log.Debugf("Unable to gather cluster status: %s", err.Error())
|
||||
}
|
||||
|
||||
shardStats, err := s.gatherShardConnPoolStats()
|
||||
if err != nil {
|
||||
log.Printf("%s [inputs.mongodb] Unable to gather shard connection pool stats: %v",
|
||||
authLogLevel(err), err)
|
||||
s.authLog(fmt.Errorf("unable to gather shard connection pool stats: %s", err.Error()))
|
||||
}
|
||||
|
||||
var collectionStats *ColStats
|
||||
@@ -246,7 +247,7 @@ func (s *Server) gatherData(acc telegraf.Accumulator, gatherDbStats bool, gather
|
||||
for _, name := range names {
|
||||
db, err := s.gatherDBStats(name)
|
||||
if err != nil {
|
||||
log.Printf("D! [inputs.mongodb] Error getting db stats from %q: %v", name, err)
|
||||
s.Log.Debugf("Error getting db stats from %q: %s", name, err.Error())
|
||||
}
|
||||
dbStats.Dbs = append(dbStats.Dbs, *db)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -61,6 +60,8 @@ type MQTTConsumer struct {
|
||||
ClientID string `toml:"client_id"`
|
||||
tls.ClientConfig
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
clientFactory ClientFactory
|
||||
client Client
|
||||
opts *mqtt.ClientOptions
|
||||
@@ -212,7 +213,7 @@ func (m *MQTTConsumer) connect() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("I! [inputs.mqtt_consumer] Connected %v", m.Servers)
|
||||
m.Log.Infof("Connected %v", m.Servers)
|
||||
m.state = Connected
|
||||
m.sem = make(semaphore, m.MaxUndeliveredMessages)
|
||||
m.messages = make(map[telegraf.TrackingID]bool)
|
||||
@@ -223,7 +224,7 @@ func (m *MQTTConsumer) connect() error {
|
||||
SessionPresent() bool
|
||||
}
|
||||
if t, ok := token.(sessionPresent); ok && t.SessionPresent() {
|
||||
log.Printf("D! [inputs.mqtt_consumer] Session found %v", m.Servers)
|
||||
m.Log.Debugf("Session found %v", m.Servers)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@ func (m *MQTTConsumer) connect() error {
|
||||
|
||||
func (m *MQTTConsumer) onConnectionLost(c mqtt.Client, err error) {
|
||||
m.acc.AddError(fmt.Errorf("connection lost: %v", err))
|
||||
log.Printf("D! [inputs.mqtt_consumer] Disconnected %v", m.Servers)
|
||||
m.Log.Debugf("Disconnected %v", m.Servers)
|
||||
m.state = Disconnected
|
||||
return
|
||||
}
|
||||
@@ -292,9 +293,9 @@ func (m *MQTTConsumer) onMessage(acc telegraf.TrackingAccumulator, msg mqtt.Mess
|
||||
|
||||
func (m *MQTTConsumer) Stop() {
|
||||
if m.state == Connected {
|
||||
log.Printf("D! [inputs.mqtt_consumer] Disconnecting %v", m.Servers)
|
||||
m.Log.Debugf("Disconnecting %v", m.Servers)
|
||||
m.client.Disconnect(200)
|
||||
log.Printf("D! [inputs.mqtt_consumer] Disconnected %v", m.Servers)
|
||||
m.Log.Debugf("Disconnected %v", m.Servers)
|
||||
m.state = Disconnected
|
||||
}
|
||||
m.cancel()
|
||||
@@ -303,7 +304,7 @@ func (m *MQTTConsumer) Stop() {
|
||||
func (m *MQTTConsumer) Gather(acc telegraf.Accumulator) error {
|
||||
if m.state == Disconnected {
|
||||
m.state = Connecting
|
||||
log.Printf("D! [inputs.mqtt_consumer] Connecting %v", m.Servers)
|
||||
m.Log.Debugf("Connecting %v", m.Servers)
|
||||
m.connect()
|
||||
}
|
||||
|
||||
@@ -346,7 +347,7 @@ func (m *MQTTConsumer) createOpts() (*mqtt.ClientOptions, error) {
|
||||
for _, server := range m.Servers {
|
||||
// Preserve support for host:port style servers; deprecated in Telegraf 1.4.4
|
||||
if !strings.Contains(server, "://") {
|
||||
log.Printf("W! [inputs.mqtt_consumer] Server %q should be updated to use `scheme://host:port` format", server)
|
||||
m.Log.Warnf("Server %q should be updated to use `scheme://host:port` format", server)
|
||||
if tlsCfg == nil {
|
||||
server = "tcp://" + server
|
||||
} else {
|
||||
|
||||
@@ -102,6 +102,7 @@ func TestLifecycleSanity(t *testing.T) {
|
||||
},
|
||||
}
|
||||
})
|
||||
plugin.Log = testutil.Logger{}
|
||||
plugin.Servers = []string{"tcp://127.0.0.1"}
|
||||
|
||||
parser := &FakeParser{}
|
||||
@@ -124,10 +125,12 @@ func TestRandomClientID(t *testing.T) {
|
||||
var err error
|
||||
|
||||
m1 := New(nil)
|
||||
m1.Log = testutil.Logger{}
|
||||
err = m1.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
m2 := New(nil)
|
||||
m2.Log = testutil.Logger{}
|
||||
err = m2.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -137,6 +140,7 @@ func TestRandomClientID(t *testing.T) {
|
||||
// PersistentSession requires ClientID
|
||||
func TestPersistentClientIDFail(t *testing.T) {
|
||||
plugin := New(nil)
|
||||
plugin.Log = testutil.Logger{}
|
||||
plugin.PersistentSession = true
|
||||
|
||||
err := plugin.Init()
|
||||
@@ -255,6 +259,7 @@ func TestTopicTag(t *testing.T) {
|
||||
plugin := New(func(o *mqtt.ClientOptions) Client {
|
||||
return client
|
||||
})
|
||||
plugin.Log = testutil.Logger{}
|
||||
plugin.Topics = []string{"telegraf"}
|
||||
plugin.TopicTag = tt.topicTag()
|
||||
|
||||
@@ -295,6 +300,7 @@ func TestAddRouteCalledForEachTopic(t *testing.T) {
|
||||
plugin := New(func(o *mqtt.ClientOptions) Client {
|
||||
return client
|
||||
})
|
||||
plugin.Log = testutil.Logger{}
|
||||
plugin.Topics = []string{"a", "b"}
|
||||
|
||||
err := plugin.Init()
|
||||
@@ -325,6 +331,7 @@ func TestSubscribeCalledIfNoSession(t *testing.T) {
|
||||
plugin := New(func(o *mqtt.ClientOptions) Client {
|
||||
return client
|
||||
})
|
||||
plugin.Log = testutil.Logger{}
|
||||
plugin.Topics = []string{"b"}
|
||||
|
||||
err := plugin.Init()
|
||||
@@ -355,6 +362,7 @@ func TestSubscribeNotCalledIfSession(t *testing.T) {
|
||||
plugin := New(func(o *mqtt.ClientOptions) Client {
|
||||
return client
|
||||
})
|
||||
plugin.Log = testutil.Logger{}
|
||||
plugin.Topics = []string{"b"}
|
||||
|
||||
err := plugin.Init()
|
||||
|
||||
@@ -39,9 +39,12 @@ type Mysql struct {
|
||||
IntervalSlow string `toml:"interval_slow"`
|
||||
MetricVersion int `toml:"metric_version"`
|
||||
tls.ClientConfig
|
||||
lastT time.Time
|
||||
initDone bool
|
||||
scanIntervalSlow uint32
|
||||
}
|
||||
|
||||
var sampleConfig = `
|
||||
const sampleConfig = `
|
||||
## specify servers via a url matching:
|
||||
## [username[:password]@][protocol[(address)]]/[?tls=[true|false|skip-verify|custom]]
|
||||
## see https://github.com/go-sql-driver/mysql#dsn-data-source-name
|
||||
@@ -123,7 +126,7 @@ var sampleConfig = `
|
||||
# insecure_skip_verify = false
|
||||
`
|
||||
|
||||
var defaultTimeout = time.Second * time.Duration(5)
|
||||
const defaultTimeout = time.Second * time.Duration(5)
|
||||
|
||||
func (m *Mysql) SampleConfig() string {
|
||||
return sampleConfig
|
||||
@@ -133,21 +136,16 @@ func (m *Mysql) Description() string {
|
||||
return "Read metrics from one or many mysql servers"
|
||||
}
|
||||
|
||||
var (
|
||||
localhost = ""
|
||||
lastT time.Time
|
||||
initDone = false
|
||||
scanIntervalSlow uint32
|
||||
)
|
||||
const localhost = ""
|
||||
|
||||
func (m *Mysql) InitMysql() {
|
||||
if len(m.IntervalSlow) > 0 {
|
||||
interval, err := time.ParseDuration(m.IntervalSlow)
|
||||
if err == nil && interval.Seconds() >= 1.0 {
|
||||
scanIntervalSlow = uint32(interval.Seconds())
|
||||
m.scanIntervalSlow = uint32(interval.Seconds())
|
||||
}
|
||||
}
|
||||
initDone = true
|
||||
m.initDone = true
|
||||
}
|
||||
|
||||
func (m *Mysql) Gather(acc telegraf.Accumulator) error {
|
||||
@@ -156,7 +154,7 @@ func (m *Mysql) Gather(acc telegraf.Accumulator) error {
|
||||
return m.gatherServer(localhost, acc)
|
||||
}
|
||||
// Initialise additional query intervals
|
||||
if !initDone {
|
||||
if !m.initDone {
|
||||
m.InitMysql()
|
||||
}
|
||||
|
||||
@@ -184,6 +182,7 @@ func (m *Mysql) Gather(acc telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// These are const but can't be declared as such because golang doesn't allow const maps
|
||||
var (
|
||||
// status counter
|
||||
generalThreadStates = map[string]uint32{
|
||||
@@ -426,12 +425,12 @@ func (m *Mysql) gatherServer(serv string, acc telegraf.Accumulator) error {
|
||||
|
||||
// Global Variables may be gathered less often
|
||||
if len(m.IntervalSlow) > 0 {
|
||||
if uint32(time.Since(lastT).Seconds()) >= scanIntervalSlow {
|
||||
if uint32(time.Since(m.lastT).Seconds()) >= m.scanIntervalSlow {
|
||||
err = m.gatherGlobalVariables(db, serv, acc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lastT = time.Now()
|
||||
m.lastT = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,54 @@ func TestMysqlDefaultsToLocal(t *testing.T) {
|
||||
assert.True(t, acc.HasMeasurement("mysql"))
|
||||
}
|
||||
|
||||
func TestMysqlMultipleInstances(t *testing.T) {
|
||||
// Invoke Gather() from two separate configurations and
|
||||
// confirm they don't interfere with each other
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
testServer := "root@tcp(127.0.0.1:3306)/?tls=false"
|
||||
m := &Mysql{
|
||||
Servers: []string{testServer},
|
||||
IntervalSlow: "30s",
|
||||
}
|
||||
|
||||
var acc, acc2 testutil.Accumulator
|
||||
err := m.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, acc.HasMeasurement("mysql"))
|
||||
// acc should have global variables
|
||||
assert.True(t, acc.HasMeasurement("mysql_variables"))
|
||||
|
||||
m2 := &Mysql{
|
||||
Servers: []string{testServer},
|
||||
}
|
||||
err = m2.Gather(&acc2)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, acc2.HasMeasurement("mysql"))
|
||||
// acc2 should not have global variables
|
||||
assert.False(t, acc2.HasMeasurement("mysql_variables"))
|
||||
}
|
||||
|
||||
func TestMysqlMultipleInits(t *testing.T) {
|
||||
m := &Mysql{
|
||||
IntervalSlow: "30s",
|
||||
}
|
||||
m2 := &Mysql{}
|
||||
|
||||
m.InitMysql()
|
||||
assert.True(t, m.initDone)
|
||||
assert.False(t, m2.initDone)
|
||||
assert.Equal(t, m.scanIntervalSlow, uint32(30))
|
||||
assert.Equal(t, m2.scanIntervalSlow, uint32(0))
|
||||
|
||||
m2.InitMysql()
|
||||
assert.True(t, m.initDone)
|
||||
assert.True(t, m2.initDone)
|
||||
assert.Equal(t, m.scanIntervalSlow, uint32(30))
|
||||
assert.Equal(t, m2.scanIntervalSlow, uint32(0))
|
||||
}
|
||||
|
||||
func TestMysqlGetDSNTag(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
|
||||
@@ -12,8 +12,10 @@ instances of telegraf can read from a NATS cluster in parallel.
|
||||
[[inputs.nats_consumer]]
|
||||
## urls of NATS servers
|
||||
servers = ["nats://localhost:4222"]
|
||||
|
||||
## subject(s) to consume
|
||||
subjects = ["telegraf"]
|
||||
|
||||
## name a queue group
|
||||
queue_group = "telegraf_consumers"
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package natsconsumer
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
@@ -40,6 +39,8 @@ type natsConsumer struct {
|
||||
Password string `toml:"password"`
|
||||
tls.ClientConfig
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
// Client pending limits:
|
||||
PendingMessageLimit int `toml:"pending_message_limit"`
|
||||
PendingBytesLimit int `toml:"pending_bytes_limit"`
|
||||
@@ -68,6 +69,7 @@ var sampleConfig = `
|
||||
|
||||
## subject(s) to consume
|
||||
subjects = ["telegraf"]
|
||||
|
||||
## name a queue group
|
||||
queue_group = "telegraf_consumers"
|
||||
|
||||
@@ -198,7 +200,7 @@ func (n *natsConsumer) Start(acc telegraf.Accumulator) error {
|
||||
go n.receiver(ctx)
|
||||
}()
|
||||
|
||||
log.Printf("I! Started the NATS consumer service, nats: %v, subjects: %v, queue: %v\n",
|
||||
n.Log.Infof("Started the NATS consumer service, nats: %v, subjects: %v, queue: %v",
|
||||
n.conn.ConnectedUrl(), n.Subjects, n.QueueGroup)
|
||||
|
||||
return nil
|
||||
@@ -216,21 +218,21 @@ func (n *natsConsumer) receiver(ctx context.Context) {
|
||||
case <-n.acc.Delivered():
|
||||
<-sem
|
||||
case err := <-n.errs:
|
||||
n.acc.AddError(err)
|
||||
n.Log.Error(err)
|
||||
case sem <- empty{}:
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case err := <-n.errs:
|
||||
<-sem
|
||||
n.acc.AddError(err)
|
||||
n.Log.Error(err)
|
||||
case <-n.acc.Delivered():
|
||||
<-sem
|
||||
<-sem
|
||||
case msg := <-n.in:
|
||||
metrics, err := n.parser.Parse(msg.Data)
|
||||
if err != nil {
|
||||
n.acc.AddError(fmt.Errorf("subject: %s, error: %s", msg.Subject, err.Error()))
|
||||
n.Log.Errorf("Subject: %s, error: %s", msg.Subject, err.Error())
|
||||
<-sem
|
||||
continue
|
||||
}
|
||||
@@ -244,8 +246,8 @@ func (n *natsConsumer) receiver(ctx context.Context) {
|
||||
func (n *natsConsumer) clean() {
|
||||
for _, sub := range n.subs {
|
||||
if err := sub.Unsubscribe(); err != nil {
|
||||
n.acc.AddError(fmt.Errorf("Error unsubscribing from subject %s in queue %s: %s\n",
|
||||
sub.Subject, sub.Queue, err.Error()))
|
||||
n.Log.Errorf("Error unsubscribing from subject %s in queue %s: %s",
|
||||
sub.Subject, sub.Queue, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@ of the supported [input data formats][].
|
||||
[[inputs.nsq_consumer]]
|
||||
## Server option still works but is deprecated, we just prepend it to the nsqd array.
|
||||
# server = "localhost:4150"
|
||||
|
||||
## An array representing the NSQD TCP HTTP Endpoints
|
||||
nsqd = ["localhost:4150"]
|
||||
|
||||
## An array representing the NSQLookupd HTTP Endpoints
|
||||
nsqlookupd = ["localhost:4161"]
|
||||
topic = "telegraf"
|
||||
|
||||
@@ -2,7 +2,6 @@ package nsq_consumer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
@@ -18,10 +17,12 @@ const (
|
||||
type empty struct{}
|
||||
type semaphore chan empty
|
||||
|
||||
type logger struct{}
|
||||
type logger struct {
|
||||
log telegraf.Logger
|
||||
}
|
||||
|
||||
func (l *logger) Output(calldepth int, s string) error {
|
||||
log.Println("D! [inputs.nsq_consumer] " + s)
|
||||
l.log.Debug(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -39,6 +40,8 @@ type NSQConsumer struct {
|
||||
parser parsers.Parser
|
||||
consumer *nsq.Consumer
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
mu sync.Mutex
|
||||
messages map[telegraf.TrackingID]*nsq.Message
|
||||
wg sync.WaitGroup
|
||||
@@ -48,8 +51,10 @@ type NSQConsumer struct {
|
||||
var sampleConfig = `
|
||||
## Server option still works but is deprecated, we just prepend it to the nsqd array.
|
||||
# server = "localhost:4150"
|
||||
|
||||
## An array representing the NSQD TCP HTTP Endpoints
|
||||
nsqd = ["localhost:4150"]
|
||||
|
||||
## An array representing the NSQLookupd HTTP Endpoints
|
||||
nsqlookupd = ["localhost:4161"]
|
||||
topic = "telegraf"
|
||||
@@ -98,7 +103,7 @@ func (n *NSQConsumer) Start(ac telegraf.Accumulator) error {
|
||||
n.cancel = cancel
|
||||
|
||||
n.connect()
|
||||
n.consumer.SetLogger(&logger{}, nsq.LogLevelInfo)
|
||||
n.consumer.SetLogger(&logger{log: n.Log}, nsq.LogLevelInfo)
|
||||
n.consumer.AddHandler(nsq.HandlerFunc(func(message *nsq.Message) error {
|
||||
metrics, err := n.parser.Parse(message.Body)
|
||||
if err != nil {
|
||||
|
||||
@@ -36,6 +36,7 @@ func TestReadsMetricsFromNSQ(t *testing.T) {
|
||||
newMockNSQD(script, addr.String())
|
||||
|
||||
consumer := &NSQConsumer{
|
||||
Log: testutil.Logger{},
|
||||
Server: "127.0.0.1:4155",
|
||||
Topic: "telegraf",
|
||||
Channel: "consume",
|
||||
|
||||
+109
-60
@@ -2,92 +2,142 @@
|
||||
|
||||
Sends a ping message by executing the system ping command and reports the results.
|
||||
|
||||
This plugin has two main methods of operation: `exec` and `native`. The
|
||||
recommended method is `native`, which has greater system compatibility and
|
||||
performance. However, for backwards compatibility the `exec` method is the
|
||||
default.
|
||||
|
||||
When using `method = "exec"`, the systems ping utility is executed to send the
|
||||
ping packets.
|
||||
|
||||
Most ping command implementations are supported, one notable exception being
|
||||
that there is currently no support for GNU Inetutils ping. You may instead
|
||||
use the iputils-ping implementation:
|
||||
that there is currently no support for GNU Inetutils ping. You may instead use
|
||||
the iputils-ping implementation:
|
||||
```
|
||||
apt-get install iputils-ping
|
||||
```
|
||||
|
||||
When using `method = "native"` a ping is sent and the results are reported in pure go, eliminating the need to execute the system `ping` command. Not using the system binary allows the use of this plugin on non-english systems.
|
||||
|
||||
There is currently no support for TTL on windows with `"native"`; track progress at https://github.com/golang/go/issues/7175 and https://github.com/golang/go/issues/7174
|
||||
When using `method = "native"` a ping is sent and the results are reported in
|
||||
native Go by the Telegraf process, eliminating the need to execute the system
|
||||
`ping` command.
|
||||
|
||||
### Configuration:
|
||||
|
||||
```toml
|
||||
[[inputs.ping]]
|
||||
## List of urls to ping
|
||||
## Hosts to send ping packets to.
|
||||
urls = ["example.org"]
|
||||
|
||||
## Number of pings to send per collection (ping -c <COUNT>)
|
||||
# count = 1
|
||||
|
||||
## Interval, in s, at which to ping. 0 == default (ping -i <PING_INTERVAL>)
|
||||
## Not available in Windows.
|
||||
# ping_interval = 1.0
|
||||
|
||||
## Per-ping timeout, in s. 0 == no timeout (ping -W <TIMEOUT>)
|
||||
# timeout = 1.0
|
||||
|
||||
## Total-ping deadline, in s. 0 == no deadline (ping -w <DEADLINE>)
|
||||
# deadline = 10
|
||||
|
||||
## Interface or source address to send ping from (ping -I <INTERFACE/SRC_ADDR>)
|
||||
## on Darwin and Freebsd only source address possible: (ping -S <SRC_ADDR>)
|
||||
# interface = ""
|
||||
|
||||
## How to ping. "native" doesn't have external dependencies, while "exec" depends on 'ping'.
|
||||
## Method used for sending pings, can be either "exec" or "native". When set
|
||||
## to "exec" the systems ping command will be executed. When set to "native"
|
||||
## the plugin will send pings directly.
|
||||
##
|
||||
## While the default is "exec" for backwards compatibility, new deployments
|
||||
## are encouraged to use the "native" method for improved compatibility and
|
||||
## performance.
|
||||
# method = "exec"
|
||||
|
||||
## Specify the ping executable binary, default is "ping"
|
||||
## Number of ping packets to send per interval. Corresponds to the "-c"
|
||||
## option of the ping command.
|
||||
# count = 1
|
||||
|
||||
## Time to wait between sending ping packets in seconds. Operates like the
|
||||
## "-i" option of the ping command.
|
||||
# ping_interval = 1.0
|
||||
|
||||
## If set, the time to wait for a ping response in seconds. Operates like
|
||||
## the "-W" option of the ping command.
|
||||
# timeout = 1.0
|
||||
|
||||
## If set, the total ping deadline, in seconds. Operates like the -w option
|
||||
## of the ping command.
|
||||
# deadline = 10
|
||||
|
||||
## Interface or source address to send ping from. Operates like the -I or -S
|
||||
## option of the ping command.
|
||||
# interface = ""
|
||||
|
||||
## Specify the ping executable binary.
|
||||
# binary = "ping"
|
||||
|
||||
## Arguments for ping command. When arguments is not empty, system binary will be used and
|
||||
## other options (ping_interval, timeout, etc) will be ignored
|
||||
## Arguments for ping command. When arguments is not empty, the command from
|
||||
## the binary option will be used and other options (ping_interval, timeout,
|
||||
## etc) will be ignored.
|
||||
# arguments = ["-c", "3"]
|
||||
|
||||
## Use only ipv6 addresses when resolving hostnames.
|
||||
## Use only IPv6 addresses when resolving a hostname.
|
||||
# ipv6 = false
|
||||
```
|
||||
|
||||
#### File Limit
|
||||
|
||||
Since this plugin runs the ping command, it may need to open several files per
|
||||
host. With a large host list you may receive a `too many open files` error.
|
||||
Since this plugin runs the ping command, it may need to open multiple files per
|
||||
host. The number of files used is lessened with the `native` option but still
|
||||
many files are used. With a large host list you may receive a `too many open
|
||||
files` error.
|
||||
|
||||
To increase this limit on platforms using systemd it must be done in the
|
||||
service file.
|
||||
To increase this limit on platforms using systemd the recommended method is to
|
||||
use the "drop-in directory", usually located at
|
||||
`/etc/systemd/system/telegraf.service.d`.
|
||||
|
||||
|
||||
Find the service unit file:
|
||||
```
|
||||
$ systemctl show telegraf.service -p FragmentPath
|
||||
FragmentPath=/lib/systemd/system/telegraf.service
|
||||
You can create or edit a drop-in file in the correct location using:
|
||||
```sh
|
||||
$ systemctl edit telegraf
|
||||
```
|
||||
|
||||
Set the file number limit:
|
||||
```
|
||||
Increase the number of open files:
|
||||
```ini
|
||||
[Service]
|
||||
LimitNOFILE=4096
|
||||
LimitNOFILE=8192
|
||||
```
|
||||
|
||||
#### Permission Caveat (non Windows)
|
||||
|
||||
It is preferred that this plugin listen on privileged ICMP sockets. To do so, telegraf can either be run as the root user or the root user can add the capability to access raw sockets to telegraf by running the following commant:
|
||||
|
||||
```
|
||||
setcap cap_net_raw=eip /path/to/telegraf
|
||||
Restart Telegraf:
|
||||
```sh
|
||||
$ systemctl edit telegraf
|
||||
```
|
||||
|
||||
Another option (doesn't work as well or in all circumstances) is to listen on unprivileged raw sockets (non-Windows only). The system group of the user running telegraf must be allowed to create ICMP Echo sockets. [See man pages icmp(7) for `ping_group_range`](http://man7.org/linux/man-pages/man7/icmp.7.html). On Linux hosts, run the following to give a group the proper permissions:
|
||||
#### Linux Permissions
|
||||
|
||||
When using `method = "native"`, Telegraf will attempt to use privileged raw
|
||||
ICMP sockets. On most systems, doing so requires `CAP_NET_RAW` capabilities.
|
||||
|
||||
With systemd:
|
||||
```sh
|
||||
$ systemctl edit telegraf
|
||||
```
|
||||
sudo sysctl -w net.ipv4.ping_group_range="GROUP_ID_LOW GROUP_ID_HIGH"
|
||||
```ini
|
||||
[Service]
|
||||
CapabilityBoundingSet=CAP_NET_RAW
|
||||
AmbientCapabilities=CAP_NET_RAW
|
||||
```
|
||||
```sh
|
||||
$ systemctl restart telegraf
|
||||
```
|
||||
|
||||
Without systemd:
|
||||
```sh
|
||||
$ setcap cap_net_raw=eip /usr/bin/telegraf
|
||||
```
|
||||
|
||||
### Metrics:
|
||||
Reference [`man 7 capabilities`][man 7 capabilities] for more information about
|
||||
setting capabilities.
|
||||
|
||||
[man 7 capabilities]: http://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||
|
||||
When Telegraf cannot listen on a privileged ICMP socket it will attempt to use
|
||||
ICMP echo sockets. If you wish to use this method you must ensure Telegraf's
|
||||
group, usually `telegraf`, is allowed to use ICMP echo sockets:
|
||||
|
||||
```sh
|
||||
$ sysctl -w net.ipv4.ping_group_range="GROUP_ID_LOW GROUP_ID_HIGH"
|
||||
```
|
||||
|
||||
Reference [`man 7 icmp`][man 7 icmp] for more information about ICMP echo
|
||||
sockets and the `ping_group_range` setting.
|
||||
|
||||
[man 7 icmp]: http://man7.org/linux/man-pages/man7/icmp.7.html
|
||||
|
||||
### Metrics
|
||||
|
||||
- ping
|
||||
- tags:
|
||||
@@ -102,24 +152,23 @@ sudo sysctl -w net.ipv4.ping_group_range="GROUP_ID_LOW GROUP_ID_HIGH"
|
||||
- maximum_response_ms (integer)
|
||||
- standard_deviation_ms (integer, Available on Windows only with native ping)
|
||||
- errors (float, Windows only)
|
||||
- reply_received (integer, Windows only*)
|
||||
- percent_reply_loss (float, Windows only*)
|
||||
- reply_received (integer, Windows with method = "exec" only)
|
||||
- percent_reply_loss (float, Windows with method = "exec" only)
|
||||
- result_code (int, success = 0, no such host = 1, ping error = 2)
|
||||
|
||||
##### reply_received vs packets_received
|
||||
|
||||
On Windows systems, "Destination net unreachable" reply will increment `packets_received` but not `reply_received`*
|
||||
On Windows systems with `method = "exec"`, the "Destination net unreachable" reply will increment `packets_received` but not `reply_received`*.
|
||||
|
||||
### Example Output:
|
||||
##### ttl
|
||||
|
||||
**Windows:**
|
||||
```
|
||||
ping,url=example.org result_code=0i,average_response_ms=7i,maximum_response_ms=9i,minimum_response_ms=7i,packets_received=4i,packets_transmitted=4i,percent_packet_loss=0,percent_reply_loss=0,reply_received=4i 1469879119000000000
|
||||
```
|
||||
There is currently no support for TTL on windows with `"native"`; track
|
||||
progress at https://github.com/golang/go/issues/7175 and
|
||||
https://github.com/golang/go/issues/7174
|
||||
|
||||
|
||||
### Example Output
|
||||
|
||||
**Linux:**
|
||||
```
|
||||
ping,url=example.org average_response_ms=23.066,ttl=63,maximum_response_ms=24.64,minimum_response_ms=22.451,packets_received=5i,packets_transmitted=5i,percent_packet_loss=0,result_code=0i,standard_deviation_ms=0.809 1535747258000000000
|
||||
```
|
||||
|
||||
*not when `method = "native"` is used
|
||||
|
||||
+34
-23
@@ -11,7 +11,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/glinton/ping"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
@@ -68,35 +67,47 @@ func (*Ping) Description() string {
|
||||
}
|
||||
|
||||
const sampleConfig = `
|
||||
## List of urls to ping
|
||||
## Hosts to send ping packets to.
|
||||
urls = ["example.org"]
|
||||
|
||||
## Number of pings to send per collection (ping -c <COUNT>)
|
||||
# count = 1
|
||||
|
||||
## Interval, in s, at which to ping. 0 == default (ping -i <PING_INTERVAL>)
|
||||
# ping_interval = 1.0
|
||||
|
||||
## Per-ping timeout, in s. 0 == no timeout (ping -W <TIMEOUT>)
|
||||
# timeout = 1.0
|
||||
|
||||
## Total-ping deadline, in s. 0 == no deadline (ping -w <DEADLINE>)
|
||||
# deadline = 10
|
||||
|
||||
## Interface or source address to send ping from (ping -I[-S] <INTERFACE/SRC_ADDR>)
|
||||
# interface = ""
|
||||
|
||||
## How to ping. "native" doesn't have external dependencies, while "exec" depends on 'ping'.
|
||||
## Method used for sending pings, can be either "exec" or "native". When set
|
||||
## to "exec" the systems ping command will be executed. When set to "native"
|
||||
## the plugin will send pings directly.
|
||||
##
|
||||
## While the default is "exec" for backwards compatibility, new deployments
|
||||
## are encouraged to use the "native" method for improved compatibility and
|
||||
## performance.
|
||||
# method = "exec"
|
||||
|
||||
## Specify the ping executable binary, default is "ping"
|
||||
# binary = "ping"
|
||||
## Number of ping packets to send per interval. Corresponds to the "-c"
|
||||
## option of the ping command.
|
||||
# count = 1
|
||||
|
||||
## Arguments for ping command. When arguments is not empty, system binary will be used and
|
||||
## other options (ping_interval, timeout, etc) will be ignored.
|
||||
## Time to wait between sending ping packets in seconds. Operates like the
|
||||
## "-i" option of the ping command.
|
||||
# ping_interval = 1.0
|
||||
|
||||
## If set, the time to wait for a ping response in seconds. Operates like
|
||||
## the "-W" option of the ping command.
|
||||
# timeout = 1.0
|
||||
|
||||
## If set, the total ping deadline, in seconds. Operates like the -w option
|
||||
## of the ping command.
|
||||
# deadline = 10
|
||||
|
||||
## Interface or source address to send ping from. Operates like the -I or -S
|
||||
## option of the ping command.
|
||||
# interface = ""
|
||||
|
||||
## Specify the ping executable binary.
|
||||
# binary = "ping"
|
||||
|
||||
## Arguments for ping command. When arguments is not empty, the command from
|
||||
## the binary option will be used and other options (ping_interval, timeout,
|
||||
## etc) will be ignored.
|
||||
# arguments = ["-c", "3"]
|
||||
|
||||
## Use only ipv6 addresses when resolving hostnames.
|
||||
## Use only IPv6 addresses when resolving a hostname.
|
||||
# ipv6 = false
|
||||
`
|
||||
|
||||
|
||||
@@ -4,11 +4,9 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
// register in driver.
|
||||
_ "github.com/jackc/pgx/stdlib"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
@@ -23,6 +21,8 @@ type Postgresql struct {
|
||||
AdditionalTags []string
|
||||
Query query
|
||||
Debug bool
|
||||
|
||||
Log telegraf.Logger
|
||||
}
|
||||
|
||||
type query []struct {
|
||||
@@ -186,7 +186,7 @@ func (p *Postgresql) Gather(acc telegraf.Accumulator) error {
|
||||
if p.Query[i].Version <= db_version {
|
||||
rows, err := p.DB.Query(sql_query)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
p.Log.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ func (p *Postgresql) Gather(acc telegraf.Accumulator) error {
|
||||
|
||||
// grab the column information from the result
|
||||
if columns, err = rows.Columns(); err != nil {
|
||||
acc.AddError(err)
|
||||
p.Log.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ func (p *Postgresql) Gather(acc telegraf.Accumulator) error {
|
||||
for rows.Next() {
|
||||
err = p.accRow(meas_name, rows, acc, columns)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
p.Log.Error(err.Error())
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -272,7 +272,7 @@ func (p *Postgresql) accRow(meas_name string, row scanner, acc telegraf.Accumula
|
||||
fields := make(map[string]interface{})
|
||||
COLUMN:
|
||||
for col, val := range columnMap {
|
||||
log.Printf("D! postgresql_extensible: column: %s = %T: %v\n", col, *val, *val)
|
||||
p.Log.Debugf("Column: %s = %T: %v\n", col, *val, *val)
|
||||
_, ignore := ignoredColumns[col]
|
||||
if ignore || *val == nil {
|
||||
continue
|
||||
@@ -290,7 +290,7 @@ COLUMN:
|
||||
case int64, int32, int:
|
||||
tags[col] = fmt.Sprintf("%d", v)
|
||||
default:
|
||||
log.Println("failed to add additional tag", col)
|
||||
p.Log.Debugf("Failed to add %q as additional tag", col)
|
||||
}
|
||||
continue COLUMN
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
func queryRunner(t *testing.T, q query) *testutil.Accumulator {
|
||||
p := &Postgresql{
|
||||
Log: testutil.Logger{},
|
||||
Service: postgresql.Service{
|
||||
Address: fmt.Sprintf(
|
||||
"host=%s user=postgres sslmode=disable",
|
||||
@@ -232,6 +233,7 @@ func TestPostgresqlIgnoresUnwantedColumns(t *testing.T) {
|
||||
}
|
||||
|
||||
p := &Postgresql{
|
||||
Log: testutil.Logger{},
|
||||
Service: postgresql.Service{
|
||||
Address: fmt.Sprintf(
|
||||
"host=%s user=postgres sslmode=disable",
|
||||
@@ -251,7 +253,10 @@ func TestPostgresqlIgnoresUnwantedColumns(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAccRow(t *testing.T) {
|
||||
p := Postgresql{}
|
||||
p := Postgresql{
|
||||
Log: testutil.Logger{},
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
columns := []string{"datname", "cat"}
|
||||
|
||||
|
||||
@@ -110,8 +110,8 @@ func parseResponse(metrics string) map[string]interface{} {
|
||||
|
||||
i, err := strconv.ParseInt(m[1], 10, 64)
|
||||
if err != nil {
|
||||
log.Printf("E! powerdns: Error parsing integer for metric [%s]: %s",
|
||||
metric, err)
|
||||
log.Printf("E! [inputs.powerdns] error parsing integer for metric %q: %s",
|
||||
metric, err.Error())
|
||||
continue
|
||||
}
|
||||
values[m[0]] = i
|
||||
|
||||
@@ -139,8 +139,8 @@ func parseResponse(metrics string) map[string]interface{} {
|
||||
|
||||
i, err := strconv.ParseInt(m[1], 10, 64)
|
||||
if err != nil {
|
||||
log.Printf("E! [inputs.powerdns_recursor] Error parsing integer for metric [%s] %v",
|
||||
metric, err)
|
||||
log.Printf("E! [inputs.powerdns_recursor] error parsing integer for metric %q: %s",
|
||||
metric, err.Error())
|
||||
continue
|
||||
}
|
||||
values[m[0]] = i
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -23,6 +22,8 @@ type Processes struct {
|
||||
execPS func() ([]byte, error)
|
||||
readProcFile func(filename string) ([]byte, error)
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
forcePS bool
|
||||
forceProc bool
|
||||
}
|
||||
@@ -124,8 +125,7 @@ func (p *Processes) gatherFromPS(fields map[string]interface{}) error {
|
||||
case '?':
|
||||
fields["unknown"] = fields["unknown"].(int64) + int64(1)
|
||||
default:
|
||||
log.Printf("I! processes: Unknown state [ %s ] from ps",
|
||||
string(status[0]))
|
||||
p.Log.Infof("Unknown state %q from ps", string(status[0]))
|
||||
}
|
||||
fields["total"] = fields["total"].(int64) + int64(1)
|
||||
}
|
||||
@@ -184,14 +184,13 @@ func (p *Processes) gatherFromProc(fields map[string]interface{}) error {
|
||||
}
|
||||
fields["parked"] = int64(1)
|
||||
default:
|
||||
log.Printf("I! processes: Unknown state [ %s ] in file %s",
|
||||
string(stats[0][0]), filename)
|
||||
p.Log.Infof("Unknown state %q in file %q", string(stats[0][0]), filename)
|
||||
}
|
||||
fields["total"] = fields["total"].(int64) + int64(1)
|
||||
|
||||
threads, err := strconv.Atoi(string(stats[17]))
|
||||
if err != nil {
|
||||
log.Printf("I! processes: Error parsing thread count: %s", err)
|
||||
p.Log.Infof("Error parsing thread count: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
fields["total_threads"] = fields["total_threads"].(int64) + int64(threads)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
func TestProcesses(t *testing.T) {
|
||||
processes := &Processes{
|
||||
Log: testutil.Logger{},
|
||||
execPS: execPS,
|
||||
readProcFile: readProcFile,
|
||||
}
|
||||
@@ -35,6 +36,7 @@ func TestProcesses(t *testing.T) {
|
||||
|
||||
func TestFromPS(t *testing.T) {
|
||||
processes := &Processes{
|
||||
Log: testutil.Logger{},
|
||||
execPS: testExecPS,
|
||||
forcePS: true,
|
||||
}
|
||||
@@ -56,6 +58,7 @@ func TestFromPS(t *testing.T) {
|
||||
|
||||
func TestFromPSError(t *testing.T) {
|
||||
processes := &Processes{
|
||||
Log: testutil.Logger{},
|
||||
execPS: testExecPSError,
|
||||
forcePS: true,
|
||||
}
|
||||
@@ -71,6 +74,7 @@ func TestFromProcFiles(t *testing.T) {
|
||||
}
|
||||
tester := tester{}
|
||||
processes := &Processes{
|
||||
Log: testutil.Logger{},
|
||||
readProcFile: tester.testProcFile,
|
||||
forceProc: true,
|
||||
}
|
||||
@@ -93,6 +97,7 @@ func TestFromProcFilesWithSpaceInCmd(t *testing.T) {
|
||||
}
|
||||
tester := tester{}
|
||||
processes := &Processes{
|
||||
Log: testutil.Logger{},
|
||||
readProcFile: tester.testProcFile2,
|
||||
forceProc: true,
|
||||
}
|
||||
@@ -120,6 +125,7 @@ func TestParkedProcess(t *testing.T) {
|
||||
procstat := `88 (watchdog/13) P 2 0 0 0 -1 69238848 0 0 0 0 0 0 0 0 20 0 1 0 20 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 1 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
`
|
||||
plugin := &Processes{
|
||||
Log: testutil.Logger{},
|
||||
readProcFile: func(string) ([]byte, error) {
|
||||
return []byte(procstat), nil
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user