Generic SQL input (#8735)
This commit is contained in:
parent
905b22cac9
commit
908ad2f6ce
|
|
@ -324,6 +324,7 @@ For documentation on the latest development code see the [documentation index][d
|
|||
* [snmp_trap](./plugins/inputs/snmp_trap)
|
||||
* [socket_listener](./plugins/inputs/socket_listener)
|
||||
* [solr](./plugins/inputs/solr)
|
||||
* [sql](./plugins/inputs/sql) (generic SQL query plugin)
|
||||
* [sql server](./plugins/inputs/sqlserver) (microsoft)
|
||||
* [stackdriver](./plugins/inputs/stackdriver) (Google Cloud Monitoring)
|
||||
* [sql](./plugins/outputs/sql) (SQL generic output)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
# Available SQL drivers for the SQL input plugin
|
||||
|
||||
This is a list of available drivers for the SQL input plugin. The data-source-name (DSN) is driver specific and
|
||||
might change between versions. Please check the driver documentation for available options and the format.
|
||||
|
||||
database | driver | aliases | example DSN | comment
|
||||
---------------------| ------------------------------------------------------| --------------- | -------------------------------------------------------------------------------------- | -------
|
||||
CockroachDB | [cockroach](https://github.com/jackc/pgx) | postgres<br>pgx | see _postgres_ driver | uses PostgresQL driver
|
||||
MariaDB | [maria](https://github.com/go-sql-driver/mysql) | mysql | see _mysql_ driver | uses MySQL driver
|
||||
Microsoft SQL Server | [sqlserver](https://github.com/denisenkom/go-mssqldb) | mssql | `username:password@host/instance?param1=value¶m2=value` | uses newer _sqlserver_ driver
|
||||
MySQL | [mysql](https://github.com/go-sql-driver/mysql) | | `[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]` | see [driver docs](https://github.com/go-sql-driver/mysql) for more information
|
||||
PostgreSQL | [postgres](https://github.com/jackc/pgx) | pgx | `[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]` | see [postgres docs](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING) for more information
|
||||
SQLite | [sqlite](https://gitlab.com/cznic/sqlite) | | `filename` | see [driver docu](https://pkg.go.dev/modernc.org/sqlite) for more information
|
||||
TiDB | [tidb](https://github.com/go-sql-driver/mysql) | mysql | see _mysql_ driver | uses MySQL driver
|
||||
|
||||
## Comments
|
||||
|
||||
### Driver aliases
|
||||
Some database drivers are supported though another driver (e.g. CockroachDB). For other databases we provide a more
|
||||
obvious name (e.g. postgres) compared to the driver name. For all of those drivers you might use an _alias_ name
|
||||
during configuration.
|
||||
|
||||
### Example data-source-name DSN
|
||||
The given examples are just that, so please check the driver documentation for the exact format
|
||||
and available options and parameters. Please note that the format of a DSN might also change
|
||||
between driver version.
|
||||
|
||||
### Type conversions
|
||||
Telegraf relies on type conversion of the database driver and/or the golang sql framework. In case you find
|
||||
any problem, please open an issue!
|
||||
|
||||
## Help
|
||||
If nothing seems to work, you might find help in the telegraf forum or in the chat.
|
||||
|
||||
### The documentation is wrong
|
||||
Please open an issue or even better send a pull-request!
|
||||
|
||||
### I found a bug
|
||||
Please open an issue or even better send a pull-request!
|
||||
|
||||
### My database is not supported
|
||||
We currently cannot support CGO drivers in telegraf! Please check if a **pure Go** driver for the [golang sql framework](https://golang.org/pkg/database/sql/) exists.
|
||||
If you found such a driver, please let us know by opening an issue or even better by sending a pull-request!
|
||||
|
|
@ -79,13 +79,24 @@ func compileFilterNoGlob(filters []string) Filter {
|
|||
}
|
||||
|
||||
type IncludeExcludeFilter struct {
|
||||
include Filter
|
||||
exclude Filter
|
||||
include Filter
|
||||
exclude Filter
|
||||
includeDefault bool
|
||||
excludeDefault bool
|
||||
}
|
||||
|
||||
func NewIncludeExcludeFilter(
|
||||
include []string,
|
||||
exclude []string,
|
||||
) (Filter, error) {
|
||||
return NewIncludeExcludeFilterDefaults(include, exclude, true, false)
|
||||
}
|
||||
|
||||
func NewIncludeExcludeFilterDefaults(
|
||||
include []string,
|
||||
exclude []string,
|
||||
includeDefault bool,
|
||||
excludeDefault bool,
|
||||
) (Filter, error) {
|
||||
in, err := Compile(include)
|
||||
if err != nil {
|
||||
|
|
@ -97,7 +108,7 @@ func NewIncludeExcludeFilter(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &IncludeExcludeFilter{in, ex}, nil
|
||||
return &IncludeExcludeFilter{in, ex, includeDefault, excludeDefault}, nil
|
||||
}
|
||||
|
||||
func (f *IncludeExcludeFilter) Match(s string) bool {
|
||||
|
|
@ -105,12 +116,17 @@ func (f *IncludeExcludeFilter) Match(s string) bool {
|
|||
if !f.include.Match(s) {
|
||||
return false
|
||||
}
|
||||
} else if !f.includeDefault {
|
||||
return false
|
||||
}
|
||||
|
||||
if f.exclude != nil {
|
||||
if f.exclude.Match(s) {
|
||||
return false
|
||||
}
|
||||
} else if f.excludeDefault {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
70
go.sum
70
go.sum
|
|
@ -110,23 +110,39 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go
|
|||
github.com/Mellanox/rdmamap v0.0.0-20191106181932-7c3c4763a6ee h1:atI/FFjXh6hIVlPE1Jup9m8N4B9q/OSbMUe2EBahs+w=
|
||||
github.com/Mellanox/rdmamap v0.0.0-20191106181932-7c3c4763a6ee/go.mod h1:jDA6v0TUYrFEIAE5uGJ29LQOeONIgMdP4Rkqb8HUnPM=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI=
|
||||
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI=
|
||||
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
||||
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
|
||||
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
|
||||
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
|
||||
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
||||
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||
github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac=
|
||||
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
|
|
@ -246,8 +262,11 @@ github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR
|
|||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
|
|
@ -257,6 +276,8 @@ github.com/caio/go-tdigest v3.1.0+incompatible h1:uoVMJ3Q5lXmVLCCqaMGHLBWnbGoN6L
|
|||
github.com/caio/go-tdigest v3.1.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
|
|
@ -287,12 +308,14 @@ github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABA
|
|||
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
||||
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
|
||||
github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E=
|
||||
github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E=
|
||||
github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
|
||||
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
||||
github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
||||
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
||||
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
||||
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68 h1:hkGVFjz+plgr5UfxZUTPFbUFIF/Km6/s+RVRIRHLrrY=
|
||||
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
|
||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||
|
|
@ -309,14 +332,17 @@ github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.
|
|||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
|
||||
github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
|
||||
github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
|
||||
github.com/containerd/containerd v1.5.0-beta.4 h1:zjz4MOAOFgdBlwid2nNUlJ3YLpVi/97L36lfMYJex60=
|
||||
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
|
||||
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
|
||||
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e h1:6JKvHHt396/qabvMhnhUZvWaHZzfVfldxE60TK8YLhg=
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
||||
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
|
|
@ -330,9 +356,11 @@ github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH
|
|||
github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
|
||||
github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||
github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0=
|
||||
github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0=
|
||||
github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA=
|
||||
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
|
||||
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
||||
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
||||
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
|
|
@ -405,16 +433,23 @@ github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/
|
|||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200706150819-a40b877fbb9e+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v20.10.6+incompatible h1:oXI3Vas8TI8Eu/EjH4srKHJBVqraSzJybhxY7Om9faQ=
|
||||
github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
|
|
@ -427,6 +462,7 @@ github.com/dropbox/godropbox v0.0.0-20180512210157-31879d3884b9/go.mod h1:glr97h
|
|||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dynatrace-oss/dynatrace-metric-utils-go v0.1.0 h1:ldKn47mFgWCoiJRXA32psdEACPKffX9O1Msh1K8M+f0=
|
||||
github.com/dynatrace-oss/dynatrace-metric-utils-go v0.1.0/go.mod h1:qw0E9EJ0PnSlhWawDNuqE0zhc1hqOBUCFIAj3dd9DNw=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
|
|
@ -614,6 +650,7 @@ github.com/gogo/googleapis v1.3.1/go.mod h1:d+q1s/xVJxZGKWwC/6UfPIF33J+G1Tq4GYv9
|
|||
github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI=
|
||||
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
|
|
@ -885,6 +922,7 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
|
|||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
|
|
@ -1045,11 +1083,16 @@ github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hx
|
|||
github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ=
|
||||
github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ=
|
||||
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
|
||||
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
|
||||
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
|
||||
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
|
||||
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM=
|
||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
|
||||
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
|
||||
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
|
||||
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
|
|
@ -1107,6 +1150,7 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
|||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
|
@ -1131,17 +1175,30 @@ github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVo
|
|||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM=
|
||||
github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM=
|
||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
|
|
@ -1230,6 +1287,7 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
|
|||
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/prometheus v1.8.2-0.20200911110723-e83ef207b6c2 h1:IB/5RJRcJiR/YzKs4Aou86s/RaMepZOZVCArYNHJHWc=
|
||||
|
|
@ -1296,6 +1354,7 @@ github.com/signalfx/sapm-proto v0.4.0/go.mod h1:x3gtwJ1GRejtkghB4nYpwixh2zqJrLbP
|
|||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
|
@ -1307,6 +1366,8 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf
|
|||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
|
|
@ -1330,6 +1391,7 @@ github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bd
|
|||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
|
|
@ -1586,6 +1648,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
|
@ -1650,6 +1713,8 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -1678,6 +1743,7 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200821140526-fda516888d29/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200821140526-fda516888d29/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -1689,11 +1755,15 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
|
|||
|
|
@ -297,8 +297,25 @@ func parseComponents(timestamp interface{}) (int64, int64, error) {
|
|||
return 0, 0, err
|
||||
}
|
||||
return integer, 0, nil
|
||||
case int8:
|
||||
return int64(ts), 0, nil
|
||||
case int16:
|
||||
return int64(ts), 0, nil
|
||||
case int32:
|
||||
return int64(ts), 0, nil
|
||||
case int64:
|
||||
return ts, 0, nil
|
||||
case uint8:
|
||||
return int64(ts), 0, nil
|
||||
case uint16:
|
||||
return int64(ts), 0, nil
|
||||
case uint32:
|
||||
return int64(ts), 0, nil
|
||||
case uint64:
|
||||
return int64(ts), 0, nil
|
||||
case float32:
|
||||
integer, fractional := math.Modf(float64(ts))
|
||||
return int64(integer), int64(fractional * 1e9), nil
|
||||
case float64:
|
||||
integer, fractional := math.Modf(ts)
|
||||
return int64(integer), int64(fractional * 1e9), nil
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ToString(value interface{}) (string, error) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return v, nil
|
||||
case []byte:
|
||||
return string(v), nil
|
||||
case int:
|
||||
return strconv.FormatInt(int64(v), 10), nil
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(v), 10), nil
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(v), 10), nil
|
||||
case int32:
|
||||
return strconv.FormatInt(int64(v), 10), nil
|
||||
case int64:
|
||||
return strconv.FormatInt(v, 10), nil
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(v), 10), nil
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(v), 10), nil
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(v), 10), nil
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(v), 10), nil
|
||||
case uint64:
|
||||
return strconv.FormatUint(v, 10), nil
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(v), 'f', -1, 32), nil
|
||||
case float64:
|
||||
return strconv.FormatFloat(v, 'f', -1, 64), nil
|
||||
case bool:
|
||||
return strconv.FormatBool(v), nil
|
||||
case fmt.Stringer:
|
||||
return v.String(), nil
|
||||
case nil:
|
||||
return "", nil
|
||||
}
|
||||
return "", fmt.Errorf("type \"%T\" unsupported", value)
|
||||
}
|
||||
|
||||
func ToFloat64(value interface{}) (float64, error) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return strconv.ParseFloat(v, 64)
|
||||
case []byte:
|
||||
return strconv.ParseFloat(string(v), 64)
|
||||
case fmt.Stringer:
|
||||
return strconv.ParseFloat(v.String(), 64)
|
||||
case int:
|
||||
return float64(v), nil
|
||||
case int8:
|
||||
return float64(v), nil
|
||||
case int16:
|
||||
return float64(v), nil
|
||||
case int32:
|
||||
return float64(v), nil
|
||||
case int64:
|
||||
return float64(v), nil
|
||||
case uint:
|
||||
return float64(v), nil
|
||||
case uint8:
|
||||
return float64(v), nil
|
||||
case uint16:
|
||||
return float64(v), nil
|
||||
case uint32:
|
||||
return float64(v), nil
|
||||
case uint64:
|
||||
return float64(v), nil
|
||||
case float32:
|
||||
return float64(v), nil
|
||||
case float64:
|
||||
return v, nil
|
||||
case nil:
|
||||
return 0, nil
|
||||
}
|
||||
return 0, fmt.Errorf("type \"%T\" unsupported", value)
|
||||
}
|
||||
|
||||
func ToInt64(value interface{}) (int64, error) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return strconv.ParseInt(v, 10, 64)
|
||||
case []byte:
|
||||
return strconv.ParseInt(string(v), 10, 64)
|
||||
case fmt.Stringer:
|
||||
return strconv.ParseInt(v.String(), 10, 64)
|
||||
case int:
|
||||
return int64(v), nil
|
||||
case int8:
|
||||
return int64(v), nil
|
||||
case int16:
|
||||
return int64(v), nil
|
||||
case int32:
|
||||
return int64(v), nil
|
||||
case int64:
|
||||
return v, nil
|
||||
case uint:
|
||||
return int64(v), nil
|
||||
case uint8:
|
||||
return int64(v), nil
|
||||
case uint16:
|
||||
return int64(v), nil
|
||||
case uint32:
|
||||
return int64(v), nil
|
||||
case uint64:
|
||||
return int64(v), nil
|
||||
case float32:
|
||||
return int64(v), nil
|
||||
case float64:
|
||||
return int64(v), nil
|
||||
case nil:
|
||||
return 0, nil
|
||||
}
|
||||
return 0, fmt.Errorf("type \"%T\" unsupported", value)
|
||||
}
|
||||
|
||||
func ToUint64(value interface{}) (uint64, error) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return strconv.ParseUint(v, 10, 64)
|
||||
case []byte:
|
||||
return strconv.ParseUint(string(v), 10, 64)
|
||||
case fmt.Stringer:
|
||||
return strconv.ParseUint(v.String(), 10, 64)
|
||||
case int:
|
||||
return uint64(v), nil
|
||||
case int8:
|
||||
return uint64(v), nil
|
||||
case int16:
|
||||
return uint64(v), nil
|
||||
case int32:
|
||||
return uint64(v), nil
|
||||
case int64:
|
||||
return uint64(v), nil
|
||||
case uint:
|
||||
return uint64(v), nil
|
||||
case uint8:
|
||||
return uint64(v), nil
|
||||
case uint16:
|
||||
return uint64(v), nil
|
||||
case uint32:
|
||||
return uint64(v), nil
|
||||
case uint64:
|
||||
return v, nil
|
||||
case float32:
|
||||
return uint64(v), nil
|
||||
case float64:
|
||||
return uint64(v), nil
|
||||
case nil:
|
||||
return 0, nil
|
||||
}
|
||||
return 0, fmt.Errorf("type \"%T\" unsupported", value)
|
||||
}
|
||||
|
||||
func ToBool(value interface{}) (bool, error) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return strconv.ParseBool(v)
|
||||
case []byte:
|
||||
return strconv.ParseBool(string(v))
|
||||
case fmt.Stringer:
|
||||
return strconv.ParseBool(v.String())
|
||||
case int:
|
||||
return v > 0, nil
|
||||
case int8:
|
||||
return v > 0, nil
|
||||
case int16:
|
||||
return v > 0, nil
|
||||
case int32:
|
||||
return v > 0, nil
|
||||
case int64:
|
||||
return v > 0, nil
|
||||
case uint:
|
||||
return v > 0, nil
|
||||
case uint8:
|
||||
return v > 0, nil
|
||||
case uint16:
|
||||
return v > 0, nil
|
||||
case uint32:
|
||||
return v > 0, nil
|
||||
case uint64:
|
||||
return v > 0, nil
|
||||
case float32:
|
||||
return v > 0, nil
|
||||
case float64:
|
||||
return v > 0, nil
|
||||
case nil:
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("type \"%T\" unsupported", value)
|
||||
}
|
||||
|
|
@ -167,6 +167,7 @@ import (
|
|||
_ "github.com/influxdata/telegraf/plugins/inputs/snmp_trap"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/socket_listener"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/solr"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/sql"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/sqlserver"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/stackdriver"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/statsd"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
# SQL Input Plugin
|
||||
|
||||
This plugin reads metrics from performing SQL queries against a SQL server. Different server
|
||||
types are supported and their settings might differ (especially the connection parameters).
|
||||
Please check the list of [supported SQL drivers](../../../docs/SQL_DRIVERS_INPUT.md) for the
|
||||
`driver` name and options for the data-source-name (`dsn`) options.
|
||||
|
||||
### Configuration
|
||||
|
||||
This section contains the default TOML to configure the plugin. You can
|
||||
generate it using `telegraf --usage <plugin-name>`.
|
||||
|
||||
```toml
|
||||
[[inputs.sql]]
|
||||
## Database Driver
|
||||
## See https://github.com/influxdata/telegraf/blob/master/docs/SQL_DRIVERS_INPUT.md for
|
||||
## a list of supported drivers.
|
||||
driver = "mysql"
|
||||
|
||||
## Data source name for connecting
|
||||
## The syntax and supported options depends on selected driver.
|
||||
dsn = "username:password@mysqlserver:3307/dbname?param=value"
|
||||
|
||||
## Timeout for any operation
|
||||
# timeout = "5s"
|
||||
|
||||
## Connection time limits
|
||||
## By default the maximum idle time and maximum lifetime of a connection is unlimited, i.e. the connections
|
||||
## will not be closed automatically. If you specify a positive time, the connections will be closed after
|
||||
## idleing or existing for at least that amount of time, respectively.
|
||||
# connection_max_idle_time = "0s"
|
||||
# connection_max_life_time = "0s"
|
||||
|
||||
## Connection count limits
|
||||
## By default the number of open connections is not limited and the number of maximum idle connections
|
||||
## will be inferred from the number of queries specified. If you specify a positive number for any of the
|
||||
## two options, connections will be closed when reaching the specified limit. The number of idle connections
|
||||
## will be clipped to the maximum number of connections limit if any.
|
||||
# connection_max_open = 0
|
||||
# connection_max_idle = auto
|
||||
|
||||
[[inputs.sql.query]]
|
||||
## Query to perform on the server
|
||||
query="SELECT user,state,latency,score FROM Scoreboard WHERE application > 0"
|
||||
## Alternatively to specifying the query directly you can select a file here containing the SQL query.
|
||||
## Only one of 'query' and 'query_script' can be specified!
|
||||
# query_script = "/path/to/sql/script.sql"
|
||||
|
||||
## Name of the measurement
|
||||
## In case both measurement and 'measurement_col' are given, the latter takes precedence.
|
||||
# measurement = "sql"
|
||||
|
||||
## Column name containing the name of the measurement
|
||||
## If given, this will take precedence over the 'measurement' setting. In case a query result
|
||||
## does not contain the specified column, we fall-back to the 'measurement' setting.
|
||||
# measurement_column = ""
|
||||
|
||||
## Column name containing the time of the measurement
|
||||
## If ommited, the time of the query will be used.
|
||||
# time_column = ""
|
||||
|
||||
## Format of the time contained in 'time_col'
|
||||
## The time must be 'unix', 'unix_ms', 'unix_us', 'unix_ns', or a golang time format.
|
||||
## See https://golang.org/pkg/time/#Time.Format for details.
|
||||
# time_format = "unix"
|
||||
|
||||
## Column names containing tags
|
||||
## An empty include list will reject all columns and an empty exclude list will not exclude any column.
|
||||
## I.e. by default no columns will be returned as tag and the tags are empty.
|
||||
# tag_columns_include = []
|
||||
# tag_columns_exclude = []
|
||||
|
||||
## Column names containing fields (explicit types)
|
||||
## Convert the given columns to the corresponding type. Explicit type conversions take precedence over
|
||||
## the automatic (driver-based) conversion below.
|
||||
## NOTE: Columns should not be specified for multiple types or the resulting type is undefined.
|
||||
# field_columns_float = []
|
||||
# field_columns_int = []
|
||||
# field_columns_uint = []
|
||||
# field_columns_bool = []
|
||||
# field_columns_string = []
|
||||
|
||||
## Column names containing fields (automatic types)
|
||||
## An empty include list is equivalent to '[*]' and all returned columns will be accepted. An empty
|
||||
## exclude list will not exclude any column. I.e. by default all columns will be returned as fields.
|
||||
## NOTE: We rely on the database driver to perform automatic datatype conversion.
|
||||
# field_columns_include = []
|
||||
# field_columns_exclude = []
|
||||
```
|
||||
|
||||
### Options
|
||||
#### Driver
|
||||
The `driver` and `dsn` options specify how to connect to the database. As especially the `dsn` format and
|
||||
values vary with the `driver` refer to the list of [supported SQL drivers](../../../docs/SQL_DRIVERS_INPUT.md) for possible values and more details.
|
||||
|
||||
#### Connection limits
|
||||
With these options you can limit the number of connections kept open by this plugin. Details about the exact
|
||||
workings can be found in the [golang sql documentation](https://golang.org/pkg/database/sql/#DB.SetConnMaxIdleTime).
|
||||
|
||||
#### Query sections
|
||||
Multiple `query` sections can be specified for this plugin. Each specified query will first be prepared on the server
|
||||
and then executed in every interval using the column mappings specified. Please note that `tag` and `field` columns
|
||||
are not exclusive, i.e. a column can be added to both. When using both `include` and `exclude` lists, the `exclude`
|
||||
list takes precedence over the `include` list. I.e. given you specify `foo` in both lists, `foo` will _never_ pass
|
||||
the filter. In case any the columns specified in `measurement_col` or `time_col` are _not_ returned by the query,
|
||||
the plugin falls-back to the documented defaults. Fields or tags specified in the includes of the options but missing
|
||||
in the returned query are silently ignored.
|
||||
|
||||
### Types
|
||||
This plugin relies on the driver to do the type conversion. For the different properties of the metric the following
|
||||
types are accepted.
|
||||
|
||||
#### Measurement
|
||||
Only columns of type `string` are accepted.
|
||||
|
||||
#### Time
|
||||
For the metric time columns of type `time` are accepted directly. For numeric columns, `time_format` should be set
|
||||
to any of `unix`, `unix_ms`, `unix_ns` or `unix_us` accordingly. By default the a timestamp in `unix` format is
|
||||
expected. For string columns, please specify the `time_format` accordingly.
|
||||
See the [golang time documentation](https://golang.org/pkg/time/#Time.Format) for details.
|
||||
|
||||
#### Tags
|
||||
For tags columns with textual values (`string` and `bytes`), signed and unsigned integers (8, 16, 32 and 64 bit),
|
||||
floating-point (32 and 64 bit), `boolean` and `time` values are accepted. Those values will be converted to string.
|
||||
|
||||
#### Fields
|
||||
For fields columns with textual values (`string` and `bytes`), signed and unsigned integers (8, 16, 32 and 64 bit),
|
||||
floating-point (32 and 64 bit), `boolean` and `time` values are accepted. Here `bytes` will be converted to `string`,
|
||||
signed and unsigned integer values will be converted to `int64` or `uint64` respectively. Floating-point values are converted to `float64` and `time` is converted to a nanosecond timestamp of type `int64`.
|
||||
|
||||
### Example Output
|
||||
Using the [MariaDB sample database](https://www.mariadbtutorial.com/getting-started/mariadb-sample-database) and the
|
||||
configuration
|
||||
```toml
|
||||
[[inputs.sql]]
|
||||
driver = "mysql"
|
||||
dsn = "root:password@/nation"
|
||||
|
||||
[[inputs.sql.query]]
|
||||
query="SELECT * FROM guests"
|
||||
measurement = "nation"
|
||||
tag_cols_include = ["name"]
|
||||
field_cols_exclude = ["name"]
|
||||
```
|
||||
|
||||
Telegraf will output the following metrics
|
||||
```
|
||||
nation,host=Hugin,name=John guest_id=1i 1611332164000000000
|
||||
nation,host=Hugin,name=Jane guest_id=2i 1611332164000000000
|
||||
nation,host=Hugin,name=Jean guest_id=3i 1611332164000000000
|
||||
nation,host=Hugin,name=Storm guest_id=4i 1611332164000000000
|
||||
nation,host=Hugin,name=Beast guest_id=5i 1611332164000000000
|
||||
```
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
// Blank imports to register the drivers
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/jackc/pgx/v4/stdlib"
|
||||
)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// +build linux,freebsd
|
||||
// +build !mips !mips64
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
|
@ -0,0 +1,542 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
dbsql "database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/filter"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/choice"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
const sampleConfig = `
|
||||
## Database Driver
|
||||
## See https://github.com/influxdata/telegraf/blob/master/docs/SQL_DRIVERS_INPUT.md for
|
||||
## a list of supported drivers.
|
||||
driver = "mysql"
|
||||
|
||||
## Data source name for connecting
|
||||
## The syntax and supported options depends on selected driver.
|
||||
dsn = "username:password@mysqlserver:3307/dbname?param=value"
|
||||
|
||||
## Timeout for any operation
|
||||
# timeout = "5s"
|
||||
|
||||
## Connection time limits
|
||||
## By default the maximum idle time and maximum lifetime of a connection is unlimited, i.e. the connections
|
||||
## will not be closed automatically. If you specify a positive time, the connections will be closed after
|
||||
## idleing or existing for at least that amount of time, respectively.
|
||||
# connection_max_idle_time = "0s"
|
||||
# connection_max_life_time = "0s"
|
||||
|
||||
## Connection count limits
|
||||
## By default the number of open connections is not limited and the number of maximum idle connections
|
||||
## will be inferred from the number of queries specified. If you specify a positive number for any of the
|
||||
## two options, connections will be closed when reaching the specified limit. The number of idle connections
|
||||
## will be clipped to the maximum number of connections limit if any.
|
||||
# connection_max_open = 0
|
||||
# connection_max_idle = auto
|
||||
|
||||
[[inputs.sql.query]]
|
||||
## Query to perform on the server
|
||||
query="SELECT user,state,latency,score FROM Scoreboard WHERE application > 0"
|
||||
## Alternatively to specifying the query directly you can select a file here containing the SQL query.
|
||||
## Only one of 'query' and 'query_script' can be specified!
|
||||
# query_script = "/path/to/sql/script.sql"
|
||||
|
||||
## Name of the measurement
|
||||
## In case both measurement and 'measurement_col' are given, the latter takes precedence.
|
||||
# measurement = "sql"
|
||||
|
||||
## Column name containing the name of the measurement
|
||||
## If given, this will take precedence over the 'measurement' setting. In case a query result
|
||||
## does not contain the specified column, we fall-back to the 'measurement' setting.
|
||||
# measurement_column = ""
|
||||
|
||||
## Column name containing the time of the measurement
|
||||
## If ommited, the time of the query will be used.
|
||||
# time_column = ""
|
||||
|
||||
## Format of the time contained in 'time_col'
|
||||
## The time must be 'unix', 'unix_ms', 'unix_us', 'unix_ns', or a golang time format.
|
||||
## See https://golang.org/pkg/time/#Time.Format for details.
|
||||
# time_format = "unix"
|
||||
|
||||
## Column names containing tags
|
||||
## An empty include list will reject all columns and an empty exclude list will not exclude any column.
|
||||
## I.e. by default no columns will be returned as tag and the tags are empty.
|
||||
# tag_columns_include = []
|
||||
# tag_columns_exclude = []
|
||||
|
||||
## Column names containing fields (explicit types)
|
||||
## Convert the given columns to the corresponding type. Explicit type conversions take precedence over
|
||||
## the automatic (driver-based) conversion below.
|
||||
## NOTE: Columns should not be specified for multiple types or the resulting type is undefined.
|
||||
# field_columns_float = []
|
||||
# field_columns_int = []
|
||||
# field_columns_uint = []
|
||||
# field_columns_bool = []
|
||||
# field_columns_string = []
|
||||
|
||||
## Column names containing fields (automatic types)
|
||||
## An empty include list is equivalent to '[*]' and all returned columns will be accepted. An empty
|
||||
## exclude list will not exclude any column. I.e. by default all columns will be returned as fields.
|
||||
## NOTE: We rely on the database driver to perform automatic datatype conversion.
|
||||
# field_columns_include = []
|
||||
# field_columns_exclude = []
|
||||
`
|
||||
|
||||
const magicIdleCount int = (-int(^uint(0) >> 1))
|
||||
|
||||
type Query struct {
|
||||
Query string `toml:"query"`
|
||||
Script string `toml:"query_script"`
|
||||
Measurement string `toml:"measurement"`
|
||||
MeasurementColumn string `toml:"measurement_column"`
|
||||
TimeColumn string `toml:"time_column"`
|
||||
TimeFormat string `toml:"time_format"`
|
||||
TagColumnsInclude []string `toml:"tag_columns_include"`
|
||||
TagColumnsExclude []string `toml:"tag_columns_exclude"`
|
||||
FieldColumnsInclude []string `toml:"field_columns_include"`
|
||||
FieldColumnsExclude []string `toml:"field_columns_exclude"`
|
||||
FieldColumnsFloat []string `toml:"field_columns_float"`
|
||||
FieldColumnsInt []string `toml:"field_columns_int"`
|
||||
FieldColumnsUint []string `toml:"field_columns_uint"`
|
||||
FieldColumnsBool []string `toml:"field_columns_bool"`
|
||||
FieldColumnsString []string `toml:"field_columns_string"`
|
||||
|
||||
statement *dbsql.Stmt
|
||||
tagFilter filter.Filter
|
||||
fieldFilter filter.Filter
|
||||
fieldFilterFloat filter.Filter
|
||||
fieldFilterInt filter.Filter
|
||||
fieldFilterUint filter.Filter
|
||||
fieldFilterBool filter.Filter
|
||||
fieldFilterString filter.Filter
|
||||
}
|
||||
|
||||
func (q *Query) parse(ctx context.Context, acc telegraf.Accumulator, rows *dbsql.Rows, t time.Time) (int, error) {
|
||||
columnNames, err := rows.Columns()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Prepare the list of datapoints according to the received row
|
||||
columnData := make([]interface{}, len(columnNames))
|
||||
columnDataPtr := make([]interface{}, len(columnNames))
|
||||
|
||||
for i := range columnData {
|
||||
columnDataPtr[i] = &columnData[i]
|
||||
}
|
||||
|
||||
rowCount := 0
|
||||
for rows.Next() {
|
||||
measurement := q.Measurement
|
||||
timestamp := t
|
||||
tags := make(map[string]string)
|
||||
fields := make(map[string]interface{}, len(columnNames))
|
||||
|
||||
// Do the parsing with (hopefully) automatic type conversion
|
||||
if err := rows.Scan(columnDataPtr...); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for i, name := range columnNames {
|
||||
if q.MeasurementColumn != "" && name == q.MeasurementColumn {
|
||||
var ok bool
|
||||
if measurement, ok = columnData[i].(string); !ok {
|
||||
return 0, fmt.Errorf("measurement column type \"%T\" unsupported", columnData[i])
|
||||
}
|
||||
}
|
||||
|
||||
if q.TimeColumn != "" && name == q.TimeColumn {
|
||||
var fieldvalue interface{}
|
||||
var skipParsing bool
|
||||
|
||||
switch v := columnData[i].(type) {
|
||||
case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
|
||||
fieldvalue = v
|
||||
case []byte:
|
||||
fieldvalue = string(v)
|
||||
case time.Time:
|
||||
timestamp = v
|
||||
skipParsing = true
|
||||
case fmt.Stringer:
|
||||
fieldvalue = v.String()
|
||||
default:
|
||||
return 0, fmt.Errorf("time column %q of type \"%T\" unsupported", name, columnData[i])
|
||||
}
|
||||
if !skipParsing {
|
||||
if timestamp, err = internal.ParseTimestamp(q.TimeFormat, fieldvalue, ""); err != nil {
|
||||
return 0, fmt.Errorf("parsing time failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if q.tagFilter.Match(name) {
|
||||
tagvalue, err := internal.ToString(columnData[i])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("converting tag column %q failed: %v", name, err)
|
||||
}
|
||||
if v := strings.TrimSpace(tagvalue); v != "" {
|
||||
tags[name] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Explicit type conversions take precedence
|
||||
if q.fieldFilterFloat.Match(name) {
|
||||
v, err := internal.ToFloat64(columnData[i])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("converting field column %q to float failed: %v", name, err)
|
||||
}
|
||||
fields[name] = v
|
||||
continue
|
||||
}
|
||||
|
||||
if q.fieldFilterInt.Match(name) {
|
||||
v, err := internal.ToInt64(columnData[i])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("converting field column %q to int failed: %v", name, err)
|
||||
}
|
||||
fields[name] = v
|
||||
continue
|
||||
}
|
||||
|
||||
if q.fieldFilterUint.Match(name) {
|
||||
v, err := internal.ToUint64(columnData[i])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("converting field column %q to uint failed: %v", name, err)
|
||||
}
|
||||
fields[name] = v
|
||||
continue
|
||||
}
|
||||
|
||||
if q.fieldFilterBool.Match(name) {
|
||||
v, err := internal.ToBool(columnData[i])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("converting field column %q to bool failed: %v", name, err)
|
||||
}
|
||||
fields[name] = v
|
||||
continue
|
||||
}
|
||||
|
||||
if q.fieldFilterString.Match(name) {
|
||||
v, err := internal.ToString(columnData[i])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("converting field column %q to string failed: %v", name, err)
|
||||
}
|
||||
fields[name] = v
|
||||
continue
|
||||
}
|
||||
|
||||
// Try automatic conversion for all remaining fields
|
||||
if q.fieldFilter.Match(name) {
|
||||
var fieldvalue interface{}
|
||||
switch v := columnData[i].(type) {
|
||||
case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool:
|
||||
fieldvalue = v
|
||||
case []byte:
|
||||
fieldvalue = string(v)
|
||||
case time.Time:
|
||||
fieldvalue = v.UnixNano()
|
||||
case nil:
|
||||
fieldvalue = nil
|
||||
case fmt.Stringer:
|
||||
fieldvalue = v.String()
|
||||
default:
|
||||
return 0, fmt.Errorf("field column %q of type \"%T\" unsupported", name, columnData[i])
|
||||
}
|
||||
if fieldvalue != nil {
|
||||
fields[name] = fieldvalue
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.AddFields(measurement, fields, tags, timestamp)
|
||||
rowCount++
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return rowCount, err
|
||||
}
|
||||
|
||||
return rowCount, nil
|
||||
}
|
||||
|
||||
type SQL struct {
|
||||
Driver string `toml:"driver"`
|
||||
Dsn string `toml:"dsn"`
|
||||
Timeout config.Duration `toml:"timeout"`
|
||||
MaxIdleTime config.Duration `toml:"connection_max_idle_time"`
|
||||
MaxLifetime config.Duration `toml:"connection_max_life_time"`
|
||||
MaxOpenConnections int `toml:"connection_max_open"`
|
||||
MaxIdleConnections int `toml:"connection_max_idle"`
|
||||
Queries []Query `toml:"query"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
|
||||
driverName string
|
||||
db *dbsql.DB
|
||||
}
|
||||
|
||||
func (s *SQL) Description() string {
|
||||
return `Read metrics from SQL queries`
|
||||
}
|
||||
|
||||
func (s *SQL) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (s *SQL) Init() error {
|
||||
// Option handling
|
||||
if s.Driver == "" {
|
||||
return errors.New("missing SQL driver option")
|
||||
}
|
||||
|
||||
if s.Dsn == "" {
|
||||
return errors.New("missing data source name (DSN) option")
|
||||
}
|
||||
|
||||
if s.Timeout <= 0 {
|
||||
s.Timeout = config.Duration(5 * time.Second)
|
||||
}
|
||||
|
||||
if s.MaxIdleConnections == magicIdleCount {
|
||||
// Determine the number by the number of queries + the golang default value
|
||||
s.MaxIdleConnections = len(s.Queries) + 2
|
||||
}
|
||||
|
||||
for i, q := range s.Queries {
|
||||
if q.Query == "" && q.Script == "" {
|
||||
return errors.New("neither 'query' nor 'query_script' specified")
|
||||
}
|
||||
|
||||
if q.Query != "" && q.Script != "" {
|
||||
return errors.New("only one of 'query' and 'query_script' can be specified")
|
||||
}
|
||||
|
||||
// In case we got a script, we should read the query now.
|
||||
if q.Script != "" {
|
||||
query, err := ioutil.ReadFile(q.Script)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading script %q failed: %v", q.Script, err)
|
||||
}
|
||||
s.Queries[i].Query = string(query)
|
||||
}
|
||||
|
||||
// Time format
|
||||
if q.TimeFormat == "" {
|
||||
s.Queries[i].TimeFormat = "unix"
|
||||
}
|
||||
|
||||
// Compile the tag-filter
|
||||
tagfilter, err := filter.NewIncludeExcludeFilterDefaults(q.TagColumnsInclude, q.TagColumnsExclude, false, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating tag filter failed: %v", err)
|
||||
}
|
||||
s.Queries[i].tagFilter = tagfilter
|
||||
|
||||
// Compile the explicit type field-filter
|
||||
fieldfilterFloat, err := filter.NewIncludeExcludeFilterDefaults(q.FieldColumnsFloat, nil, false, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating field filter for float failed: %v", err)
|
||||
}
|
||||
s.Queries[i].fieldFilterFloat = fieldfilterFloat
|
||||
|
||||
fieldfilterInt, err := filter.NewIncludeExcludeFilterDefaults(q.FieldColumnsInt, nil, false, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating field filter for int failed: %v", err)
|
||||
}
|
||||
s.Queries[i].fieldFilterInt = fieldfilterInt
|
||||
|
||||
fieldfilterUint, err := filter.NewIncludeExcludeFilterDefaults(q.FieldColumnsUint, nil, false, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating field filter for uint failed: %v", err)
|
||||
}
|
||||
s.Queries[i].fieldFilterUint = fieldfilterUint
|
||||
|
||||
fieldfilterBool, err := filter.NewIncludeExcludeFilterDefaults(q.FieldColumnsBool, nil, false, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating field filter for bool failed: %v", err)
|
||||
}
|
||||
s.Queries[i].fieldFilterBool = fieldfilterBool
|
||||
|
||||
fieldfilterString, err := filter.NewIncludeExcludeFilterDefaults(q.FieldColumnsString, nil, false, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating field filter for string failed: %v", err)
|
||||
}
|
||||
s.Queries[i].fieldFilterString = fieldfilterString
|
||||
|
||||
// Compile the field-filter
|
||||
fieldfilter, err := filter.NewIncludeExcludeFilter(q.FieldColumnsInclude, q.FieldColumnsExclude)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating field filter failed: %v", err)
|
||||
}
|
||||
s.Queries[i].fieldFilter = fieldfilter
|
||||
|
||||
if q.Measurement == "" {
|
||||
s.Queries[i].Measurement = "sql"
|
||||
}
|
||||
}
|
||||
|
||||
// Derive the sql-framework driver name from our config name. This abstracts the actual driver
|
||||
// from the database-type the user wants.
|
||||
aliases := map[string]string{
|
||||
"cockroach": "pgx",
|
||||
"tidb": "mysql",
|
||||
"mssql": "sqlserver",
|
||||
"maria": "mysql",
|
||||
"postgres": "pgx",
|
||||
}
|
||||
s.driverName = s.Driver
|
||||
if driver, ok := aliases[s.Driver]; ok {
|
||||
s.driverName = driver
|
||||
}
|
||||
|
||||
availDrivers := dbsql.Drivers()
|
||||
if !choice.Contains(s.driverName, availDrivers) {
|
||||
for d, r := range aliases {
|
||||
if choice.Contains(r, availDrivers) {
|
||||
availDrivers = append(availDrivers, d)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the list of drivers and make them unique
|
||||
sort.Strings(availDrivers)
|
||||
last := 0
|
||||
for _, d := range availDrivers {
|
||||
if d != availDrivers[last] {
|
||||
last++
|
||||
availDrivers[last] = d
|
||||
}
|
||||
}
|
||||
availDrivers = availDrivers[:last+1]
|
||||
|
||||
return fmt.Errorf("driver %q not supported use one of %v", s.Driver, availDrivers)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SQL) Start(_ telegraf.Accumulator) error {
|
||||
var err error
|
||||
|
||||
// Connect to the database server
|
||||
s.Log.Debugf("Connecting to %q...", s.Dsn)
|
||||
s.db, err = dbsql.Open(s.driverName, s.Dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the connection limits
|
||||
// s.db.SetConnMaxIdleTime(time.Duration(s.MaxIdleTime)) // Requires go >= 1.15
|
||||
s.db.SetConnMaxLifetime(time.Duration(s.MaxLifetime))
|
||||
s.db.SetMaxOpenConns(s.MaxOpenConnections)
|
||||
s.db.SetMaxIdleConns(s.MaxIdleConnections)
|
||||
|
||||
// Test if the connection can be established
|
||||
s.Log.Debugf("Testing connectivity...")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(s.Timeout))
|
||||
err = s.db.PingContext(ctx)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return fmt.Errorf("connecting to database failed: %v", err)
|
||||
}
|
||||
|
||||
// Prepare the statements
|
||||
for i, q := range s.Queries {
|
||||
s.Log.Debugf("Preparing statement %q...", q.Query)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(s.Timeout))
|
||||
stmt, err := s.db.PrepareContext(ctx, q.Query) //nolint:sqlclosecheck // Closed in Stop()
|
||||
cancel()
|
||||
if err != nil {
|
||||
return fmt.Errorf("preparing query %q failed: %v", q.Query, err)
|
||||
}
|
||||
s.Queries[i].statement = stmt
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SQL) Stop() {
|
||||
// Free the statements
|
||||
for _, q := range s.Queries {
|
||||
if q.statement != nil {
|
||||
if err := q.statement.Close(); err != nil {
|
||||
s.Log.Errorf("closing statement for query %q failed: %v", q.Query, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection to the server
|
||||
if s.db != nil {
|
||||
if err := s.db.Close(); err != nil {
|
||||
s.Log.Errorf("closing database connection failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SQL) Gather(acc telegraf.Accumulator) error {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(s.Timeout))
|
||||
defer cancel()
|
||||
|
||||
tstart := time.Now()
|
||||
for _, query := range s.Queries {
|
||||
wg.Add(1)
|
||||
|
||||
go func(q Query) {
|
||||
defer wg.Done()
|
||||
if err := s.executeQuery(ctx, acc, q, tstart); err != nil {
|
||||
acc.AddError(err)
|
||||
}
|
||||
}(query)
|
||||
}
|
||||
wg.Wait()
|
||||
s.Log.Debugf("Executed %d queries in %s", len(s.Queries), time.Since(tstart).String())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("sql", func() telegraf.Input {
|
||||
return &SQL{
|
||||
MaxIdleTime: config.Duration(0), // unlimited
|
||||
MaxLifetime: config.Duration(0), // unlimited
|
||||
MaxOpenConnections: 0, // unlimited
|
||||
MaxIdleConnections: magicIdleCount, // will trigger auto calculation
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SQL) executeQuery(ctx context.Context, acc telegraf.Accumulator, q Query, tquery time.Time) error {
|
||||
if q.statement == nil {
|
||||
return fmt.Errorf("statement is nil for query %q", q.Query)
|
||||
}
|
||||
|
||||
// Execute the query
|
||||
rows, err := q.statement.QueryContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
// Handle the rows
|
||||
columnNames, err := rows.Columns()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rowCount, err := q.parse(ctx, acc, rows, tquery)
|
||||
s.Log.Debugf("Received %d rows and %d columns for query %q", rowCount, len(columnNames), q.Query)
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func pwgen(n int) string {
|
||||
charset := []byte("abcdedfghijklmnopqrstABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
|
||||
nchars := len(charset)
|
||||
buffer := make([]byte, n)
|
||||
|
||||
for i := range buffer {
|
||||
buffer[i] = charset[rand.Intn(nchars)]
|
||||
}
|
||||
|
||||
return string(buffer)
|
||||
}
|
||||
|
||||
var spinup = flag.Bool("spinup", false, "Spin-up the required test containers")
|
||||
|
||||
func TestMariaDB(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
logger := testutil.Logger{}
|
||||
|
||||
addr := "127.0.0.1"
|
||||
port := "3306"
|
||||
passwd := ""
|
||||
database := "foo"
|
||||
|
||||
if *spinup {
|
||||
logger.Infof("Spinning up container...")
|
||||
|
||||
// Generate a random password
|
||||
passwd = pwgen(32)
|
||||
|
||||
// Determine the test-data mountpoint
|
||||
testdata, err := filepath.Abs("testdata/mariadb")
|
||||
require.NoError(t, err, "determining absolute path of test-data failed")
|
||||
|
||||
// Spin-up the container
|
||||
ctx := context.Background()
|
||||
req := testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: testcontainers.ContainerRequest{
|
||||
Image: "mariadb",
|
||||
Env: map[string]string{
|
||||
"MYSQL_ROOT_PASSWORD": passwd,
|
||||
"MYSQL_DATABASE": database,
|
||||
},
|
||||
BindMounts: map[string]string{
|
||||
testdata: "/docker-entrypoint-initdb.d",
|
||||
},
|
||||
ExposedPorts: []string{"3306/tcp"},
|
||||
WaitingFor: wait.ForListeningPort("3306/tcp"),
|
||||
},
|
||||
Started: true,
|
||||
}
|
||||
container, err := testcontainers.GenericContainer(ctx, req)
|
||||
require.NoError(t, err, "starting container failed")
|
||||
defer func() {
|
||||
require.NoError(t, container.Terminate(ctx), "terminating container failed")
|
||||
}()
|
||||
|
||||
// Get the connection details from the container
|
||||
addr, err = container.Host(ctx)
|
||||
require.NoError(t, err, "getting container host address failed")
|
||||
p, err := container.MappedPort(ctx, "3306/tcp")
|
||||
require.NoError(t, err, "getting container host port failed")
|
||||
port = p.Port()
|
||||
}
|
||||
|
||||
// Define the testset
|
||||
var testset = []struct {
|
||||
name string
|
||||
queries []Query
|
||||
expected []telegraf.Metric
|
||||
}{
|
||||
{
|
||||
name: "metric_one",
|
||||
queries: []Query{
|
||||
{
|
||||
Query: "SELECT * FROM metric_one",
|
||||
TagColumnsInclude: []string{"tag_*"},
|
||||
FieldColumnsExclude: []string{"tag_*", "timestamp"},
|
||||
TimeColumn: "timestamp",
|
||||
TimeFormat: "2006-01-02 15:04:05",
|
||||
},
|
||||
},
|
||||
expected: []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"sql",
|
||||
map[string]string{
|
||||
"tag_one": "tag1",
|
||||
"tag_two": "tag2",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"int64_one": int64(1234),
|
||||
"int64_two": int64(2345),
|
||||
},
|
||||
time.Date(2021, 5, 17, 22, 4, 45, 0, time.UTC),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testset {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Setup the plugin-under-test
|
||||
plugin := &SQL{
|
||||
Driver: "maria",
|
||||
Dsn: fmt.Sprintf("root:%s@tcp(%s:%s)/%s", passwd, addr, port, database),
|
||||
Queries: tt.queries,
|
||||
Log: logger,
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
// Startup the plugin
|
||||
err := plugin.Init()
|
||||
require.NoError(t, err)
|
||||
err = plugin.Start(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Gather
|
||||
err = plugin.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, acc.Errors, 0)
|
||||
|
||||
// Stopping the plugin
|
||||
plugin.Stop()
|
||||
|
||||
// Do the comparison
|
||||
testutil.RequireMetricsEqual(t, tt.expected, acc.GetTelegrafMetrics())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostgreSQL(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping integration test in short mode")
|
||||
}
|
||||
|
||||
logger := testutil.Logger{}
|
||||
|
||||
addr := "127.0.0.1"
|
||||
port := "5432"
|
||||
passwd := ""
|
||||
database := "foo"
|
||||
|
||||
if *spinup {
|
||||
logger.Infof("Spinning up container...")
|
||||
|
||||
// Generate a random password
|
||||
passwd = pwgen(32)
|
||||
|
||||
// Determine the test-data mountpoint
|
||||
testdata, err := filepath.Abs("testdata/postgres")
|
||||
require.NoError(t, err, "determining absolute path of test-data failed")
|
||||
|
||||
// Spin-up the container
|
||||
ctx := context.Background()
|
||||
req := testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: testcontainers.ContainerRequest{
|
||||
Image: "postgres",
|
||||
Env: map[string]string{
|
||||
"POSTGRES_PASSWORD": passwd,
|
||||
"POSTGRES_DB": database,
|
||||
},
|
||||
BindMounts: map[string]string{
|
||||
testdata: "/docker-entrypoint-initdb.d",
|
||||
},
|
||||
ExposedPorts: []string{"5432/tcp"},
|
||||
WaitingFor: wait.ForListeningPort("5432/tcp"),
|
||||
},
|
||||
Started: true,
|
||||
}
|
||||
container, err := testcontainers.GenericContainer(ctx, req)
|
||||
require.NoError(t, err, "starting container failed")
|
||||
defer func() {
|
||||
require.NoError(t, container.Terminate(ctx), "terminating container failed")
|
||||
}()
|
||||
|
||||
// Get the connection details from the container
|
||||
addr, err = container.Host(ctx)
|
||||
require.NoError(t, err, "getting container host address failed")
|
||||
p, err := container.MappedPort(ctx, "5432/tcp")
|
||||
require.NoError(t, err, "getting container host port failed")
|
||||
port = p.Port()
|
||||
}
|
||||
|
||||
// Define the testset
|
||||
var testset = []struct {
|
||||
name string
|
||||
queries []Query
|
||||
expected []telegraf.Metric
|
||||
}{
|
||||
{
|
||||
name: "metric_one",
|
||||
queries: []Query{
|
||||
{
|
||||
Query: "SELECT * FROM metric_one",
|
||||
TagColumnsInclude: []string{"tag_*"},
|
||||
FieldColumnsExclude: []string{"tag_*", "timestamp"},
|
||||
TimeColumn: "timestamp",
|
||||
TimeFormat: "2006-01-02 15:04:05",
|
||||
},
|
||||
},
|
||||
expected: []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
"sql",
|
||||
map[string]string{
|
||||
"tag_one": "tag1",
|
||||
"tag_two": "tag2",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"int64_one": int64(1234),
|
||||
"int64_two": int64(2345),
|
||||
},
|
||||
time.Date(2021, 5, 17, 22, 4, 45, 0, time.UTC),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testset {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Setup the plugin-under-test
|
||||
plugin := &SQL{
|
||||
Driver: "pgx",
|
||||
Dsn: fmt.Sprintf("postgres://postgres:%v@%v:%v/%v", passwd, addr, port, database),
|
||||
Queries: tt.queries,
|
||||
Log: logger,
|
||||
}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
||||
// Startup the plugin
|
||||
err := plugin.Init()
|
||||
require.NoError(t, err)
|
||||
err = plugin.Start(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Gather
|
||||
err = plugin.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, acc.Errors, 0)
|
||||
|
||||
// Stopping the plugin
|
||||
plugin.Stop()
|
||||
|
||||
// Do the comparison
|
||||
testutil.RequireMetricsEqual(t, tt.expected, acc.GetTelegrafMetrics())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `bar` (
|
||||
`baz` int(11) DEFAULT NULL
|
||||
);
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
INSERT INTO `bar` VALUES (1);
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `metric three` (
|
||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`tag four` text DEFAULT NULL,
|
||||
`string two` text DEFAULT NULL
|
||||
);
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
INSERT INTO `metric three` VALUES ('2021-05-17 22:04:45','tag4','string2');
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `metric_one` (
|
||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`tag_one` text DEFAULT NULL,
|
||||
`tag_two` text DEFAULT NULL,
|
||||
`int64_one` int(11) DEFAULT NULL,
|
||||
`int64_two` int(11) DEFAULT NULL
|
||||
);
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
INSERT INTO `metric_one` VALUES ('2021-05-17 22:04:45','tag1','tag2',1234,2345);
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `metric_two` (
|
||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||
`tag_three` text DEFAULT NULL,
|
||||
`string_one` text DEFAULT NULL
|
||||
);
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
INSERT INTO `metric_two` VALUES ('2021-05-17 22:04:45','tag3','string1');
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
SET default_tablespace = '';
|
||||
SET default_table_access_method = heap;
|
||||
CREATE TABLE public."metric three" (
|
||||
"timestamp" timestamp without time zone,
|
||||
"tag four" text,
|
||||
"string two" text
|
||||
);
|
||||
ALTER TABLE public."metric three" OWNER TO postgres;
|
||||
CREATE TABLE public.metric_one (
|
||||
"timestamp" timestamp without time zone,
|
||||
tag_one text,
|
||||
tag_two text,
|
||||
int64_one integer,
|
||||
int64_two integer
|
||||
);
|
||||
ALTER TABLE public.metric_one OWNER TO postgres;
|
||||
CREATE TABLE public.metric_two (
|
||||
"timestamp" timestamp without time zone,
|
||||
tag_three text,
|
||||
string_one text
|
||||
);
|
||||
ALTER TABLE public.metric_two OWNER TO postgres;
|
||||
COPY public."metric three" ("timestamp", "tag four", "string two") FROM stdin;
|
||||
2021-05-17 22:04:45 tag4 string2
|
||||
\.
|
||||
COPY public.metric_one ("timestamp", tag_one, tag_two, int64_one, int64_two) FROM stdin;
|
||||
2021-05-17 22:04:45 tag1 tag2 1234 2345
|
||||
\.
|
||||
COPY public.metric_two ("timestamp", tag_three, string_one) FROM stdin;
|
||||
2021-05-17 22:04:45 tag3 string1
|
||||
\.
|
||||
Loading…
Reference in New Issue