Compare commits
80 Commits
1.7.0-rc2
...
bugfix/433
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f4bd9ad82 | ||
|
|
4ea618ea26 | ||
|
|
a7545e6cac | ||
|
|
58e815fdd1 | ||
|
|
06682c6350 | ||
|
|
839ca60b0e | ||
|
|
9fe90d71f4 | ||
|
|
2ee374cf50 | ||
|
|
220e6c5361 | ||
|
|
c7cfc2ec39 | ||
|
|
9bc63c2f7a | ||
|
|
56ea2eb57b | ||
|
|
210dfcee83 | ||
|
|
b7a02c73b3 | ||
|
|
73e2e6afc5 | ||
|
|
b2586a7eaf | ||
|
|
abfbf4f4f2 | ||
|
|
85eacf268b | ||
|
|
1a781a5851 | ||
|
|
ed2bc1151b | ||
|
|
b2e972cd81 | ||
|
|
54056f3808 | ||
|
|
5aa199e2b3 | ||
|
|
9bd5e10133 | ||
|
|
beaef8e3da | ||
|
|
a10262c5d6 | ||
|
|
8bf18d6ac7 | ||
|
|
23523ffd10 | ||
|
|
523d761f34 | ||
|
|
3f28add025 | ||
|
|
ee6e4b0afd | ||
|
|
16454e25ba | ||
|
|
2a1feb6db9 | ||
|
|
61e197d254 | ||
|
|
1bd41ef3ce | ||
|
|
d7c756e9ff | ||
|
|
39206677f8 | ||
|
|
b66eb2fec7 | ||
|
|
3ad10283ef | ||
|
|
84e9a5c97e | ||
|
|
c98b58dacc | ||
|
|
98d86df797 | ||
|
|
4e9e57e210 | ||
|
|
7781507c01 | ||
|
|
8482c40a91 | ||
|
|
0dda9b8319 | ||
|
|
4e69d10ff7 | ||
|
|
f689463e8e | ||
|
|
f217d12de5 | ||
|
|
886795063e | ||
|
|
30dc95fa78 | ||
|
|
40fac0a9b4 | ||
|
|
36df4c5ae5 | ||
|
|
70ffed3a4d | ||
|
|
bf59bcf721 | ||
|
|
a789f97feb | ||
|
|
d2e00a3205 | ||
|
|
daddd8bbac | ||
|
|
d16530677d | ||
|
|
1ea18ffd0a | ||
|
|
dd2223ae1c | ||
|
|
90eebd88af | ||
|
|
d2e729dfaf | ||
|
|
f64d612294 | ||
|
|
76ec90e66d | ||
|
|
1690f36b09 | ||
|
|
87f711a19a | ||
|
|
58895d6b03 | ||
|
|
cd9ad77038 | ||
|
|
8563238059 | ||
|
|
11335f5fee | ||
|
|
acba20af1a | ||
|
|
229b6bd944 | ||
|
|
7fe6e2f5ae | ||
|
|
a4214abfc4 | ||
|
|
5f0cbd1255 | ||
|
|
3ef4dff4ec | ||
|
|
dfe7b5eec2 | ||
|
|
92a8f795f5 | ||
|
|
b1d77ade55 |
@@ -2,15 +2,12 @@
|
||||
defaults:
|
||||
defaults: &defaults
|
||||
working_directory: '/go/src/github.com/influxdata/telegraf'
|
||||
go-1_8: &go-1_8
|
||||
docker:
|
||||
- image: 'circleci/golang:1.8.7'
|
||||
go-1_9: &go-1_9
|
||||
docker:
|
||||
- image: 'circleci/golang:1.9.5'
|
||||
- image: 'circleci/golang:1.9.7'
|
||||
go-1_10: &go-1_10
|
||||
docker:
|
||||
- image: 'circleci/golang:1.10.1'
|
||||
- image: 'circleci/golang:1.10.3'
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
@@ -18,17 +15,18 @@ jobs:
|
||||
<<: [ *defaults, *go-1_10 ]
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: vendor-{{ checksum "Gopkg.lock" }}
|
||||
- run: 'make deps'
|
||||
- save_cache:
|
||||
name: 'vendored deps'
|
||||
key: vendor-{{ checksum "Gopkg.lock" }}
|
||||
paths:
|
||||
- './vendor'
|
||||
- persist_to_workspace:
|
||||
root: '/go/src'
|
||||
paths:
|
||||
- '*'
|
||||
test-go-1.8:
|
||||
<<: [ *defaults, *go-1_8 ]
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '/go/src'
|
||||
- run: 'make test-ci'
|
||||
test-go-1.9:
|
||||
<<: [ *defaults, *go-1_9 ]
|
||||
steps:
|
||||
@@ -66,9 +64,6 @@ workflows:
|
||||
build_and_release:
|
||||
jobs:
|
||||
- 'deps'
|
||||
- 'test-go-1.8':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'test-go-1.9':
|
||||
requires:
|
||||
- 'deps'
|
||||
@@ -77,15 +72,11 @@ workflows:
|
||||
- 'deps'
|
||||
- 'release':
|
||||
requires:
|
||||
- 'test-go-1.8'
|
||||
- 'test-go-1.9'
|
||||
- 'test-go-1.10'
|
||||
nightly:
|
||||
jobs:
|
||||
- 'deps'
|
||||
- 'test-go-1.8':
|
||||
requires:
|
||||
- 'deps'
|
||||
- 'test-go-1.9':
|
||||
requires:
|
||||
- 'deps'
|
||||
@@ -94,7 +85,6 @@ workflows:
|
||||
- 'deps'
|
||||
- 'nightly':
|
||||
requires:
|
||||
- 'test-go-1.8'
|
||||
- 'test-go-1.9'
|
||||
- 'test-go-1.10'
|
||||
triggers:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
/telegraf
|
||||
/telegraf.exe
|
||||
/telegraf.gz
|
||||
/vendor
|
||||
|
||||
47
CHANGELOG.md
47
CHANGELOG.md
@@ -1,4 +1,45 @@
|
||||
## v1.7 [unreleased]
|
||||
## v1.8 [unreleased]
|
||||
|
||||
### Release Notes
|
||||
|
||||
### New Inputs
|
||||
|
||||
- [tengine](./plugins/inputs/tengine/README.md) - Contributed by @ertaoxu
|
||||
|
||||
### New Aggregators
|
||||
|
||||
- [valuecounter](./plugins/aggregators/valuecounter/README.md) - Contributed by @piotr1212
|
||||
|
||||
### Features
|
||||
|
||||
- [#4236](https://github.com/influxdata/telegraf/pull/4236): Add SSL/TLS support to redis input.
|
||||
- [#4160](https://github.com/influxdata/telegraf/pull/4160): Add tengine input plugin.
|
||||
- [#4262](https://github.com/influxdata/telegraf/pull/4262): Add power draw field to nvidia_smi plugin.
|
||||
- [#4271](https://github.com/influxdata/telegraf/pull/4271): Add support for solr 7 to the solr input.
|
||||
- [#4281](https://github.com/influxdata/telegraf/pull/4281): Add owner tag on partitions in burrow input.
|
||||
- [#4259](https://github.com/influxdata/telegraf/pull/4259): Add container status tag to docker input.
|
||||
- [#3523](https://github.com/influxdata/telegraf/pull/3523): Add valuecounter aggregator plugin.
|
||||
- [#4307](https://github.com/influxdata/telegraf/pull/4307): Add new measurement with results of pgrep lookup to procstat input.
|
||||
- [#4311](https://github.com/influxdata/telegraf/pull/4311): Add support for comma in logparser timestamp format.
|
||||
- [#4292](https://github.com/influxdata/telegraf/pull/4292): Add path tag to tail input plugin.
|
||||
- [#4322](https://github.com/influxdata/telegraf/pull/4322): Add log message when tail is added or removed from a file.
|
||||
- [#4267](https://github.com/influxdata/telegraf/pull/4267): Add option to use of counter time in win perf counters.
|
||||
- [#4343](https://github.com/influxdata/telegraf/pull/4343): Add energy and power field and device id tag to fibaro input.
|
||||
- [#4347](https://github.com/influxdata/telegraf/pull/4347): Add http path configuration for OpenTSDB output.
|
||||
|
||||
## v1.7.1 [unreleased]
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- [#4277](https://github.com/influxdata/telegraf/pull/4277): Treat sigterm as a clean shutdown signal.
|
||||
- [#4284](https://github.com/influxdata/telegraf/pull/4284): Fix selection of tags under nested objects in the JSON parser.
|
||||
- [#4135](https://github.com/influxdata/telegraf/issues/4135): Fix postfix input handling multi-level queues.
|
||||
- [#4334](https://github.com/influxdata/telegraf/pull/4334): Fix syslog timestamp parsing with single digit day of month.
|
||||
- [#2910](https://github.com/influxdata/telegraf/issues/2910): Handle mysql input variations in the user_statistics collecting.
|
||||
- [#4293](https://github.com/influxdata/telegraf/issues/4293): Fix minmax and basicstats aggregators to use uint64.
|
||||
- [#4290](https://github.com/influxdata/telegraf/issues/4290): Document swap input plugin.
|
||||
|
||||
## v1.7 [2018-06-12]
|
||||
|
||||
### Release Notes
|
||||
|
||||
@@ -73,8 +114,10 @@
|
||||
- [#2879](https://github.com/influxdata/telegraf/issues/2879): Fix wildcards and multi instance processes in win_perf_counters.
|
||||
- [#2468](https://github.com/influxdata/telegraf/issues/2468): Fix crash on 32-bit Windows in win_perf_counters.
|
||||
- [#4198](https://github.com/influxdata/telegraf/issues/4198): Fix win_perf_counters not collecting at every interval.
|
||||
- [#4227](https://github.com/influxdata/telegraf/issues/4227): Use same flags for all BSD family ping variants.
|
||||
- [#4266](https://github.com/influxdata/telegraf/issues/4266): Remove tags with empty values from Wavefront output.
|
||||
|
||||
## v1.6.4 [unreleased]
|
||||
## v1.6.4 [2018-06-05]
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ which can be found [on our website](http://influxdb.com/community/cla.html)
|
||||
|
||||
Assuming you can already build the project, run these in the telegraf directory:
|
||||
|
||||
1. `go get github.com/sparrc/gdm`
|
||||
1. `gdm restore`
|
||||
1. `GOOS=linux gdm save`
|
||||
1. `go get -u github.com/golang/dep/cmd/dep`
|
||||
2. `dep ensure`
|
||||
3. `dep ensure -add github.com/[dependency]/[new-package]`
|
||||
|
||||
## Input Plugins
|
||||
|
||||
@@ -100,6 +100,13 @@ func init() {
|
||||
}
|
||||
```
|
||||
|
||||
### Input Plugin Development
|
||||
|
||||
* Run `make static` followed by `make plugin-[pluginName]` to spin up a docker dev environment
|
||||
using docker-compose.
|
||||
* ***[Optional]*** When developing a plugin, add a `dev` directory with a `docker-compose.yml` and `telegraf.conf`
|
||||
as well as any other supporting files, where sensible.
|
||||
|
||||
## Adding Typed Metrics
|
||||
|
||||
In addition the the `AddFields` function, the accumulator also supports an
|
||||
|
||||
101
Godeps
101
Godeps
@@ -1,101 +0,0 @@
|
||||
code.cloudfoundry.org/clock e9dc86bbf0e5bbe6bf7ff5a6f71e048959b61f71
|
||||
collectd.org 2ce144541b8903101fb8f1483cc0497a68798122
|
||||
github.com/aerospike/aerospike-client-go 95e1ad7791bdbca44707fedbb29be42024900d9c
|
||||
github.com/amir/raidman c74861fe6a7bb8ede0a010ce4485bdbb4fc4c985
|
||||
github.com/apache/thrift 4aaa92ece8503a6da9bc6701604f69acf2b99d07
|
||||
github.com/aws/aws-sdk-go c861d27d0304a79f727e9a8a4e2ac1e74602fdc0
|
||||
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||
github.com/bsm/sarama-cluster abf039439f66c1ce78017f560b490612552f6472
|
||||
github.com/cenkalti/backoff b02f2bbce11d7ea6b97f282ef1771b0fe2f65ef3
|
||||
github.com/couchbase/go-couchbase bfe555a140d53dc1adf390f1a1d4b0fd4ceadb28
|
||||
github.com/couchbase/gomemcached 4a25d2f4e1dea9ea7dd76dfd943407abf9b07d29
|
||||
github.com/couchbase/goutils 5823a0cbaaa9008406021dc5daf80125ea30bba6
|
||||
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76
|
||||
github.com/dgrijalva/jwt-go dbeaa9332f19a944acb5736b4456cfcc02140e29
|
||||
github.com/docker/docker f5ec1e2936dcbe7b5001c2b817188b095c700c27
|
||||
github.com/docker/go-connections 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a
|
||||
github.com/eapache/go-resiliency b86b1ec0dd4209a588dc1285cdd471e73525c0b3
|
||||
github.com/eapache/go-xerial-snappy bb955e01b9346ac19dc29eb16586c90ded99a98c
|
||||
github.com/eapache/queue 44cc805cf13205b55f69e14bcb69867d1ae92f98
|
||||
github.com/eclipse/paho.mqtt.golang aff15770515e3c57fc6109da73d42b0d46f7f483
|
||||
github.com/go-logfmt/logfmt 390ab7935ee28ec6b286364bba9b4dd6410cb3d5
|
||||
github.com/go-sql-driver/mysql 2e00b5cd70399450106cec6431c2e2ce3cae5034
|
||||
github.com/gobwas/glob bea32b9cd2d6f55753d94a28e959b13f0244797a
|
||||
github.com/go-ini/ini 9144852efba7c4daf409943ee90767da62d55438
|
||||
github.com/gogo/protobuf 7b6c6391c4ff245962047fc1e2c6e08b1cdfa0e8
|
||||
github.com/golang/protobuf 8ee79997227bf9b34611aee7946ae64735e6fd93
|
||||
github.com/golang/snappy 7db9049039a047d955fe8c19b83c8ff5abd765c7
|
||||
github.com/go-ole/go-ole be49f7c07711fcb603cff39e1de7c67926dc0ba7
|
||||
github.com/google/go-cmp f94e52cad91c65a63acc1e75d4be223ea22e99bc
|
||||
github.com/gorilla/mux 53c1911da2b537f792e7cafcb446b05ffe33b996
|
||||
github.com/go-redis/redis 73b70592cdaa9e6abdfcfbf97b4a90d80728c836
|
||||
github.com/go-sql-driver/mysql 2e00b5cd70399450106cec6431c2e2ce3cae5034
|
||||
github.com/hailocab/go-hostpool e80d13ce29ede4452c43dea11e79b9bc8a15b478
|
||||
github.com/hashicorp/consul 5174058f0d2bda63fa5198ab96c33d9a909c58ed
|
||||
github.com/influxdata/go-syslog 84f3b60009444d298f97454feb1f20cf91d1fa6e
|
||||
github.com/influxdata/tail c43482518d410361b6c383d7aebce33d0471d7bc
|
||||
github.com/influxdata/toml 5d1d907f22ead1cd47adde17ceec5bda9cacaf8f
|
||||
github.com/influxdata/wlog 7c63b0a71ef8300adc255344d275e10e5c3a71ec
|
||||
github.com/fsnotify/fsnotify c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9
|
||||
github.com/jackc/pgx 63f58fd32edb5684b9e9f4cfaac847c6b42b3917
|
||||
github.com/jmespath/go-jmespath bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d
|
||||
github.com/kardianos/osext c2c54e542fb797ad986b31721e1baedf214ca413
|
||||
github.com/kardianos/service 6d3a0ee7d3425d9d835debc51a0ca1ffa28f4893
|
||||
github.com/kballard/go-shellquote d8ec1a69a250a17bb0e419c386eac1f3711dc142
|
||||
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c
|
||||
github.com/Microsoft/ApplicationInsights-Go 3612f58550c1de70f1a110c78c830e55f29aa65d
|
||||
github.com/Microsoft/go-winio ce2922f643c8fd76b46cadc7f404a06282678b34
|
||||
github.com/miekg/dns 99f84ae56e75126dd77e5de4fae2ea034a468ca1
|
||||
github.com/mitchellh/mapstructure d0303fe809921458f417bcf828397a65db30a7e4
|
||||
github.com/multiplay/go-ts3 07477f49b8dfa3ada231afc7b7b17617d42afe8e
|
||||
github.com/naoina/go-stringutil 6b638e95a32d0c1131db0e7fe83775cbea4a0d0b
|
||||
github.com/nats-io/gnatsd 393bbb7c031433e68707c8810fda0bfcfbe6ab9b
|
||||
github.com/nats-io/go-nats ea9585611a4ab58a205b9b125ebd74c389a6b898
|
||||
github.com/nats-io/nats ea9585611a4ab58a205b9b125ebd74c389a6b898
|
||||
github.com/nats-io/nuid 289cccf02c178dc782430d534e3c1f5b72af807f
|
||||
github.com/nsqio/go-nsq eee57a3ac4174c55924125bb15eeeda8cffb6e6f
|
||||
github.com/opencontainers/runc 89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8
|
||||
github.com/opentracing-contrib/go-observer a52f2342449246d5bcc273e65cbdcfa5f7d6c63c
|
||||
github.com/opentracing/opentracing-go 06f47b42c792fef2796e9681353e1d908c417827
|
||||
github.com/openzipkin/zipkin-go-opentracing 1cafbdfde94fbf2b373534764e0863aa3bd0bf7b
|
||||
github.com/pierrec/lz4 5c9560bfa9ace2bf86080bf40d46b34ae44604df
|
||||
github.com/pierrec/xxHash 5a004441f897722c627870a981d02b29924215fa
|
||||
github.com/pkg/errors 645ef00459ed84a119197bfb8d8205042c6df63d
|
||||
github.com/pmezard/go-difflib/difflib 792786c7400a136282c1664665ae0a8db921c6c2
|
||||
github.com/prometheus/client_golang c317fb74746eac4fc65fe3909195f4cf67c5562a
|
||||
github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6
|
||||
github.com/prometheus/common dd2f054febf4a6c00f2343686efb775948a8bff4
|
||||
github.com/prometheus/procfs 1878d9fbb537119d24b21ca07effd591627cd160
|
||||
github.com/rcrowley/go-metrics 1f30fe9094a513ce4c700b9a54458bbb0c96996c
|
||||
github.com/samuel/go-zookeeper 1d7be4effb13d2d908342d349d71a284a7542693
|
||||
github.com/satori/go.uuid 5bf94b69c6b68ee1b541973bb8e1144db23a194b
|
||||
github.com/shirou/gopsutil c95755e4bcd7a62bb8bd33f3a597a7c7f35e2cf3
|
||||
github.com/shirou/w32 3c9377fc6748f222729a8270fe2775d149a249ad
|
||||
github.com/Shopify/sarama 3b1b38866a79f06deddf0487d5c27ba0697ccd65
|
||||
github.com/Sirupsen/logrus 61e43dc76f7ee59a82bdf3d71033dc12bea4c77d
|
||||
github.com/soniah/gosnmp f15472a4cd6f6ea7929e4c7d9f163c49f059924f
|
||||
github.com/StackExchange/wmi f3e2bae1e0cb5aef83e319133eabfee30013a4a5
|
||||
github.com/streadway/amqp 63795daa9a446c920826655f26ba31c81c860fd6
|
||||
github.com/stretchr/objx facf9a85c22f48d2f52f2380e4efce1768749a89
|
||||
github.com/stretchr/testify 12b6f73e6084dad08a7c6e575284b177ecafbc71
|
||||
github.com/tidwall/gjson 0623bd8fbdbf97cc62b98d15108832851a658e59
|
||||
github.com/tidwall/match 173748da739a410c5b0b813b956f89ff94730b4c
|
||||
github.com/vjeantet/grok d73e972b60935c7fec0b4ffbc904ed39ecaf7efe
|
||||
github.com/wvanbergen/kafka bc265fedb9ff5b5c5d3c0fdcef4a819b3523d3ee
|
||||
github.com/wvanbergen/kazoo-go 968957352185472eacb69215fa3dbfcfdbac1096
|
||||
github.com/yuin/gopher-lua 66c871e454fcf10251c61bf8eff02d0978cae75a
|
||||
github.com/zensqlmonitor/go-mssqldb ffe5510c6fa5e15e6d983210ab501c815b56b363
|
||||
golang.org/x/crypto dc137beb6cce2043eb6b5f223ab8bf51c32459f4
|
||||
golang.org/x/net a337091b0525af65de94df2eb7e98bd9962dcbe2
|
||||
golang.org/x/sys 739734461d1c916b6c72a63d7efda2b27edb369f
|
||||
golang.org/x/text 506f9d5c962f284575e88337e7d9296d27e729d3
|
||||
google.golang.org/genproto 11c7f9e547da6db876260ce49ea7536985904c9b
|
||||
google.golang.org/grpc de2209a968d48e8970546c8a710189f7461370f7
|
||||
gopkg.in/asn1-ber.v1 4e86f4367175e39f69d9358a5f17b4dda270378d
|
||||
gopkg.in/fatih/pool.v2 6e328e67893eb46323ad06f0e92cb9536babbabc
|
||||
gopkg.in/gorethink/gorethink.v3 7ab832f7b65573104a555d84a27992ae9ea1f659
|
||||
gopkg.in/ldap.v2 8168ee085ee43257585e50c6441aadf54ecb2c9f
|
||||
gopkg.in/mgo.v2 3f83fa5005286a7fe593b055f0d7771a7dce4655
|
||||
gopkg.in/olivere/elastic.v5 3113f9b9ad37509fe5f8a0e5e91c96fdc4435e26
|
||||
gopkg.in/tomb.v1 dd632973f1e7218eb1089048e0798ec9ae7dceb8
|
||||
gopkg.in/yaml.v2 4c78c975fe7c825c6d1466c42be594d1d6f3aba6
|
||||
973
Gopkg.lock
generated
Normal file
973
Gopkg.lock
generated
Normal file
@@ -0,0 +1,973 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "code.cloudfoundry.org/clock"
|
||||
packages = ["."]
|
||||
revision = "02e53af36e6c978af692887ed449b74026d76fec"
|
||||
|
||||
[[projects]]
|
||||
name = "collectd.org"
|
||||
packages = [
|
||||
"api",
|
||||
"cdtime",
|
||||
"network"
|
||||
]
|
||||
revision = "2ce144541b8903101fb8f1483cc0497a68798122"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Microsoft/ApplicationInsights-Go"
|
||||
packages = [
|
||||
"appinsights",
|
||||
"appinsights/contracts"
|
||||
]
|
||||
revision = "d2df5d440eda5372f24fcac03839a64d6cb5f7e5"
|
||||
version = "v0.4.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Microsoft/go-winio"
|
||||
packages = ["."]
|
||||
revision = "7da180ee92d8bd8bb8c37fc560e673e6557c392f"
|
||||
version = "v0.4.7"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Shopify/sarama"
|
||||
packages = ["."]
|
||||
revision = "35324cf48e33d8260e1c7c18854465a904ade249"
|
||||
version = "v1.17.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/StackExchange/wmi"
|
||||
packages = ["."]
|
||||
revision = "5d049714c4a64225c3c79a7cf7d02f7fb5b96338"
|
||||
version = "1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/aerospike/aerospike-client-go"
|
||||
packages = [
|
||||
".",
|
||||
"internal/lua",
|
||||
"internal/lua/resources",
|
||||
"logger",
|
||||
"pkg/bcrypt",
|
||||
"pkg/ripemd160",
|
||||
"types",
|
||||
"types/atomic",
|
||||
"types/particle_type",
|
||||
"types/rand",
|
||||
"utils/buffer"
|
||||
]
|
||||
revision = "c10b5393e43bd60125aca6289c7b24879edb1787"
|
||||
version = "v1.33.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/alecthomas/template"
|
||||
packages = [
|
||||
".",
|
||||
"parse"
|
||||
]
|
||||
revision = "a0175ee3bccc567396460bf5acd36800cb10c49c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/alecthomas/units"
|
||||
packages = ["."]
|
||||
revision = "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/amir/raidman"
|
||||
packages = [
|
||||
".",
|
||||
"proto"
|
||||
]
|
||||
revision = "1ccc43bfb9c93cb401a4025e49c64ba71e5e668b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/apache/thrift"
|
||||
packages = ["lib/go/thrift"]
|
||||
revision = "f5f430df56871bc937950274b2c86681d3db6e59"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
packages = [
|
||||
"aws",
|
||||
"aws/awserr",
|
||||
"aws/awsutil",
|
||||
"aws/client",
|
||||
"aws/client/metadata",
|
||||
"aws/corehandlers",
|
||||
"aws/credentials",
|
||||
"aws/credentials/ec2rolecreds",
|
||||
"aws/credentials/endpointcreds",
|
||||
"aws/credentials/stscreds",
|
||||
"aws/csm",
|
||||
"aws/defaults",
|
||||
"aws/ec2metadata",
|
||||
"aws/endpoints",
|
||||
"aws/request",
|
||||
"aws/session",
|
||||
"aws/signer/v4",
|
||||
"internal/sdkio",
|
||||
"internal/sdkrand",
|
||||
"internal/shareddefaults",
|
||||
"private/protocol",
|
||||
"private/protocol/json/jsonutil",
|
||||
"private/protocol/jsonrpc",
|
||||
"private/protocol/query",
|
||||
"private/protocol/query/queryutil",
|
||||
"private/protocol/rest",
|
||||
"private/protocol/xml/xmlutil",
|
||||
"service/cloudwatch",
|
||||
"service/kinesis",
|
||||
"service/sts"
|
||||
]
|
||||
revision = "bfc1a07cf158c30c41a3eefba8aae043d0bb5bff"
|
||||
version = "v1.14.8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/beorn7/perks"
|
||||
packages = ["quantile"]
|
||||
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/bsm/sarama-cluster"
|
||||
packages = ["."]
|
||||
revision = "cf455bc755fe41ac9bb2861e7a961833d9c2ecc3"
|
||||
version = "v2.1.13"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/cenkalti/backoff"
|
||||
packages = ["."]
|
||||
revision = "2ea60e5f094469f9e65adb9cd103795b73ae743e"
|
||||
version = "v2.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/couchbase/go-couchbase"
|
||||
packages = ["."]
|
||||
revision = "16db1f1fe037412f12738fa4d8448c549c4edd77"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/couchbase/gomemcached"
|
||||
packages = [
|
||||
".",
|
||||
"client"
|
||||
]
|
||||
revision = "0da75df145308b9a4e6704d762ca9d9b77752efc"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/couchbase/goutils"
|
||||
packages = [
|
||||
"logging",
|
||||
"scramsha"
|
||||
]
|
||||
revision = "e865a1461c8ac0032bd37e2d4dab3289faea3873"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/dgrijalva/jwt-go"
|
||||
packages = ["."]
|
||||
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
|
||||
version = "v3.2.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/distribution"
|
||||
packages = [
|
||||
"digest",
|
||||
"reference"
|
||||
]
|
||||
revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
|
||||
version = "v2.6.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/docker"
|
||||
packages = [
|
||||
"api/types",
|
||||
"api/types/blkiodev",
|
||||
"api/types/container",
|
||||
"api/types/events",
|
||||
"api/types/filters",
|
||||
"api/types/mount",
|
||||
"api/types/network",
|
||||
"api/types/reference",
|
||||
"api/types/registry",
|
||||
"api/types/strslice",
|
||||
"api/types/swarm",
|
||||
"api/types/time",
|
||||
"api/types/versions",
|
||||
"api/types/volume",
|
||||
"client",
|
||||
"pkg/tlsconfig"
|
||||
]
|
||||
revision = "eef6495eddab52828327aade186443681ed71a4e"
|
||||
version = "v17.03.2-ce-rc1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/go-connections"
|
||||
packages = [
|
||||
"nat",
|
||||
"sockets",
|
||||
"tlsconfig"
|
||||
]
|
||||
revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/go-units"
|
||||
packages = ["."]
|
||||
revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
|
||||
version = "v0.3.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/eapache/go-resiliency"
|
||||
packages = ["breaker"]
|
||||
revision = "ea41b0fad31007accc7f806884dcdf3da98b79ce"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/eapache/go-xerial-snappy"
|
||||
packages = ["."]
|
||||
revision = "bb955e01b9346ac19dc29eb16586c90ded99a98c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/eapache/queue"
|
||||
packages = ["."]
|
||||
revision = "44cc805cf13205b55f69e14bcb69867d1ae92f98"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/eclipse/paho.mqtt.golang"
|
||||
packages = [
|
||||
".",
|
||||
"packets"
|
||||
]
|
||||
revision = "36d01c2b4cbeb3d2a12063e4880ce30800af9560"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-ini/ini"
|
||||
packages = ["."]
|
||||
revision = "06f5f3d67269ccec1fe5fe4134ba6e982984f7f5"
|
||||
version = "v1.37.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-logfmt/logfmt"
|
||||
packages = ["."]
|
||||
revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-ole/go-ole"
|
||||
packages = [
|
||||
".",
|
||||
"oleutil"
|
||||
]
|
||||
revision = "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506"
|
||||
version = "v1.2.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-redis/redis"
|
||||
packages = [
|
||||
".",
|
||||
"internal",
|
||||
"internal/consistenthash",
|
||||
"internal/hashtag",
|
||||
"internal/pool",
|
||||
"internal/proto",
|
||||
"internal/singleflight",
|
||||
"internal/util"
|
||||
]
|
||||
revision = "83fb42932f6145ce52df09860384a4653d2d332a"
|
||||
version = "v6.12.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
packages = ["."]
|
||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gobwas/glob"
|
||||
packages = [
|
||||
".",
|
||||
"compiler",
|
||||
"match",
|
||||
"syntax",
|
||||
"syntax/ast",
|
||||
"syntax/lexer",
|
||||
"util/runes",
|
||||
"util/strings"
|
||||
]
|
||||
revision = "5ccd90ef52e1e632236f7326478d4faa74f99438"
|
||||
version = "v0.2.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = ["proto"]
|
||||
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"ptypes",
|
||||
"ptypes/any",
|
||||
"ptypes/duration",
|
||||
"ptypes/timestamp"
|
||||
]
|
||||
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/snappy"
|
||||
packages = ["."]
|
||||
revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/google/go-cmp"
|
||||
packages = [
|
||||
"cmp",
|
||||
"cmp/internal/diff",
|
||||
"cmp/internal/function",
|
||||
"cmp/internal/value"
|
||||
]
|
||||
revision = "3af367b6b30c263d47e8895973edcca9a49cf029"
|
||||
version = "v0.2.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/context"
|
||||
packages = ["."]
|
||||
revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gorilla/mux"
|
||||
packages = ["."]
|
||||
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
|
||||
version = "v1.6.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hailocab/go-hostpool"
|
||||
packages = ["."]
|
||||
revision = "e80d13ce29ede4452c43dea11e79b9bc8a15b478"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/hashicorp/consul"
|
||||
packages = ["api"]
|
||||
revision = "5174058f0d2bda63fa5198ab96c33d9a909c58ed"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-cleanhttp"
|
||||
packages = ["."]
|
||||
revision = "d5fe4b57a186c716b0e00b8c301cbd9b4182694d"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-rootcerts"
|
||||
packages = ["."]
|
||||
revision = "6bb64b370b90e7ef1fa532be9e591a81c3493e00"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/hashicorp/serf"
|
||||
packages = ["coordinate"]
|
||||
revision = "d6574a5bb1226678d7010325fb6c985db20ee458"
|
||||
version = "v0.8.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/influxdata/go-syslog"
|
||||
packages = [
|
||||
"rfc5424",
|
||||
"rfc5425"
|
||||
]
|
||||
revision = "eecd51df3ad85464a2bab9b7d3a45bc1e299059e"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/influxdata/tail"
|
||||
packages = [
|
||||
".",
|
||||
"ratelimiter",
|
||||
"util",
|
||||
"watch",
|
||||
"winfile"
|
||||
]
|
||||
revision = "c43482518d410361b6c383d7aebce33d0471d7bc"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/influxdata/toml"
|
||||
packages = [
|
||||
".",
|
||||
"ast"
|
||||
]
|
||||
revision = "2a2e3012f7cfbef64091cc79776311e65dfa211b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/influxdata/wlog"
|
||||
packages = ["."]
|
||||
revision = "7c63b0a71ef8300adc255344d275e10e5c3a71ec"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jackc/pgx"
|
||||
packages = [
|
||||
".",
|
||||
"chunkreader",
|
||||
"internal/sanitize",
|
||||
"pgio",
|
||||
"pgproto3",
|
||||
"pgtype",
|
||||
"stdlib"
|
||||
]
|
||||
revision = "da3231b0b66e2e74cdb779f1d46c5e958ba8be27"
|
||||
version = "v3.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jmespath/go-jmespath"
|
||||
packages = ["."]
|
||||
revision = "0b12d6b5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kardianos/osext"
|
||||
packages = ["."]
|
||||
revision = "ae77be60afb1dcacde03767a8c37337fad28ac14"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kardianos/service"
|
||||
packages = ["."]
|
||||
revision = "615a14ed75099c9eaac6949e22ac2341bf9d3197"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kballard/go-shellquote"
|
||||
packages = ["."]
|
||||
revision = "95032a82bc518f77982ea72343cc1ade730072f0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kr/logfmt"
|
||||
packages = ["."]
|
||||
revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mailru/easyjson"
|
||||
packages = [
|
||||
".",
|
||||
"buffer",
|
||||
"jlexer",
|
||||
"jwriter"
|
||||
]
|
||||
revision = "3fdea8d05856a0c8df22ed4bc71b3219245e4485"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
packages = ["pbutil"]
|
||||
revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/miekg/dns"
|
||||
packages = ["."]
|
||||
revision = "5a2b9fab83ff0f8bfc99684bd5f43a37abe560f1"
|
||||
version = "v1.0.8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/go-homedir"
|
||||
packages = ["."]
|
||||
revision = "3864e76763d94a6df2f9960b16a20a33da9f9a66"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/mapstructure"
|
||||
packages = ["."]
|
||||
revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/multiplay/go-ts3"
|
||||
packages = ["."]
|
||||
revision = "d0d44555495c8776880a17e439399e715a4ef319"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/naoina/go-stringutil"
|
||||
packages = ["."]
|
||||
revision = "6b638e95a32d0c1131db0e7fe83775cbea4a0d0b"
|
||||
version = "v0.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/nats-io/gnatsd"
|
||||
packages = [
|
||||
"conf",
|
||||
"logger",
|
||||
"server",
|
||||
"server/pse",
|
||||
"util"
|
||||
]
|
||||
revision = "add6d7930ae6d4bff8823b28999ea87bf1bfd23d"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/nats-io/go-nats"
|
||||
packages = [
|
||||
".",
|
||||
"encoders/builtin",
|
||||
"util"
|
||||
]
|
||||
revision = "062418ea1c2181f52dc0f954f6204370519a868b"
|
||||
version = "v1.5.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/nats-io/nuid"
|
||||
packages = ["."]
|
||||
revision = "289cccf02c178dc782430d534e3c1f5b72af807f"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/nsqio/go-nsq"
|
||||
packages = ["."]
|
||||
revision = "eee57a3ac4174c55924125bb15eeeda8cffb6e6f"
|
||||
version = "v1.0.7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/opentracing-contrib/go-observer"
|
||||
packages = ["."]
|
||||
revision = "a52f2342449246d5bcc273e65cbdcfa5f7d6c63c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/opentracing/opentracing-go"
|
||||
packages = [
|
||||
".",
|
||||
"ext",
|
||||
"log"
|
||||
]
|
||||
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
|
||||
version = "v1.0.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/openzipkin/zipkin-go-opentracing"
|
||||
packages = [
|
||||
".",
|
||||
"flag",
|
||||
"thrift/gen-go/scribe",
|
||||
"thrift/gen-go/zipkincore",
|
||||
"types",
|
||||
"wire"
|
||||
]
|
||||
revision = "26cf9707480e6b90e5eff22cf0bbf05319154232"
|
||||
version = "v0.3.4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pierrec/lz4"
|
||||
packages = [
|
||||
".",
|
||||
"internal/xxh32"
|
||||
]
|
||||
revision = "6b9367c9ff401dbc54fabce3fb8d972e799b702d"
|
||||
version = "v2.0.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
packages = [
|
||||
"prometheus",
|
||||
"prometheus/promhttp"
|
||||
]
|
||||
revision = "c5b7fccd204277076155f10851dad72b76a49317"
|
||||
version = "v0.8.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/client_model"
|
||||
packages = ["go"]
|
||||
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/common"
|
||||
packages = [
|
||||
"expfmt",
|
||||
"internal/bitbucket.org/ww/goautoneg",
|
||||
"log",
|
||||
"model"
|
||||
]
|
||||
revision = "7600349dcfe1abd18d72d3a1770870d9800a7801"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/prometheus/procfs"
|
||||
packages = [
|
||||
".",
|
||||
"internal/util",
|
||||
"nfs",
|
||||
"xfs"
|
||||
]
|
||||
revision = "7d6f385de8bea29190f15ba9931442a0eaef9af7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/rcrowley/go-metrics"
|
||||
packages = ["."]
|
||||
revision = "e2704e165165ec55d062f5919b4b29494e9fa790"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/samuel/go-zookeeper"
|
||||
packages = ["zk"]
|
||||
revision = "c4fab1ac1bec58281ad0667dc3f0907a9476ac47"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/satori/go.uuid"
|
||||
packages = ["."]
|
||||
revision = "f58768cc1a7a7e77a3bd49e98cdd21419399b6a3"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/shirou/gopsutil"
|
||||
packages = [
|
||||
"cpu",
|
||||
"disk",
|
||||
"host",
|
||||
"internal/common",
|
||||
"load",
|
||||
"mem",
|
||||
"net",
|
||||
"process"
|
||||
]
|
||||
revision = "eeb1d38d69593f121e060d24d17f7b1f0936b203"
|
||||
version = "v2.18.05"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/shirou/w32"
|
||||
packages = ["."]
|
||||
revision = "bb4de0191aa41b5507caa14b0650cdbddcd9280b"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||
version = "v1.0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/soniah/gosnmp"
|
||||
packages = ["."]
|
||||
revision = "bcf840db66be7d64bf96c3c0e075c92e3d98f793"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/streadway/amqp"
|
||||
packages = ["."]
|
||||
revision = "e5adc2ada8b8efff032bf61173a233d143e9318e"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/objx"
|
||||
packages = ["."]
|
||||
revision = "477a77ecc69700c7cdeb1fa9e129548e1c1c393c"
|
||||
version = "v0.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = [
|
||||
"assert",
|
||||
"mock",
|
||||
"require"
|
||||
]
|
||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/tidwall/gjson"
|
||||
packages = ["."]
|
||||
revision = "afaeb9562041a8018c74e006551143666aed08bf"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/tidwall/match"
|
||||
packages = ["."]
|
||||
revision = "1731857f09b1f38450e2c12409748407822dc6be"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/vjeantet/grok"
|
||||
packages = ["."]
|
||||
revision = "ce01e59abcf6fbc9833b7deb5e4b8ee1769bcc53"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/wvanbergen/kafka"
|
||||
packages = ["consumergroup"]
|
||||
revision = "e2edea948ddfee841ea9a263b32ccca15f7d6c2f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/wvanbergen/kazoo-go"
|
||||
packages = ["."]
|
||||
revision = "f72d8611297a7cf105da904c04198ad701a60101"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/yuin/gopher-lua"
|
||||
packages = [
|
||||
".",
|
||||
"ast",
|
||||
"parse",
|
||||
"pm"
|
||||
]
|
||||
revision = "ca850f594eaafa5468da2bd53b865e4ee55be18b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/zensqlmonitor/go-mssqldb"
|
||||
packages = ["."]
|
||||
revision = "e8fbf836e44e86764eba398361d1825651709547"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = [
|
||||
"bcrypt",
|
||||
"blowfish",
|
||||
"ed25519",
|
||||
"ed25519/internal/edwards25519",
|
||||
"md4",
|
||||
"pbkdf2",
|
||||
"ssh/terminal"
|
||||
]
|
||||
revision = "027cca12c2d63e3d62b670d901e8a2c95854feec"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"bpf",
|
||||
"context",
|
||||
"context/ctxhttp",
|
||||
"html",
|
||||
"html/atom",
|
||||
"html/charset",
|
||||
"http/httpguts",
|
||||
"http2",
|
||||
"http2/hpack",
|
||||
"idna",
|
||||
"internal/iana",
|
||||
"internal/socket",
|
||||
"internal/socks",
|
||||
"internal/timeseries",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
"proxy",
|
||||
"trace",
|
||||
"websocket"
|
||||
]
|
||||
revision = "db08ff08e8622530d9ed3a0e8ac279f6d4c02196"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows",
|
||||
"windows/registry",
|
||||
"windows/svc",
|
||||
"windows/svc/debug",
|
||||
"windows/svc/eventlog",
|
||||
"windows/svc/mgr"
|
||||
]
|
||||
revision = "6c888cc515d3ed83fc103cf1d84468aad274b0a7"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"collate",
|
||||
"collate/build",
|
||||
"encoding",
|
||||
"encoding/charmap",
|
||||
"encoding/htmlindex",
|
||||
"encoding/internal",
|
||||
"encoding/internal/identifier",
|
||||
"encoding/japanese",
|
||||
"encoding/korean",
|
||||
"encoding/simplifiedchinese",
|
||||
"encoding/traditionalchinese",
|
||||
"encoding/unicode",
|
||||
"internal/colltab",
|
||||
"internal/gen",
|
||||
"internal/tag",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"internal/utf8internal",
|
||||
"language",
|
||||
"runes",
|
||||
"secure/bidirule",
|
||||
"transform",
|
||||
"unicode/bidi",
|
||||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
"unicode/rangetable"
|
||||
]
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = ["cloudsql"]
|
||||
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "32ee49c4dd805befd833990acba36cb75042378c"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [
|
||||
".",
|
||||
"balancer",
|
||||
"balancer/base",
|
||||
"balancer/roundrobin",
|
||||
"channelz",
|
||||
"codes",
|
||||
"connectivity",
|
||||
"credentials",
|
||||
"encoding",
|
||||
"encoding/proto",
|
||||
"grpclb/grpc_lb_v1/messages",
|
||||
"grpclog",
|
||||
"internal",
|
||||
"keepalive",
|
||||
"metadata",
|
||||
"naming",
|
||||
"peer",
|
||||
"resolver",
|
||||
"resolver/dns",
|
||||
"resolver/passthrough",
|
||||
"stats",
|
||||
"status",
|
||||
"tap",
|
||||
"transport"
|
||||
]
|
||||
revision = "7a6a684ca69eb4cae85ad0a484f2e531598c047b"
|
||||
version = "v1.12.2"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/alecthomas/kingpin.v2"
|
||||
packages = ["."]
|
||||
revision = "947dcec5ba9c011838740e680966fd7087a71d0d"
|
||||
version = "v2.2.6"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/asn1-ber.v1"
|
||||
packages = ["."]
|
||||
revision = "379148ca0225df7a432012b8df0355c2a2063ac0"
|
||||
version = "v1.2"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/fatih/pool.v2"
|
||||
packages = ["."]
|
||||
revision = "010e0b745d12eaf8426c95f9c3924d81dd0b668f"
|
||||
version = "v2.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/fsnotify.v1"
|
||||
packages = ["."]
|
||||
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
|
||||
source = "https://github.com/fsnotify/fsnotify/archive/v1.4.7.tar.gz"
|
||||
version = "v1.4.7"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/gorethink/gorethink.v3"
|
||||
packages = [
|
||||
".",
|
||||
"encoding",
|
||||
"ql2",
|
||||
"types"
|
||||
]
|
||||
revision = "7f5bdfd858bb064d80559b2a32b86669c5de5d3b"
|
||||
version = "v3.0.5"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/ldap.v2"
|
||||
packages = ["."]
|
||||
revision = "bb7a9ca6e4fbc2129e3db588a34bc970ffe811a9"
|
||||
version = "v2.5.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/mgo.v2"
|
||||
packages = [
|
||||
".",
|
||||
"bson",
|
||||
"internal/json",
|
||||
"internal/sasl",
|
||||
"internal/scram"
|
||||
]
|
||||
revision = "3f83fa5005286a7fe593b055f0d7771a7dce4655"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/olivere/elastic.v5"
|
||||
packages = [
|
||||
".",
|
||||
"config",
|
||||
"uritemplates"
|
||||
]
|
||||
revision = "b708306d715bea9b983685e94ab4602cdc9f988b"
|
||||
version = "v5.0.69"
|
||||
|
||||
[[projects]]
|
||||
branch = "v1"
|
||||
name = "gopkg.in/tomb.v1"
|
||||
packages = ["."]
|
||||
revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||
version = "v2.2.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "024194b983d91b9500fe97e0aa0ddb5fe725030cb51ddfb034e386cae1098370"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
243
Gopkg.toml
Normal file
243
Gopkg.toml
Normal file
@@ -0,0 +1,243 @@
|
||||
[[constraint]]
|
||||
name = "collectd.org"
|
||||
version = "0.3.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aerospike/aerospike-client-go"
|
||||
version = "^1.33.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/amir/raidman"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/apache/thrift"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
version = "1.14.8"
|
||||
# version = "1.8.39"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/bsm/sarama-cluster"
|
||||
version = "2.1.13"
|
||||
# version = "2.1.10"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/couchbase/go-couchbase"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/dgrijalva/jwt-go"
|
||||
version = "3.2.0"
|
||||
# version = "3.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/docker/docker"
|
||||
version = "~17.03.2-ce"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/docker/go-connections"
|
||||
version = "0.3.0"
|
||||
# version = "0.2.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/eclipse/paho.mqtt.golang"
|
||||
version = "~1.1.1"
|
||||
# version = "1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
version = "1.4.0"
|
||||
# version = "1.3.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gobwas/glob"
|
||||
version = "0.2.3"
|
||||
# version = "0.2.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/golang/protobuf"
|
||||
version = "1.1.0"
|
||||
# version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/google/go-cmp"
|
||||
version = "0.2.0"
|
||||
# version = "0.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/mux"
|
||||
version = "1.6.2"
|
||||
# version = "1.6.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-redis/redis"
|
||||
version = "6.12.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/hashicorp/consul"
|
||||
version = "1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/influxdata/go-syslog"
|
||||
version = "1.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/influxdata/tail"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/influxdata/toml"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/influxdata/wlog"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/jackc/pgx"
|
||||
version = "3.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/kardianos/service"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/kballard/go-shellquote"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/matttproud/golang_protobuf_extensions"
|
||||
version = "1.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Microsoft/ApplicationInsights-Go"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/miekg/dns"
|
||||
version = "1.0.8"
|
||||
# version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/multiplay/go-ts3"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/nats-io/gnatsd"
|
||||
version = "1.1.0"
|
||||
# version = "1.0.4"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/nats-io/go-nats"
|
||||
version = "1.5.0"
|
||||
# version = "1.3.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/nsqio/go-nsq"
|
||||
version = "1.0.7"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/openzipkin/zipkin-go-opentracing"
|
||||
version = "0.3.4"
|
||||
# version = "0.3.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_golang"
|
||||
version = "0.8.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/client_model"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/prometheus/common"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/satori/go.uuid"
|
||||
version = "1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/shirou/gopsutil"
|
||||
version = "2.18.05"
|
||||
# version = "2.18.04"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Shopify/sarama"
|
||||
version = "1.17.0"
|
||||
# version = "1.15.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/soniah/gosnmp"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/StackExchange/wmi"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/streadway/amqp"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "1.2.2"
|
||||
# version = "1.2.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tidwall/gjson"
|
||||
version = "1.1.1"
|
||||
# version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/vjeantet/grok"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/wvanbergen/kafka"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/zensqlmonitor/go-mssqldb"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "golang.org/x/net"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "golang.org/x/sys"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/grpc"
|
||||
version = "1.12.2"
|
||||
# version = "1.8.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/gorethink/gorethink.v3"
|
||||
version = "3.0.5"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/ldap.v2"
|
||||
version = "2.5.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/mgo.v2"
|
||||
branch = "v2"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/olivere/elastic.v5"
|
||||
version = "^5.0.69"
|
||||
# version = "^6.1.23"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
version = "^2.2.1"
|
||||
|
||||
[[override]]
|
||||
source = "https://github.com/fsnotify/fsnotify/archive/v1.4.7.tar.gz"
|
||||
name = "gopkg.in/fsnotify.v1"
|
||||
29
Makefile
29
Makefile
@@ -23,8 +23,8 @@ all:
|
||||
|
||||
deps:
|
||||
go get -u github.com/golang/lint/golint
|
||||
go get github.com/sparrc/gdm
|
||||
gdm restore --parallel=false
|
||||
go get -u github.com/golang/dep/cmd/dep
|
||||
dep ensure
|
||||
|
||||
telegraf:
|
||||
go build -ldflags "$(LDFLAGS)" ./cmd/telegraf
|
||||
@@ -34,7 +34,7 @@ go-install:
|
||||
|
||||
install: telegraf
|
||||
mkdir -p $(DESTDIR)$(PREFIX)/bin/
|
||||
cp $(TELEGRAF) $(DESTDIR)$(PREFIX)/bin/
|
||||
cp telegraf $(DESTDIR)$(PREFIX)/bin/
|
||||
|
||||
test:
|
||||
go test -short ./...
|
||||
@@ -54,11 +54,11 @@ fmtcheck:
|
||||
@echo '[INFO] done.'
|
||||
|
||||
test-windows:
|
||||
go test ./plugins/inputs/ping/...
|
||||
go test ./plugins/inputs/win_perf_counters/...
|
||||
go test ./plugins/inputs/win_services/...
|
||||
go test ./plugins/inputs/procstat/...
|
||||
go test ./plugins/inputs/ntpq/...
|
||||
go test -short ./plugins/inputs/ping/...
|
||||
go test -short ./plugins/inputs/win_perf_counters/...
|
||||
go test -short ./plugins/inputs/win_services/...
|
||||
go test -short ./plugins/inputs/procstat/...
|
||||
go test -short ./plugins/inputs/ntpq/...
|
||||
|
||||
# vet runs the Go source code static analysis tool `vet` to find
|
||||
# any common errors.
|
||||
@@ -92,4 +92,15 @@ docker-image:
|
||||
plugins/parsers/influx/machine.go: plugins/parsers/influx/machine.go.rl
|
||||
ragel -Z -G2 $^ -o $@
|
||||
|
||||
.PHONY: deps telegraf install test test-windows lint vet test-all package clean docker-image fmtcheck uint64
|
||||
static:
|
||||
@echo "Building static linux binary..."
|
||||
@CGO_ENABLED=0 \
|
||||
GOOS=linux \
|
||||
GOARCH=amd64 \
|
||||
go build -ldflags "$(LDFLAGS)" ./cmd/telegraf
|
||||
|
||||
plugin-%:
|
||||
@echo "Starting dev environment for $${$(@)} input plugin..."
|
||||
@docker-compose -f plugins/inputs/$${$(@)}/dev/docker-compose.yml up
|
||||
|
||||
.PHONY: deps telegraf install test test-windows lint vet test-all package clean docker-image fmtcheck uint64 static
|
||||
|
||||
@@ -40,9 +40,9 @@ Ansible role: https://github.com/rossmcdonald/telegraf
|
||||
|
||||
### From Source:
|
||||
|
||||
Telegraf requires golang version 1.8+, the Makefile requires GNU make.
|
||||
Telegraf requires golang version 1.9 or newer, the Makefile requires GNU make.
|
||||
|
||||
Dependencies are managed with [gdm](https://github.com/sparrc/gdm),
|
||||
Dependencies are managed with [dep](https://github.com/golang/dep),
|
||||
which is installed by the Makefile if you don't have it already.
|
||||
|
||||
1. [Install Go](https://golang.org/doc/install)
|
||||
@@ -213,6 +213,7 @@ configuration options.
|
||||
* [sql server](./plugins/inputs/sqlserver) (microsoft)
|
||||
* [syslog](./plugins/inputs/syslog)
|
||||
* [teamspeak](./plugins/inputs/teamspeak)
|
||||
* [tengine](./plugins/inputs/tengine)
|
||||
* [tomcat](./plugins/inputs/tomcat)
|
||||
* [twemproxy](./plugins/inputs/twemproxy)
|
||||
* [unbound](./plugins/inputs/unbound)
|
||||
@@ -281,6 +282,7 @@ formats may be used with input plugins supporting the `data_format` option:
|
||||
* [basicstats](./plugins/aggregators/basicstats)
|
||||
* [minmax](./plugins/aggregators/minmax)
|
||||
* [histogram](./plugins/aggregators/histogram)
|
||||
* [valuecounter](./plugins/aggregators/valuecounter)
|
||||
|
||||
## Output Plugins
|
||||
|
||||
|
||||
@@ -362,24 +362,6 @@ func (a *Agent) Run(shutdown chan struct{}) error {
|
||||
metricC := make(chan telegraf.Metric, 100)
|
||||
aggC := make(chan telegraf.Metric, 100)
|
||||
|
||||
// Start all ServicePlugins
|
||||
for _, input := range a.Config.Inputs {
|
||||
input.SetDefaultTags(a.Config.Tags)
|
||||
switch p := input.Input.(type) {
|
||||
case telegraf.ServiceInput:
|
||||
acc := NewAccumulator(input, metricC)
|
||||
// Service input plugins should set their own precision of their
|
||||
// metrics.
|
||||
acc.SetPrecision(time.Nanosecond, 0)
|
||||
if err := p.Start(acc); err != nil {
|
||||
log.Printf("E! Service for input %s failed to start, exiting\n%s\n",
|
||||
input.Name(), err.Error())
|
||||
return err
|
||||
}
|
||||
defer p.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// Round collection to nearest interval by sleeping
|
||||
if a.Config.Agent.RoundInterval {
|
||||
i := int64(a.Config.Agent.Interval.Duration)
|
||||
@@ -419,6 +401,25 @@ func (a *Agent) Run(shutdown chan struct{}) error {
|
||||
}(input, interval)
|
||||
}
|
||||
|
||||
// Start all ServicePlugins inputs after all other
|
||||
// plugins are loaded so that no metrics get dropped
|
||||
for _, input := range a.Config.Inputs {
|
||||
input.SetDefaultTags(a.Config.Tags)
|
||||
switch p := input.Input.(type) {
|
||||
case telegraf.ServiceInput:
|
||||
acc := NewAccumulator(input, metricC)
|
||||
// Service input plugins should set their own precision of their
|
||||
// metrics.
|
||||
acc.SetPrecision(time.Nanosecond, 0)
|
||||
if err := p.Start(acc); err != nil {
|
||||
log.Printf("E! Service for input %s failed to start, exiting\n%s\n",
|
||||
input.Name(), err.Error())
|
||||
return err
|
||||
}
|
||||
defer p.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
a.Close()
|
||||
return nil
|
||||
|
||||
@@ -21,6 +21,7 @@ install:
|
||||
- 7z x "C:\Cache\gnuwin32-dep.zip" -oC:\GnuWin32 -y
|
||||
- go version
|
||||
- go env
|
||||
- git config --system core.longpaths true
|
||||
|
||||
build_script:
|
||||
- cmd: C:\GnuWin32\bin\make deps
|
||||
|
||||
@@ -58,7 +58,7 @@ var fService = flag.String("service", "",
|
||||
var fRunAsConsole = flag.Bool("console", false, "run as console application (windows only)")
|
||||
|
||||
var (
|
||||
nextVersion = "1.7.0"
|
||||
nextVersion = "1.8.0"
|
||||
version string
|
||||
commit string
|
||||
branch string
|
||||
@@ -147,11 +147,11 @@ func reloadLoop(
|
||||
|
||||
shutdown := make(chan struct{})
|
||||
signals := make(chan os.Signal)
|
||||
signal.Notify(signals, os.Interrupt, syscall.SIGHUP)
|
||||
signal.Notify(signals, os.Interrupt, syscall.SIGHUP, syscall.SIGTERM)
|
||||
go func() {
|
||||
select {
|
||||
case sig := <-signals:
|
||||
if sig == os.Interrupt {
|
||||
if sig == os.Interrupt || sig == syscall.SIGTERM {
|
||||
close(shutdown)
|
||||
}
|
||||
if sig == syscall.SIGHUP {
|
||||
|
||||
@@ -723,6 +723,10 @@
|
||||
# ## Not used with telnet API.
|
||||
# httpBatchSize = 50
|
||||
#
|
||||
# ## URI Path for Http requests to OpenTSDB.
|
||||
# ## Used in cases where OpenTSDB is located behind a reverse proxy.
|
||||
# httpPath = "/api/put"
|
||||
#
|
||||
# ## Debug true - Prints OpenTSDB communication
|
||||
# debug = false
|
||||
#
|
||||
@@ -1077,7 +1081,7 @@
|
||||
# mount_points = ["/"]
|
||||
|
||||
## Ignore mount points by filesystem type.
|
||||
ignore_fs = ["tmpfs", "devtmpfs", "devfs"]
|
||||
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs"]
|
||||
|
||||
|
||||
# Read metrics about disk IO by device
|
||||
|
||||
@@ -242,7 +242,7 @@
|
||||
#
|
||||
# ## Ignore some mountpoints by filesystem type. For example (dev)tmpfs (usually
|
||||
# ## present on /run, /var/run, /dev/shm or /dev).
|
||||
# # ignore_fs = ["tmpfs", "devtmpfs"]
|
||||
# # ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs"]
|
||||
|
||||
|
||||
# # Read metrics about disk IO by device
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
@@ -193,3 +194,15 @@ func RandomSleep(max time.Duration, shutdown chan struct{}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Exit status takes the error from exec.Command
|
||||
// and returns the exit status and true
|
||||
// if error is not exit status, will return 0 and false
|
||||
func ExitStatus(err error) (int, bool) {
|
||||
if exiterr, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
|
||||
return status.ExitStatus(), true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
@@ -153,6 +154,7 @@ func (r *RunningAggregator) Run(
|
||||
m.Time().After(r.periodEnd.Add(truncation).Add(r.Config.Delay)) {
|
||||
// the metric is outside the current aggregation period, so
|
||||
// skip it.
|
||||
log.Printf("D! aggregator: metric \"%s\" is not in the current timewindow, skipping", m.Name())
|
||||
continue
|
||||
}
|
||||
r.add(m)
|
||||
|
||||
@@ -17,7 +17,7 @@ type ClientConfig struct {
|
||||
// Deprecated in 1.7; use TLS variables above
|
||||
SSLCA string `toml:"ssl_ca"`
|
||||
SSLCert string `toml:"ssl_cert"`
|
||||
SSLKey string `toml:"ssl_ca"`
|
||||
SSLKey string `toml:"ssl_key"`
|
||||
}
|
||||
|
||||
// ServerConfig represents the standard server TLS config.
|
||||
|
||||
@@ -4,4 +4,5 @@ import (
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/basicstats"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/histogram"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/minmax"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/valuecounter"
|
||||
)
|
||||
|
||||
@@ -246,6 +246,8 @@ func convert(in interface{}) (float64, bool) {
|
||||
return v, true
|
||||
case int64:
|
||||
return float64(v), true
|
||||
case uint64:
|
||||
return float64(v), true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ var m2, _ = metric.New("m1",
|
||||
"c": float64(4),
|
||||
"d": float64(6),
|
||||
"e": float64(200),
|
||||
"f": uint64(200),
|
||||
"ignoreme": "string",
|
||||
"andme": true,
|
||||
},
|
||||
@@ -81,6 +82,10 @@ func TestBasicStatsWithPeriod(t *testing.T) {
|
||||
"e_max": float64(200),
|
||||
"e_min": float64(200),
|
||||
"e_mean": float64(200),
|
||||
"f_count": float64(1), //f
|
||||
"f_max": float64(200),
|
||||
"f_min": float64(200),
|
||||
"f_mean": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -144,6 +149,10 @@ func TestBasicStatsDifferentPeriods(t *testing.T) {
|
||||
"e_max": float64(200),
|
||||
"e_min": float64(200),
|
||||
"e_mean": float64(200),
|
||||
"f_count": float64(1), //f
|
||||
"f_max": float64(200),
|
||||
"f_min": float64(200),
|
||||
"f_mean": float64(200),
|
||||
}
|
||||
expectedTags = map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -169,6 +178,7 @@ func TestBasicStatsWithOnlyCount(t *testing.T) {
|
||||
"c_count": float64(2),
|
||||
"d_count": float64(2),
|
||||
"e_count": float64(1),
|
||||
"f_count": float64(1),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -194,6 +204,7 @@ func TestBasicStatsWithOnlyMin(t *testing.T) {
|
||||
"c_min": float64(2),
|
||||
"d_min": float64(2),
|
||||
"e_min": float64(200),
|
||||
"f_min": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -219,6 +230,7 @@ func TestBasicStatsWithOnlyMax(t *testing.T) {
|
||||
"c_max": float64(4),
|
||||
"d_max": float64(6),
|
||||
"e_max": float64(200),
|
||||
"f_max": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -244,6 +256,7 @@ func TestBasicStatsWithOnlyMean(t *testing.T) {
|
||||
"c_mean": float64(3),
|
||||
"d_mean": float64(4),
|
||||
"e_mean": float64(200),
|
||||
"f_mean": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -269,6 +282,7 @@ func TestBasicStatsWithOnlySum(t *testing.T) {
|
||||
"c_sum": float64(6),
|
||||
"d_sum": float64(8),
|
||||
"e_sum": float64(200),
|
||||
"f_sum": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -399,6 +413,8 @@ func TestBasicStatsWithMinAndMax(t *testing.T) {
|
||||
"d_min": float64(2),
|
||||
"e_max": float64(200), //e
|
||||
"e_min": float64(200),
|
||||
"f_max": float64(200), //f
|
||||
"f_min": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -450,6 +466,11 @@ func TestBasicStatsWithAllStats(t *testing.T) {
|
||||
"e_min": float64(200),
|
||||
"e_mean": float64(200),
|
||||
"e_sum": float64(200),
|
||||
"f_count": float64(1), //f
|
||||
"f_max": float64(200),
|
||||
"f_min": float64(200),
|
||||
"f_mean": float64(200),
|
||||
"f_sum": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
|
||||
@@ -107,6 +107,8 @@ func convert(in interface{}) (float64, bool) {
|
||||
return v, true
|
||||
case int64:
|
||||
return float64(v), true
|
||||
case uint64:
|
||||
return float64(v), true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ var m2, _ = metric.New("m1",
|
||||
"i": float64(1),
|
||||
"j": float64(1),
|
||||
"k": float64(200),
|
||||
"l": uint64(200),
|
||||
"ignoreme": "string",
|
||||
"andme": true,
|
||||
},
|
||||
@@ -85,6 +86,8 @@ func TestMinMaxWithPeriod(t *testing.T) {
|
||||
"j_min": float64(1),
|
||||
"k_max": float64(200),
|
||||
"k_min": float64(200),
|
||||
"l_max": float64(200),
|
||||
"l_min": float64(200),
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
@@ -154,6 +157,8 @@ func TestMinMaxDifferentPeriods(t *testing.T) {
|
||||
"j_min": float64(1),
|
||||
"k_max": float64(200),
|
||||
"k_min": float64(200),
|
||||
"l_max": float64(200),
|
||||
"l_min": float64(200),
|
||||
}
|
||||
expectedTags = map[string]string{
|
||||
"foo": "bar",
|
||||
|
||||
73
plugins/aggregators/valuecounter/README.md
Normal file
73
plugins/aggregators/valuecounter/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# ValueCounter Aggregator Plugin
|
||||
|
||||
The valuecounter plugin counts the occurrence of values in fields and emits the
|
||||
counter once every 'period' seconds.
|
||||
|
||||
A use case for the valuecounter plugin is when you are processing a HTTP access
|
||||
log (with the logparser input) and want to count the HTTP status codes.
|
||||
|
||||
The fields which will be counted must be configured with the `fields`
|
||||
configuration directive. When no `fields` is provided the plugin will not count
|
||||
any fields. The results are emitted in fields in the format:
|
||||
`originalfieldname_fieldvalue = count`.
|
||||
|
||||
Valuecounter only works on fields of the type int, bool or string. Float fields
|
||||
are being dropped to prevent the creating of too many fields.
|
||||
|
||||
### Configuration:
|
||||
|
||||
```toml
|
||||
[[aggregators.valuecounter]]
|
||||
## General Aggregator Arguments:
|
||||
## 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
|
||||
## The fields for which the values will be counted
|
||||
fields = ["status"]
|
||||
```
|
||||
|
||||
### Measurements & Fields:
|
||||
|
||||
- measurement1
|
||||
- field_value1
|
||||
- field_value2
|
||||
|
||||
### Tags:
|
||||
|
||||
No tags are applied by this aggregator.
|
||||
|
||||
### Example Output:
|
||||
|
||||
Example for parsing a HTTP access log.
|
||||
|
||||
telegraf.conf:
|
||||
```
|
||||
[[inputs.logparser]]
|
||||
files = ["/tmp/tst.log"]
|
||||
[inputs.logparser.grok]
|
||||
patterns = ['%{DATA:url:tag} %{NUMBER:response:string}']
|
||||
measurement = "access"
|
||||
|
||||
[[aggregators.valuecounter]]
|
||||
namepass = ["access"]
|
||||
fields = ["response"]
|
||||
```
|
||||
|
||||
/tmp/tst.log
|
||||
```
|
||||
/some/path 200
|
||||
/some/path 401
|
||||
/some/path 200
|
||||
```
|
||||
|
||||
```
|
||||
$ telegraf --config telegraf.conf --quiet
|
||||
|
||||
access,url=/some/path,path=/tmp/tst.log,host=localhost.localdomain response="200" 1511948755991487011
|
||||
access,url=/some/path,path=/tmp/tst.log,host=localhost.localdomain response="401" 1511948755991522282
|
||||
access,url=/some/path,path=/tmp/tst.log,host=localhost.localdomain response="200" 1511948755991531697
|
||||
|
||||
access,path=/tmp/tst.log,host=localhost.localdomain,url=/some/path response_200=2i,response_401=1i 1511948761000000000
|
||||
```
|
||||
108
plugins/aggregators/valuecounter/valuecounter.go
Normal file
108
plugins/aggregators/valuecounter/valuecounter.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package valuecounter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/aggregators"
|
||||
)
|
||||
|
||||
type aggregate struct {
|
||||
name string
|
||||
tags map[string]string
|
||||
fieldCount map[string]int
|
||||
}
|
||||
|
||||
// ValueCounter an aggregation plugin
|
||||
type ValueCounter struct {
|
||||
cache map[uint64]aggregate
|
||||
Fields []string
|
||||
}
|
||||
|
||||
// NewValueCounter create a new aggregation plugin which counts the occurances
|
||||
// of fields and emits the count.
|
||||
func NewValueCounter() telegraf.Aggregator {
|
||||
vc := &ValueCounter{}
|
||||
vc.Reset()
|
||||
return vc
|
||||
}
|
||||
|
||||
var sampleConfig = `
|
||||
## General Aggregator Arguments:
|
||||
## 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
|
||||
## The fields for which the values will be counted
|
||||
fields = []
|
||||
`
|
||||
|
||||
// SampleConfig generates a sample config for the ValueCounter plugin
|
||||
func (vc *ValueCounter) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
// Description returns the description of the ValueCounter plugin
|
||||
func (vc *ValueCounter) Description() string {
|
||||
return "Count the occurance of values in fields."
|
||||
}
|
||||
|
||||
// Add is run on every metric which passes the plugin
|
||||
func (vc *ValueCounter) Add(in telegraf.Metric) {
|
||||
id := in.HashID()
|
||||
|
||||
// Check if the cache already has an entry for this metric, if not create it
|
||||
if _, ok := vc.cache[id]; !ok {
|
||||
a := aggregate{
|
||||
name: in.Name(),
|
||||
tags: in.Tags(),
|
||||
fieldCount: make(map[string]int),
|
||||
}
|
||||
vc.cache[id] = a
|
||||
}
|
||||
|
||||
// Check if this metric has fields which we need to count, if so increment
|
||||
// the count.
|
||||
for fk, fv := range in.Fields() {
|
||||
for _, cf := range vc.Fields {
|
||||
if fk == cf {
|
||||
// Do not process float types to prevent memory from blowing up
|
||||
switch fv.(type) {
|
||||
default:
|
||||
log.Printf("I! Valuecounter: Unsupported field type. " +
|
||||
"Must be an int, string or bool. Ignoring.")
|
||||
continue
|
||||
case uint64, int64, string, bool:
|
||||
}
|
||||
fn := fmt.Sprintf("%v_%v", fk, fv)
|
||||
vc.cache[id].fieldCount[fn]++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push emits the counters
|
||||
func (vc *ValueCounter) Push(acc telegraf.Accumulator) {
|
||||
for _, agg := range vc.cache {
|
||||
fields := map[string]interface{}{}
|
||||
|
||||
for field, count := range agg.fieldCount {
|
||||
fields[field] = count
|
||||
}
|
||||
|
||||
acc.AddFields(agg.name, fields, agg.tags)
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the cache, executed after each push
|
||||
func (vc *ValueCounter) Reset() {
|
||||
vc.cache = make(map[uint64]aggregate)
|
||||
}
|
||||
|
||||
func init() {
|
||||
aggregators.Add("valuecounter", func() telegraf.Aggregator {
|
||||
return NewValueCounter()
|
||||
})
|
||||
}
|
||||
126
plugins/aggregators/valuecounter/valuecounter_test.go
Normal file
126
plugins/aggregators/valuecounter/valuecounter_test.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package valuecounter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/metric"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
// Create a valuecounter with config
|
||||
func NewTestValueCounter(fields []string) telegraf.Aggregator {
|
||||
vc := &ValueCounter{
|
||||
Fields: fields,
|
||||
}
|
||||
vc.Reset()
|
||||
|
||||
return vc
|
||||
}
|
||||
|
||||
var m1, _ = metric.New("m1",
|
||||
map[string]string{"foo": "bar"},
|
||||
map[string]interface{}{
|
||||
"status": 200,
|
||||
"somefield": 20.1,
|
||||
"foobar": "bar",
|
||||
},
|
||||
time.Now(),
|
||||
)
|
||||
|
||||
var m2, _ = metric.New("m1",
|
||||
map[string]string{"foo": "bar"},
|
||||
map[string]interface{}{
|
||||
"status": "OK",
|
||||
"ignoreme": "string",
|
||||
"andme": true,
|
||||
"boolfield": false,
|
||||
},
|
||||
time.Now(),
|
||||
)
|
||||
|
||||
func BenchmarkApply(b *testing.B) {
|
||||
vc := NewTestValueCounter([]string{"status"})
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
vc.Add(m1)
|
||||
vc.Add(m2)
|
||||
}
|
||||
}
|
||||
|
||||
// Test basic functionality
|
||||
func TestBasic(t *testing.T) {
|
||||
vc := NewTestValueCounter([]string{"status"})
|
||||
acc := testutil.Accumulator{}
|
||||
|
||||
vc.Add(m1)
|
||||
vc.Add(m2)
|
||||
vc.Add(m1)
|
||||
vc.Push(&acc)
|
||||
|
||||
expectedFields := map[string]interface{}{
|
||||
"status_200": 2,
|
||||
"status_OK": 1,
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "m1", expectedFields, expectedTags)
|
||||
}
|
||||
|
||||
// Test with multiple fields to count
|
||||
func TestMultipleFields(t *testing.T) {
|
||||
vc := NewTestValueCounter([]string{"status", "somefield", "boolfield"})
|
||||
acc := testutil.Accumulator{}
|
||||
|
||||
vc.Add(m1)
|
||||
vc.Add(m2)
|
||||
vc.Add(m2)
|
||||
vc.Add(m1)
|
||||
vc.Push(&acc)
|
||||
|
||||
expectedFields := map[string]interface{}{
|
||||
"status_200": 2,
|
||||
"status_OK": 2,
|
||||
"boolfield_false": 2,
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "m1", expectedFields, expectedTags)
|
||||
}
|
||||
|
||||
// Test with a reset between two runs
|
||||
func TestWithReset(t *testing.T) {
|
||||
vc := NewTestValueCounter([]string{"status"})
|
||||
acc := testutil.Accumulator{}
|
||||
|
||||
vc.Add(m1)
|
||||
vc.Add(m1)
|
||||
vc.Add(m2)
|
||||
vc.Push(&acc)
|
||||
|
||||
expectedFields := map[string]interface{}{
|
||||
"status_200": 2,
|
||||
"status_OK": 1,
|
||||
}
|
||||
expectedTags := map[string]string{
|
||||
"foo": "bar",
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "m1", expectedFields, expectedTags)
|
||||
|
||||
acc.ClearMetrics()
|
||||
vc.Reset()
|
||||
|
||||
vc.Add(m2)
|
||||
vc.Add(m2)
|
||||
vc.Add(m1)
|
||||
vc.Push(&acc)
|
||||
|
||||
expectedFields = map[string]interface{}{
|
||||
"status_200": 1,
|
||||
"status_OK": 2,
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "m1", expectedFields, expectedTags)
|
||||
}
|
||||
@@ -103,6 +103,7 @@ import (
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/tail"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/tcp_listener"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/teamspeak"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/tengine"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/tomcat"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/trig"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/twemproxy"
|
||||
|
||||
@@ -92,6 +92,7 @@ Supported Burrow version: `1.x`
|
||||
- group (string)
|
||||
- topic (string)
|
||||
- partition (int)
|
||||
- owner (string)
|
||||
|
||||
* `burrow_topic`
|
||||
- cluster (string)
|
||||
|
||||
@@ -116,6 +116,7 @@ type (
|
||||
Start apiStatusResponseLagItem `json:"start"`
|
||||
End apiStatusResponseLagItem `json:"end"`
|
||||
CurrentLag int64 `json:"current_lag"`
|
||||
Owner string `json:"owner"`
|
||||
}
|
||||
|
||||
// response: lag field item
|
||||
@@ -447,6 +448,7 @@ func (b *burrow) genGroupLagMetrics(r *apiResponse, cluster, group string, acc t
|
||||
"group": group,
|
||||
"topic": partition.Topic,
|
||||
"partition": strconv.FormatInt(int64(partition.Partition), 10),
|
||||
"owner": partition.Owner,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -129,9 +129,9 @@ func TestBurrowPartition(t *testing.T) {
|
||||
},
|
||||
}
|
||||
tags := []map[string]string{
|
||||
{"cluster": "clustername1", "group": "group1", "topic": "topicA", "partition": "0"},
|
||||
{"cluster": "clustername1", "group": "group1", "topic": "topicA", "partition": "1"},
|
||||
{"cluster": "clustername1", "group": "group1", "topic": "topicA", "partition": "2"},
|
||||
{"cluster": "clustername1", "group": "group1", "topic": "topicA", "partition": "0", "owner": "kafka1"},
|
||||
{"cluster": "clustername1", "group": "group1", "topic": "topicA", "partition": "1", "owner": "kafka2"},
|
||||
{"cluster": "clustername1", "group": "group1", "topic": "topicA", "partition": "2", "owner": "kafka3"},
|
||||
}
|
||||
|
||||
require.Empty(t, acc.Errors)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{
|
||||
"topic": "topicA",
|
||||
"partition": 0,
|
||||
"owner": "kafka",
|
||||
"owner": "kafka1",
|
||||
"status": "OK",
|
||||
"start": {
|
||||
"offset": 431323195,
|
||||
@@ -28,7 +28,7 @@
|
||||
{
|
||||
"topic": "topicA",
|
||||
"partition": 1,
|
||||
"owner": "kafka",
|
||||
"owner": "kafka2",
|
||||
"status": "OK",
|
||||
"start": {
|
||||
"offset": 431322962,
|
||||
@@ -46,7 +46,7 @@
|
||||
{
|
||||
"topic": "topicA",
|
||||
"partition": 2,
|
||||
"owner": "kafka",
|
||||
"owner": "kafka3",
|
||||
"status": "OK",
|
||||
"start": {
|
||||
"offset": 428636563,
|
||||
|
||||
@@ -124,6 +124,7 @@ docker API.
|
||||
- server_version
|
||||
- container_image
|
||||
- container_name
|
||||
- container_status
|
||||
- container_version
|
||||
- fields:
|
||||
- total_pgmafault
|
||||
@@ -167,6 +168,7 @@ docker API.
|
||||
- server_version
|
||||
- container_image
|
||||
- container_name
|
||||
- container_status
|
||||
- container_version
|
||||
- cpu
|
||||
- fields:
|
||||
@@ -186,6 +188,7 @@ docker API.
|
||||
- server_version
|
||||
- container_image
|
||||
- container_name
|
||||
- container_status
|
||||
- container_version
|
||||
- network
|
||||
- fields:
|
||||
@@ -205,6 +208,7 @@ docker API.
|
||||
- server_version
|
||||
- container_image
|
||||
- container_name
|
||||
- container_status
|
||||
- container_version
|
||||
- device
|
||||
- fields:
|
||||
@@ -226,11 +230,27 @@ docker API.
|
||||
- server_version
|
||||
- container_image
|
||||
- container_name
|
||||
- container_status
|
||||
- container_version
|
||||
- fields:
|
||||
- health_status (string)
|
||||
- failing_streak (integer)
|
||||
|
||||
- docker_container_status
|
||||
- tags:
|
||||
- engine_host
|
||||
- server_version
|
||||
- container_image
|
||||
- container_name
|
||||
- container_status
|
||||
- container_version
|
||||
- fields:
|
||||
- oomkilled (boolean)
|
||||
- pid (integer)
|
||||
- exitcode (integer)
|
||||
- started_at (integer)
|
||||
- finished_at (integer)
|
||||
|
||||
- docker_swarm
|
||||
- tags:
|
||||
- service_id
|
||||
@@ -245,12 +265,12 @@ docker API.
|
||||
```
|
||||
docker,engine_host=debian-stretch-docker,server_version=17.09.0-ce n_containers=6i,n_containers_paused=0i,n_containers_running=1i,n_containers_stopped=5i,n_cpus=2i,n_goroutines=41i,n_images=2i,n_listener_events=0i,n_used_file_descriptors=27i 1524002041000000000
|
||||
docker,engine_host=debian-stretch-docker,server_version=17.09.0-ce,unit=bytes memory_total=2101661696i 1524002041000000000
|
||||
docker_container_mem,container_image=telegraf,container_name=zen_ritchie,container_version=unknown,engine_host=debian-stretch-docker,server_version=17.09.0-ce active_anon=8327168i,active_file=2314240i,cache=27402240i,container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",hierarchical_memory_limit=9223372036854771712i,inactive_anon=0i,inactive_file=25088000i,limit=2101661696i,mapped_file=20582400i,max_usage=36646912i,pgfault=4193i,pgmajfault=214i,pgpgin=9243i,pgpgout=520i,rss=8327168i,rss_huge=0i,total_active_anon=8327168i,total_active_file=2314240i,total_cache=27402240i,total_inactive_anon=0i,total_inactive_file=25088000i,total_mapped_file=20582400i,total_pgfault=4193i,total_pgmajfault=214i,total_pgpgin=9243i,total_pgpgout=520i,total_rss=8327168i,total_rss_huge=0i,total_unevictable=0i,total_writeback=0i,unevictable=0i,usage=36528128i,usage_percent=0.4342225020025297,writeback=0i 1524002042000000000
|
||||
docker_container_cpu,container_image=telegraf,container_name=zen_ritchie,container_version=unknown,cpu=cpu-total,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",throttling_periods=0i,throttling_throttled_periods=0i,throttling_throttled_time=0i,usage_in_kernelmode=40000000i,usage_in_usermode=100000000i,usage_percent=0,usage_system=6394210000000i,usage_total=117319068i 1524002042000000000
|
||||
docker_container_cpu,container_image=telegraf,container_name=zen_ritchie,container_version=unknown,cpu=cpu0,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",usage_total=20825265i 1524002042000000000
|
||||
docker_container_cpu,container_image=telegraf,container_name=zen_ritchie,container_version=unknown,cpu=cpu1,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",usage_total=96493803i 1524002042000000000
|
||||
docker_container_net,container_image=telegraf,container_name=zen_ritchie,container_version=unknown,engine_host=debian-stretch-docker,network=eth0,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",rx_bytes=1576i,rx_dropped=0i,rx_errors=0i,rx_packets=20i,tx_bytes=0i,tx_dropped=0i,tx_errors=0i,tx_packets=0i 1524002042000000000
|
||||
docker_container_blkio,container_image=telegraf,container_name=zen_ritchie,container_version=unknown,device=254:0,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",io_service_bytes_recursive_async=27398144i,io_service_bytes_recursive_read=27398144i,io_service_bytes_recursive_sync=0i,io_service_bytes_recursive_total=27398144i,io_service_bytes_recursive_write=0i,io_serviced_recursive_async=529i,io_serviced_recursive_read=529i,io_serviced_recursive_sync=0i,io_serviced_recursive_total=529i,io_serviced_recursive_write=0i 1524002042000000000
|
||||
docker_container_health,container_image=telegraf,container_name=zen_ritchie,container_version=unknown,engine_host=debian-stretch-docker,server_version=17.09.0-ce failing_streak=0i,health_status="healthy" 1524007529000000000
|
||||
docker_container_mem,container_image=telegraf,container_name=zen_ritchie,container_status=running,container_version=unknown,engine_host=debian-stretch-docker,server_version=17.09.0-ce active_anon=8327168i,active_file=2314240i,cache=27402240i,container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",hierarchical_memory_limit=9223372036854771712i,inactive_anon=0i,inactive_file=25088000i,limit=2101661696i,mapped_file=20582400i,max_usage=36646912i,pgfault=4193i,pgmajfault=214i,pgpgin=9243i,pgpgout=520i,rss=8327168i,rss_huge=0i,total_active_anon=8327168i,total_active_file=2314240i,total_cache=27402240i,total_inactive_anon=0i,total_inactive_file=25088000i,total_mapped_file=20582400i,total_pgfault=4193i,total_pgmajfault=214i,total_pgpgin=9243i,total_pgpgout=520i,total_rss=8327168i,total_rss_huge=0i,total_unevictable=0i,total_writeback=0i,unevictable=0i,usage=36528128i,usage_percent=0.4342225020025297,writeback=0i 1524002042000000000
|
||||
docker_container_cpu,container_image=telegraf,container_name=zen_ritchie,container_status=running,container_version=unknown,cpu=cpu-total,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",throttling_periods=0i,throttling_throttled_periods=0i,throttling_throttled_time=0i,usage_in_kernelmode=40000000i,usage_in_usermode=100000000i,usage_percent=0,usage_system=6394210000000i,usage_total=117319068i 1524002042000000000
|
||||
docker_container_cpu,container_image=telegraf,container_name=zen_ritchie,container_status=running,container_version=unknown,cpu=cpu0,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",usage_total=20825265i 1524002042000000000
|
||||
docker_container_cpu,container_image=telegraf,container_name=zen_ritchie,container_status=running,container_version=unknown,cpu=cpu1,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",usage_total=96493803i 1524002042000000000
|
||||
docker_container_net,container_image=telegraf,container_name=zen_ritchie,container_status=running,container_version=unknown,engine_host=debian-stretch-docker,network=eth0,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",rx_bytes=1576i,rx_dropped=0i,rx_errors=0i,rx_packets=20i,tx_bytes=0i,tx_dropped=0i,tx_errors=0i,tx_packets=0i 1524002042000000000
|
||||
docker_container_blkio,container_image=telegraf,container_name=zen_ritchie,container_status=running,container_version=unknown,device=254:0,engine_host=debian-stretch-docker,server_version=17.09.0-ce container_id="adc4ba9593871bf2ab95f3ffde70d1b638b897bb225d21c2c9c84226a10a8cf4",io_service_bytes_recursive_async=27398144i,io_service_bytes_recursive_read=27398144i,io_service_bytes_recursive_sync=0i,io_service_bytes_recursive_total=27398144i,io_service_bytes_recursive_write=0i,io_serviced_recursive_async=529i,io_serviced_recursive_read=529i,io_serviced_recursive_sync=0i,io_serviced_recursive_total=529i,io_serviced_recursive_write=0i 1524002042000000000
|
||||
docker_container_health,container_image=telegraf,container_name=zen_ritchie,container_status=running,container_version=unknown,engine_host=debian-stretch-docker,server_version=17.09.0-ce failing_streak=0i,health_status="healthy" 1524007529000000000
|
||||
docker_swarm,service_id=xaup2o9krw36j2dy1mjx1arjw,service_mode=replicated,service_name=test tasks_desired=3,tasks_running=3 1508968160000000000
|
||||
```
|
||||
|
||||
@@ -435,6 +435,23 @@ func (d *Docker) gatherContainer(
|
||||
}
|
||||
}
|
||||
}
|
||||
if info.State != nil {
|
||||
tags["container_status"] = info.State.Status
|
||||
statefields := map[string]interface{}{
|
||||
"oomkilled": info.State.OOMKilled,
|
||||
"pid": info.State.Pid,
|
||||
"exitcode": info.State.ExitCode,
|
||||
}
|
||||
container_time, err := time.Parse(time.RFC3339, info.State.StartedAt)
|
||||
if err == nil && !container_time.IsZero() {
|
||||
statefields["started_at"] = container_time.UnixNano()
|
||||
}
|
||||
container_time, err = time.Parse(time.RFC3339, info.State.FinishedAt)
|
||||
if err == nil && !container_time.IsZero() {
|
||||
statefields["finished_at"] = container_time.UnixNano()
|
||||
}
|
||||
acc.AddFields("docker_container_status", statefields, tags, time.Now())
|
||||
}
|
||||
|
||||
if info.State.Health != nil {
|
||||
healthfields := map[string]interface{}{
|
||||
|
||||
@@ -653,6 +653,7 @@ func TestDockerGatherInfo(t *testing.T) {
|
||||
"label1": "test_value_1",
|
||||
"label2": "test_value_2",
|
||||
"server_version": "17.09.0-ce",
|
||||
"container_status": "running",
|
||||
},
|
||||
)
|
||||
acc.AssertContainsTaggedFields(t,
|
||||
@@ -676,6 +677,7 @@ func TestDockerGatherInfo(t *testing.T) {
|
||||
"label1": "test_value_1",
|
||||
"label2": "test_value_2",
|
||||
"server_version": "17.09.0-ce",
|
||||
"container_status": "running",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -484,6 +484,12 @@ var containerInspect = types.ContainerJSON{
|
||||
FailingStreak: 1,
|
||||
Status: "Unhealthy",
|
||||
},
|
||||
Status: "running",
|
||||
OOMKilled: false,
|
||||
Pid: 1234,
|
||||
ExitCode: 0,
|
||||
StartedAt: "2018-06-14T05:48:53.266176036Z",
|
||||
FinishedAt: "0001-01-01T00:00:00Z",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@ Those values could be true (1) or false (0) for switches, percentage for dimmers
|
||||
|
||||
- fibaro
|
||||
- tags:
|
||||
- deviceId (device id)
|
||||
- section (section name)
|
||||
- room (room name)
|
||||
- name (device name)
|
||||
- type (device type)
|
||||
- fields:
|
||||
- energy (float, when available from device)
|
||||
- power (float, when available from device)
|
||||
- value (float)
|
||||
- value2 (float, when available from device)
|
||||
|
||||
@@ -36,16 +39,17 @@ Those values could be true (1) or false (0) for switches, percentage for dimmers
|
||||
### Example Output:
|
||||
|
||||
```
|
||||
fibaro,host=vm1,name=Escaliers,room=Dégagement,section=Pièces\ communes,type=com.fibaro.binarySwitch value=0 1523351010000000000
|
||||
fibaro,host=vm1,name=Porte\ fenêtre,room=Salon,section=Pièces\ communes,type=com.fibaro.FGRM222 value=99,value2=99 1523351010000000000
|
||||
fibaro,host=vm1,name=LED\ îlot\ central,room=Cuisine,section=Cuisine,type=com.fibaro.binarySwitch value=0 1523351010000000000
|
||||
fibaro,host=vm1,name=Détérioration,room=Entrée,section=Pièces\ communes,type=com.fibaro.heatDetector value=0 1523351010000000000
|
||||
fibaro,host=vm1,name=Température,room=Cave,section=Cave,type=com.fibaro.temperatureSensor value=17.87 1523351010000000000
|
||||
fibaro,host=vm1,name=Présence,room=Garde-manger,section=Cuisine,type=com.fibaro.FGMS001 value=1 1523351010000000000
|
||||
fibaro,host=vm1,name=Luminosité,room=Garde-manger,section=Cuisine,type=com.fibaro.lightSensor value=92 1523351010000000000
|
||||
fibaro,host=vm1,name=Etat,room=Garage,section=Extérieur,type=com.fibaro.doorSensor value=0 1523351010000000000
|
||||
fibaro,host=vm1,name=CO2\ (ppm),room=Salon,section=Pièces\ communes,type=com.fibaro.multilevelSensor value=880 1523351010000000000
|
||||
fibaro,host=vm1,name=Humidité\ (%),room=Salon,section=Pièces\ communes,type=com.fibaro.humiditySensor value=53 1523351010000000000
|
||||
fibaro,host=vm1,name=Pression\ (mb),room=Salon,section=Pièces\ communes,type=com.fibaro.multilevelSensor value=1006.9 1523351010000000000
|
||||
fibaro,host=vm1,name=Bruit\ (db),room=Salon,section=Pièces\ communes,type=com.fibaro.multilevelSensor value=58 1523351010000000000
|
||||
fibaro,deviceId=9,host=vm1,name=Fenêtre\ haute,room=Cuisine,section=Cuisine,type=com.fibaro.FGRM222 energy=2.04,power=0.7,value=99,value2=99 1529996807000000000
|
||||
fibaro,deviceId=10,host=vm1,name=Escaliers,room=Dégagement,section=Pièces\ communes,type=com.fibaro.binarySwitch value=0 1529996807000000000
|
||||
fibaro,deviceId=13,host=vm1,name=Porte\ fenêtre,room=Salon,section=Pièces\ communes,type=com.fibaro.FGRM222 energy=4.33,power=0.7,value=99,value2=99 1529996807000000000
|
||||
fibaro,deviceId=21,host=vm1,name=LED\ îlot\ central,room=Cuisine,section=Cuisine,type=com.fibaro.binarySwitch value=0 1529996807000000000
|
||||
fibaro,deviceId=90,host=vm1,name=Détérioration,room=Entrée,section=Pièces\ communes,type=com.fibaro.heatDetector value=0 1529996807000000000
|
||||
fibaro,deviceId=163,host=vm1,name=Température,room=Cave,section=Cave,type=com.fibaro.temperatureSensor value=21.62 1529996807000000000
|
||||
fibaro,deviceId=191,host=vm1,name=Présence,room=Garde-manger,section=Cuisine,type=com.fibaro.FGMS001 value=1 1529996807000000000
|
||||
fibaro,deviceId=193,host=vm1,name=Luminosité,room=Garde-manger,section=Cuisine,type=com.fibaro.lightSensor value=195 1529996807000000000
|
||||
fibaro,deviceId=200,host=vm1,name=Etat,room=Garage,section=Extérieur,type=com.fibaro.doorSensor value=0 1529996807000000000
|
||||
fibaro,deviceId=220,host=vm1,name=CO2\ (ppm),room=Salon,section=Pièces\ communes,type=com.fibaro.multilevelSensor value=536 1529996807000000000
|
||||
fibaro,deviceId=221,host=vm1,name=Humidité\ (%),room=Salon,section=Pièces\ communes,type=com.fibaro.humiditySensor value=61 1529996807000000000
|
||||
fibaro,deviceId=222,host=vm1,name=Pression\ (mb),room=Salon,section=Pièces\ communes,type=com.fibaro.multilevelSensor value=1013.7 1529996807000000000
|
||||
fibaro,deviceId=223,host=vm1,name=Bruit\ (db),room=Salon,section=Pièces\ communes,type=com.fibaro.multilevelSensor value=44 1529996807000000000
|
||||
```
|
||||
|
||||
@@ -67,6 +67,8 @@ type Devices struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Properties struct {
|
||||
Dead interface{} `json:"dead"`
|
||||
Energy interface{} `json:"energy"`
|
||||
Power interface{} `json:"power"`
|
||||
Value interface{} `json:"value"`
|
||||
Value2 interface{} `json:"value2"`
|
||||
} `json:"properties"`
|
||||
@@ -162,13 +164,26 @@ func (f *Fibaro) Gather(acc telegraf.Accumulator) error {
|
||||
}
|
||||
|
||||
tags := map[string]string{
|
||||
"section": sections[rooms[device.RoomID].SectionID],
|
||||
"room": rooms[device.RoomID].Name,
|
||||
"name": device.Name,
|
||||
"type": device.Type,
|
||||
"deviceId": strconv.FormatUint(uint64(device.ID), 10),
|
||||
"section": sections[rooms[device.RoomID].SectionID],
|
||||
"room": rooms[device.RoomID].Name,
|
||||
"name": device.Name,
|
||||
"type": device.Type,
|
||||
}
|
||||
fields := make(map[string]interface{})
|
||||
|
||||
if device.Properties.Energy != nil {
|
||||
if fValue, err := strconv.ParseFloat(device.Properties.Energy.(string), 64); err == nil {
|
||||
fields["energy"] = fValue
|
||||
}
|
||||
}
|
||||
|
||||
if device.Properties.Power != nil {
|
||||
if fValue, err := strconv.ParseFloat(device.Properties.Power.(string), 64); err == nil {
|
||||
fields["power"] = fValue
|
||||
}
|
||||
}
|
||||
|
||||
if device.Properties.Value != nil {
|
||||
value := device.Properties.Value
|
||||
switch value {
|
||||
|
||||
@@ -119,6 +119,8 @@ const devicesJSON = `
|
||||
"type": "com.fibaro.FGRM222",
|
||||
"enabled": true,
|
||||
"properties": {
|
||||
"energy": "4.33",
|
||||
"power": "0.7",
|
||||
"dead": "false",
|
||||
"value": "50",
|
||||
"value2": "75"
|
||||
@@ -178,27 +180,27 @@ func TestJSONSuccess(t *testing.T) {
|
||||
assert.Equal(t, uint64(5), acc.NMetrics())
|
||||
|
||||
// Ensure fields / values are correct - Device 1
|
||||
tags := map[string]string{"section": "Section 1", "room": "Room 1", "name": "Device 1", "type": "com.fibaro.binarySwitch"}
|
||||
tags := map[string]string{"deviceId": "1", "section": "Section 1", "room": "Room 1", "name": "Device 1", "type": "com.fibaro.binarySwitch"}
|
||||
fields := map[string]interface{}{"value": float64(0)}
|
||||
acc.AssertContainsTaggedFields(t, "fibaro", fields, tags)
|
||||
|
||||
// Ensure fields / values are correct - Device 2
|
||||
tags = map[string]string{"section": "Section 2", "room": "Room 2", "name": "Device 2", "type": "com.fibaro.binarySwitch"}
|
||||
tags = map[string]string{"deviceId": "2", "section": "Section 2", "room": "Room 2", "name": "Device 2", "type": "com.fibaro.binarySwitch"}
|
||||
fields = map[string]interface{}{"value": float64(1)}
|
||||
acc.AssertContainsTaggedFields(t, "fibaro", fields, tags)
|
||||
|
||||
// Ensure fields / values are correct - Device 3
|
||||
tags = map[string]string{"section": "Section 3", "room": "Room 3", "name": "Device 3", "type": "com.fibaro.multilevelSwitch"}
|
||||
tags = map[string]string{"deviceId": "3", "section": "Section 3", "room": "Room 3", "name": "Device 3", "type": "com.fibaro.multilevelSwitch"}
|
||||
fields = map[string]interface{}{"value": float64(67)}
|
||||
acc.AssertContainsTaggedFields(t, "fibaro", fields, tags)
|
||||
|
||||
// Ensure fields / values are correct - Device 4
|
||||
tags = map[string]string{"section": "Section 3", "room": "Room 4", "name": "Device 4", "type": "com.fibaro.temperatureSensor"}
|
||||
tags = map[string]string{"deviceId": "4", "section": "Section 3", "room": "Room 4", "name": "Device 4", "type": "com.fibaro.temperatureSensor"}
|
||||
fields = map[string]interface{}{"value": float64(22.8)}
|
||||
acc.AssertContainsTaggedFields(t, "fibaro", fields, tags)
|
||||
|
||||
// Ensure fields / values are correct - Device 5
|
||||
tags = map[string]string{"section": "Section 3", "room": "Room 4", "name": "Device 5", "type": "com.fibaro.FGRM222"}
|
||||
fields = map[string]interface{}{"value": float64(50), "value2": float64(75)}
|
||||
tags = map[string]string{"deviceId": "5", "section": "Section 3", "room": "Room 4", "name": "Device 5", "type": "com.fibaro.FGRM222"}
|
||||
fields = map[string]interface{}{"energy": float64(4.33), "power": float64(0.7), "value": float64(50), "value2": float64(75)}
|
||||
acc.AssertContainsTaggedFields(t, "fibaro", fields, tags)
|
||||
}
|
||||
|
||||
@@ -108,7 +108,9 @@ You must capture at least one field per line.
|
||||
- ts-"CUSTOM"
|
||||
|
||||
CUSTOM time layouts must be within quotes and be the representation of the
|
||||
"reference time", which is `Mon Jan 2 15:04:05 -0700 MST 2006`
|
||||
"reference time", which is `Mon Jan 2 15:04:05 -0700 MST 2006`.
|
||||
To match a comma decimal point you can use a period. For example `%{TIMESTAMP:timestamp:ts-"2006-01-02 15:04:05.000"}` can be used to match `"2018-01-02 15:04:05,000"`
|
||||
To match a comma decimal point you can use a period in the pattern string.
|
||||
See https://golang.org/pkg/time/#Parse for more details.
|
||||
|
||||
Telegraf has many of its own [built-in patterns](./grok/patterns/influx-patterns),
|
||||
|
||||
13
plugins/inputs/logparser/dev/docker-compose.yml
Normal file
13
plugins/inputs/logparser/dev/docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
telegraf:
|
||||
image: glinton/scratch
|
||||
volumes:
|
||||
- ./telegraf.conf:/telegraf.conf
|
||||
- ../../../../telegraf:/telegraf
|
||||
- ./test.log:/var/log/test.log
|
||||
entrypoint:
|
||||
- /telegraf
|
||||
- --config
|
||||
- /telegraf.conf
|
||||
12
plugins/inputs/logparser/dev/telegraf.conf
Normal file
12
plugins/inputs/logparser/dev/telegraf.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
[agent]
|
||||
interval="1s"
|
||||
flush_interval="1s"
|
||||
|
||||
[[inputs.logparser]]
|
||||
files = ["/var/log/test.log"]
|
||||
from_beginning = true
|
||||
[inputs.logparser.grok]
|
||||
patterns = [ "%{COMBINED_LOG_FORMAT}", "%{CLIENT:client_ip} %{NOTSPACE:ident} %{NOTSPACE:auth} \\[%{TIMESTAMP_ISO8601:timestamp}\\] \"(?:%{WORD:verb:tag} %{NOTSPACE:request}(?: HTTP/%{NUMBER:http_version:float})?|%{DATA})\" %{NUMBER:resp_code:tag} (?:%{NUMBER:resp_bytes:int}|-) %{QS:referrer} %{QS:agent}"]
|
||||
|
||||
[[outputs.file]]
|
||||
files = ["stdout"]
|
||||
2
plugins/inputs/logparser/dev/test.log
Normal file
2
plugins/inputs/logparser/dev/test.log
Normal file
@@ -0,0 +1,2 @@
|
||||
127.0.0.1 ident auth [10/Oct/2000:13:55:36 -0700] "GET /anything HTTP/1.0" 200 2326 "http://localhost:8083/" "Chrome/51.0.2704.84"
|
||||
127.0.0.1 ident auth [2018-02-21 13:10:34,555] "GET /peter HTTP/1.0" 200 2326 "http://localhost:8083/" "Chrome/51.0.2704.84"
|
||||
@@ -293,7 +293,7 @@ func (p *Parser) ParseLine(line string) (telegraf.Metric, error) {
|
||||
timestamp = time.Unix(0, iv)
|
||||
}
|
||||
case SYSLOG_TIMESTAMP:
|
||||
ts, err := time.ParseInLocation("Jan 02 15:04:05", v, p.loc)
|
||||
ts, err := time.ParseInLocation(time.Stamp, v, p.loc)
|
||||
if err == nil {
|
||||
if ts.Year() == 0 {
|
||||
ts = ts.AddDate(timestamp.Year(), 0, 0)
|
||||
@@ -335,6 +335,9 @@ func (p *Parser) ParseLine(line string) (telegraf.Metric, error) {
|
||||
case DROP:
|
||||
// goodbye!
|
||||
default:
|
||||
// Replace commas with dot character
|
||||
v = strings.Replace(v, ",", ".", -1)
|
||||
|
||||
ts, err := time.ParseInLocation(t, v, p.loc)
|
||||
if err == nil {
|
||||
timestamp = ts
|
||||
|
||||
@@ -971,14 +971,57 @@ func TestNewlineInPatterns(t *testing.T) {
|
||||
require.NotNil(t, m)
|
||||
}
|
||||
|
||||
func TestSyslogTimestampParser(t *testing.T) {
|
||||
p := &Parser{
|
||||
Patterns: []string{`%{SYSLOGTIMESTAMP:timestamp:ts-syslog} value=%{NUMBER:value:int}`},
|
||||
timeFunc: func() time.Time { return time.Date(2018, time.April, 1, 0, 0, 0, 0, nil) },
|
||||
func TestSyslogTimestamp(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
line string
|
||||
expected time.Time
|
||||
}{
|
||||
{
|
||||
name: "two digit day of month",
|
||||
line: "Sep 25 09:01:55 value=42",
|
||||
expected: time.Date(2018, time.September, 25, 9, 1, 55, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
name: "one digit day of month single space",
|
||||
line: "Sep 2 09:01:55 value=42",
|
||||
expected: time.Date(2018, time.September, 2, 9, 1, 55, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
name: "one digit day of month double space",
|
||||
line: "Sep 2 09:01:55 value=42",
|
||||
expected: time.Date(2018, time.September, 2, 9, 1, 55, 0, time.UTC),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := &Parser{
|
||||
Patterns: []string{`%{SYSLOGTIMESTAMP:timestamp:ts-syslog} value=%{NUMBER:value:int}`},
|
||||
timeFunc: func() time.Time { return time.Date(2017, time.April, 1, 0, 0, 0, 0, time.UTC) },
|
||||
}
|
||||
require.NoError(t, p.Compile())
|
||||
m, err := p.ParseLine(tt.line)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, m)
|
||||
require.Equal(t, tt.expected, m.Time())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReplaceTimestampComma(t *testing.T) {
|
||||
|
||||
p := &Parser{
|
||||
Patterns: []string{`%{TIMESTAMP_ISO8601:timestamp:ts-"2006-01-02 15:04:05.000"} successfulMatches=%{NUMBER:value:int}`},
|
||||
}
|
||||
|
||||
require.NoError(t, p.Compile())
|
||||
m, err := p.ParseLine("Sep 25 09:01:55 value=42")
|
||||
m, err := p.ParseLine("2018-02-21 13:10:34,555 successfulMatches=1")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, m)
|
||||
|
||||
require.Equal(t, 2018, m.Time().Year())
|
||||
require.Equal(t, 13, m.Time().Hour())
|
||||
require.Equal(t, 34, m.Time().Second())
|
||||
//Convert Nanosecond to milisecond for compare
|
||||
require.Equal(t, 555, m.Time().Nanosecond()/1000000)
|
||||
}
|
||||
|
||||
@@ -203,6 +203,10 @@ func (l *LogParserPlugin) tailNewfiles(fromBeginning bool) error {
|
||||
Poll: poll,
|
||||
Logger: tail.DiscardingLogger,
|
||||
})
|
||||
|
||||
//add message saying a new tailer was added for the file
|
||||
log.Printf("D! tail added for file: %v", file)
|
||||
|
||||
if err != nil {
|
||||
l.acc.AddError(err)
|
||||
continue
|
||||
@@ -287,6 +291,10 @@ func (l *LogParserPlugin) Stop() {
|
||||
|
||||
for _, t := range l.tailers {
|
||||
err := t.Stop()
|
||||
|
||||
//message for a stopped tailer
|
||||
log.Printf("D! tail dropped for file: %v", t.Filename)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("E! Error stopping tail on file %s\n", t.Filename)
|
||||
}
|
||||
|
||||
16
plugins/inputs/mongodb/dev/docker-compose.yml
Normal file
16
plugins/inputs/mongodb/dev/docker-compose.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
version: '3'
|
||||
services:
|
||||
mongodb:
|
||||
image: mongo
|
||||
|
||||
telegraf:
|
||||
image: glinton/scratch
|
||||
volumes:
|
||||
- ./telegraf.conf:/telegraf.conf
|
||||
- ../../../../telegraf:/telegraf
|
||||
depends_on:
|
||||
- mongodb
|
||||
entrypoint:
|
||||
- /telegraf
|
||||
- --config
|
||||
- /telegraf.conf
|
||||
9
plugins/inputs/mongodb/dev/telegraf.conf
Normal file
9
plugins/inputs/mongodb/dev/telegraf.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
[agent]
|
||||
interval="1s"
|
||||
flush_interval="3s"
|
||||
|
||||
[[inputs.mongodb]]
|
||||
servers = ["mongodb://mongodb:27017"]
|
||||
|
||||
[[outputs.file]]
|
||||
files = ["stdout"]
|
||||
42
plugins/inputs/mysql/dev/docker-compose.yml
Normal file
42
plugins/inputs/mysql/dev/docker-compose.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: telegraf
|
||||
MYSQL_DATABASE: telegraf
|
||||
MYSQL_USER: telegraf
|
||||
MYSQL_PASSWORD: telegraf
|
||||
maria:
|
||||
image: mariadb
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: telegraf
|
||||
MYSQL_DATABASE: telegraf
|
||||
MYSQL_USER: telegraf
|
||||
MYSQL_PASSWORD: telegraf
|
||||
command: mysqld --userstat=1
|
||||
percona:
|
||||
image: percona
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: telegraf
|
||||
MYSQL_DATABASE: telegraf
|
||||
MYSQL_USER: telegraf
|
||||
MYSQL_PASSWORD: telegraf
|
||||
|
||||
telegraf:
|
||||
image: glinton/scratch
|
||||
depends_on:
|
||||
- mysql
|
||||
- maria
|
||||
- percona
|
||||
volumes:
|
||||
- ./telegraf.conf:/telegraf.conf
|
||||
- ../../../../telegraf:/telegraf
|
||||
entrypoint:
|
||||
- /telegraf
|
||||
- --config
|
||||
- /telegraf.conf
|
||||
61
plugins/inputs/mysql/dev/telegraf.conf
Normal file
61
plugins/inputs/mysql/dev/telegraf.conf
Normal file
@@ -0,0 +1,61 @@
|
||||
# Uncomment each input as needed to test plugin
|
||||
|
||||
## mysql
|
||||
#[[inputs.mysql]]
|
||||
# servers = ["root:telegraf@tcp(mysql:3306)/"]
|
||||
# gather_table_schema = true
|
||||
# gather_process_list = true
|
||||
# gather_user_statistics = true
|
||||
# gather_info_schema_auto_inc = true
|
||||
# gather_innodb_metrics = true
|
||||
# gather_slave_status = true
|
||||
# gather_binary_logs = false
|
||||
# gather_table_io_waits = true
|
||||
# gather_table_lock_waits = true
|
||||
# gather_index_io_waits = true
|
||||
# gather_event_waits = true
|
||||
# gather_file_events_stats = true
|
||||
# gather_perf_events_statements = true
|
||||
# interval_slow = "30m"
|
||||
# table_schema_databases = []
|
||||
#
|
||||
## mariadb
|
||||
#[[inputs.mysql]]
|
||||
# servers = ["root:telegraf@tcp(maria:3306)/"]
|
||||
# gather_table_schema = true
|
||||
# gather_process_list = true
|
||||
# gather_user_statistics = true
|
||||
# gather_info_schema_auto_inc = true
|
||||
# gather_innodb_metrics = true
|
||||
# gather_slave_status = true
|
||||
# gather_binary_logs = false
|
||||
# gather_table_io_waits = true
|
||||
# gather_table_lock_waits = true
|
||||
# gather_index_io_waits = true
|
||||
# gather_event_waits = true
|
||||
# gather_file_events_stats = true
|
||||
# gather_perf_events_statements = true
|
||||
# interval_slow = "30m"
|
||||
# table_schema_databases = []
|
||||
|
||||
# percona
|
||||
[[inputs.mysql]]
|
||||
servers = ["root:telegraf@tcp(percona:3306)/"]
|
||||
gather_table_schema = true
|
||||
gather_process_list = true
|
||||
gather_user_statistics = true
|
||||
gather_info_schema_auto_inc = true
|
||||
gather_innodb_metrics = true
|
||||
gather_slave_status = true
|
||||
gather_binary_logs = false
|
||||
gather_table_io_waits = true
|
||||
gather_table_lock_waits = true
|
||||
gather_index_io_waits = true
|
||||
gather_event_waits = true
|
||||
gather_file_events_stats = true
|
||||
gather_perf_events_statements = true
|
||||
interval_slow = "30m"
|
||||
table_schema_databases = []
|
||||
|
||||
[[outputs.file]]
|
||||
files = ["stdout"]
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -80,7 +79,7 @@ var sampleConfig = `
|
||||
## gather thread state counts from INFORMATION_SCHEMA.PROCESSLIST
|
||||
gather_process_list = true
|
||||
#
|
||||
## gather thread state counts from INFORMATION_SCHEMA.USER_STATISTICS
|
||||
## gather user statistics from INFORMATION_SCHEMA.USER_STATISTICS
|
||||
gather_user_statistics = true
|
||||
#
|
||||
## gather auto_increment columns and max values from information schema
|
||||
@@ -282,9 +281,8 @@ const (
|
||||
GROUP BY command,state
|
||||
ORDER BY null`
|
||||
infoSchemaUserStatisticsQuery = `
|
||||
SELECT *,count(*)
|
||||
FROM information_schema.user_statistics
|
||||
GROUP BY user`
|
||||
SELECT *
|
||||
FROM information_schema.user_statistics`
|
||||
infoSchemaAutoIncQuery = `
|
||||
SELECT table_schema, table_name, column_name, auto_increment,
|
||||
CAST(pow(2, case data_type
|
||||
@@ -761,103 +759,6 @@ func (m *Mysql) gatherGlobalStatuses(db *sql.DB, serv string, acc telegraf.Accum
|
||||
if len(fields) > 0 {
|
||||
acc.AddFields("mysql", fields, tags)
|
||||
}
|
||||
// gather connection metrics from processlist for each user
|
||||
if m.GatherProcessList {
|
||||
conn_rows, err := db.Query("SELECT user, sum(1) FROM INFORMATION_SCHEMA.PROCESSLIST GROUP BY user")
|
||||
if err != nil {
|
||||
log.Printf("E! MySQL Error gathering process list: %s", err)
|
||||
} else {
|
||||
for conn_rows.Next() {
|
||||
var user string
|
||||
var connections int64
|
||||
|
||||
err = conn_rows.Scan(&user, &connections)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := map[string]string{"server": servtag, "user": user}
|
||||
fields := make(map[string]interface{})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fields["connections"] = connections
|
||||
acc.AddFields("mysql_users", fields, tags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gather connection metrics from user_statistics for each user
|
||||
if m.GatherUserStatistics {
|
||||
conn_rows, err := db.Query("select user, total_connections, concurrent_connections, connected_time, busy_time, cpu_time, bytes_received, bytes_sent, binlog_bytes_written, rows_fetched, rows_updated, table_rows_read, select_commands, update_commands, other_commands, commit_transactions, rollback_transactions, denied_connections, lost_connections, access_denied, empty_queries, total_ssl_connections FROM INFORMATION_SCHEMA.USER_STATISTICS GROUP BY user")
|
||||
if err != nil {
|
||||
log.Printf("E! MySQL Error gathering user stats: %s", err)
|
||||
} else {
|
||||
for conn_rows.Next() {
|
||||
var user string
|
||||
var total_connections int64
|
||||
var concurrent_connections int64
|
||||
var connected_time int64
|
||||
var busy_time int64
|
||||
var cpu_time int64
|
||||
var bytes_received int64
|
||||
var bytes_sent int64
|
||||
var binlog_bytes_written int64
|
||||
var rows_fetched int64
|
||||
var rows_updated int64
|
||||
var table_rows_read int64
|
||||
var select_commands int64
|
||||
var update_commands int64
|
||||
var other_commands int64
|
||||
var commit_transactions int64
|
||||
var rollback_transactions int64
|
||||
var denied_connections int64
|
||||
var lost_connections int64
|
||||
var access_denied int64
|
||||
var empty_queries int64
|
||||
var total_ssl_connections int64
|
||||
|
||||
err = conn_rows.Scan(&user, &total_connections, &concurrent_connections,
|
||||
&connected_time, &busy_time, &cpu_time, &bytes_received, &bytes_sent, &binlog_bytes_written,
|
||||
&rows_fetched, &rows_updated, &table_rows_read, &select_commands, &update_commands, &other_commands,
|
||||
&commit_transactions, &rollback_transactions, &denied_connections, &lost_connections, &access_denied,
|
||||
&empty_queries, &total_ssl_connections,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := map[string]string{"server": servtag, "user": user}
|
||||
fields := map[string]interface{}{
|
||||
"total_connections": total_connections,
|
||||
"concurrent_connections": concurrent_connections,
|
||||
"connected_time": connected_time,
|
||||
"busy_time": busy_time,
|
||||
"cpu_time": cpu_time,
|
||||
"bytes_received": bytes_received,
|
||||
"bytes_sent": bytes_sent,
|
||||
"binlog_bytes_written": binlog_bytes_written,
|
||||
"rows_fetched": rows_fetched,
|
||||
"rows_updated": rows_updated,
|
||||
"table_rows_read": table_rows_read,
|
||||
"select_commands": select_commands,
|
||||
"update_commands": update_commands,
|
||||
"other_commands": other_commands,
|
||||
"commit_transactions": commit_transactions,
|
||||
"rollback_transactions": rollback_transactions,
|
||||
"denied_connections": denied_connections,
|
||||
"lost_connections": lost_connections,
|
||||
"access_denied": access_denied,
|
||||
"empty_queries": empty_queries,
|
||||
"total_ssl_connections": total_ssl_connections,
|
||||
}
|
||||
|
||||
acc.AddFields("mysql_user_stats", fields, tags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -908,6 +809,29 @@ func (m *Mysql) GatherProcessListStatuses(db *sql.DB, serv string, acc telegraf.
|
||||
} else {
|
||||
acc.AddFields("mysql_process_list", fields, tags)
|
||||
}
|
||||
|
||||
// get count of connections from each user
|
||||
conn_rows, err := db.Query("SELECT user, sum(1) AS connections FROM INFORMATION_SCHEMA.PROCESSLIST GROUP BY user")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for conn_rows.Next() {
|
||||
var user string
|
||||
var connections int64
|
||||
|
||||
err = conn_rows.Scan(&user, &connections)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := map[string]string{"server": servtag, "user": user}
|
||||
fields := make(map[string]interface{})
|
||||
|
||||
fields["connections"] = connections
|
||||
acc.AddFields("mysql_users", fields, tags)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -917,77 +841,190 @@ func (m *Mysql) GatherUserStatisticsStatuses(db *sql.DB, serv string, acc telegr
|
||||
// run query
|
||||
rows, err := db.Query(infoSchemaUserStatisticsQuery)
|
||||
if err != nil {
|
||||
// disable collecting if table is not found (mysql specific error)
|
||||
// (suppresses repeat errors)
|
||||
if strings.Contains(err.Error(), "nknown table 'user_statistics'") {
|
||||
m.GatherUserStatistics = false
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
var (
|
||||
user string
|
||||
total_connections int64
|
||||
concurrent_connections int64
|
||||
connected_time int64
|
||||
busy_time int64
|
||||
cpu_time int64
|
||||
bytes_received int64
|
||||
bytes_sent int64
|
||||
binlog_bytes_written int64
|
||||
rows_fetched int64
|
||||
rows_updated int64
|
||||
table_rows_read int64
|
||||
select_commands int64
|
||||
update_commands int64
|
||||
other_commands int64
|
||||
commit_transactions int64
|
||||
rollback_transactions int64
|
||||
denied_connections int64
|
||||
lost_connections int64
|
||||
access_denied int64
|
||||
empty_queries int64
|
||||
total_ssl_connections int64
|
||||
count uint32
|
||||
)
|
||||
|
||||
cols, err := columnsToLower(rows.Columns())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
read, err := getColSlice(len(cols))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
servtag := getDSNTag(serv)
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&user, &total_connections, &concurrent_connections,
|
||||
&connected_time, &busy_time, &cpu_time, &bytes_received, &bytes_sent, &binlog_bytes_written,
|
||||
&rows_fetched, &rows_updated, &table_rows_read, &select_commands, &update_commands, &other_commands,
|
||||
&commit_transactions, &rollback_transactions, &denied_connections, &lost_connections, &access_denied,
|
||||
&empty_queries, &total_ssl_connections, &count,
|
||||
)
|
||||
err = rows.Scan(read...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tags := map[string]string{"server": servtag, "user": user}
|
||||
fields := map[string]interface{}{
|
||||
tags := map[string]string{"server": servtag, "user": *read[0].(*string)}
|
||||
fields := map[string]interface{}{}
|
||||
|
||||
"total_connections": total_connections,
|
||||
"concurrent_connections": concurrent_connections,
|
||||
"connected_time": connected_time,
|
||||
"busy_time": busy_time,
|
||||
"cpu_time": cpu_time,
|
||||
"bytes_received": bytes_received,
|
||||
"bytes_sent": bytes_sent,
|
||||
"binlog_bytes_written": binlog_bytes_written,
|
||||
"rows_fetched": rows_fetched,
|
||||
"rows_updated": rows_updated,
|
||||
"table_rows_read": table_rows_read,
|
||||
"select_commands": select_commands,
|
||||
"update_commands": update_commands,
|
||||
"other_commands": other_commands,
|
||||
"commit_transactions": commit_transactions,
|
||||
"rollback_transactions": rollback_transactions,
|
||||
"denied_connections": denied_connections,
|
||||
"lost_connections": lost_connections,
|
||||
"access_denied": access_denied,
|
||||
"empty_queries": empty_queries,
|
||||
"total_ssl_connections": total_ssl_connections,
|
||||
for i := range cols {
|
||||
if i == 0 {
|
||||
continue // skip "user"
|
||||
}
|
||||
switch v := read[i].(type) {
|
||||
case *int64:
|
||||
fields[cols[i]] = *v
|
||||
case *float64:
|
||||
fields[cols[i]] = *v
|
||||
case *string:
|
||||
fields[cols[i]] = *v
|
||||
default:
|
||||
return fmt.Errorf("Unknown column type - %T", v)
|
||||
}
|
||||
}
|
||||
acc.AddFields("mysql_user_stats", fields, tags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// columnsToLower converts selected column names to lowercase.
|
||||
func columnsToLower(s []string, e error) ([]string, error) {
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
d := make([]string, len(s))
|
||||
|
||||
for i := range s {
|
||||
d[i] = strings.ToLower(s[i])
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// getColSlice returns an in interface slice that can be used in the row.Scan().
|
||||
func getColSlice(l int) ([]interface{}, error) {
|
||||
// list of all possible column names
|
||||
var (
|
||||
user string
|
||||
total_connections int64
|
||||
concurrent_connections int64
|
||||
connected_time int64
|
||||
busy_time int64
|
||||
cpu_time int64
|
||||
bytes_received int64
|
||||
bytes_sent int64
|
||||
binlog_bytes_written int64
|
||||
rows_read int64
|
||||
rows_sent int64
|
||||
rows_deleted int64
|
||||
rows_inserted int64
|
||||
rows_updated int64
|
||||
select_commands int64
|
||||
update_commands int64
|
||||
other_commands int64
|
||||
commit_transactions int64
|
||||
rollback_transactions int64
|
||||
denied_connections int64
|
||||
lost_connections int64
|
||||
access_denied int64
|
||||
empty_queries int64
|
||||
total_ssl_connections int64
|
||||
max_statement_time_exceeded int64
|
||||
// maria specific
|
||||
fbusy_time float64
|
||||
fcpu_time float64
|
||||
// percona specific
|
||||
rows_fetched int64
|
||||
table_rows_read int64
|
||||
)
|
||||
|
||||
switch l {
|
||||
case 23: // maria5
|
||||
return []interface{}{
|
||||
&user,
|
||||
&total_connections,
|
||||
&concurrent_connections,
|
||||
&connected_time,
|
||||
&fbusy_time,
|
||||
&fcpu_time,
|
||||
&bytes_received,
|
||||
&bytes_sent,
|
||||
&binlog_bytes_written,
|
||||
&rows_read,
|
||||
&rows_sent,
|
||||
&rows_deleted,
|
||||
&rows_inserted,
|
||||
&rows_updated,
|
||||
&select_commands,
|
||||
&update_commands,
|
||||
&other_commands,
|
||||
&commit_transactions,
|
||||
&rollback_transactions,
|
||||
&denied_connections,
|
||||
&lost_connections,
|
||||
&access_denied,
|
||||
&empty_queries,
|
||||
}, nil
|
||||
case 25: // maria10
|
||||
return []interface{}{
|
||||
&user,
|
||||
&total_connections,
|
||||
&concurrent_connections,
|
||||
&connected_time,
|
||||
&fbusy_time,
|
||||
&fcpu_time,
|
||||
&bytes_received,
|
||||
&bytes_sent,
|
||||
&binlog_bytes_written,
|
||||
&rows_read,
|
||||
&rows_sent,
|
||||
&rows_deleted,
|
||||
&rows_inserted,
|
||||
&rows_updated,
|
||||
&select_commands,
|
||||
&update_commands,
|
||||
&other_commands,
|
||||
&commit_transactions,
|
||||
&rollback_transactions,
|
||||
&denied_connections,
|
||||
&lost_connections,
|
||||
&access_denied,
|
||||
&empty_queries,
|
||||
&total_ssl_connections,
|
||||
&max_statement_time_exceeded,
|
||||
}, nil
|
||||
case 22: // percona
|
||||
return []interface{}{
|
||||
&user,
|
||||
&total_connections,
|
||||
&concurrent_connections,
|
||||
&connected_time,
|
||||
&busy_time,
|
||||
&cpu_time,
|
||||
&bytes_received,
|
||||
&bytes_sent,
|
||||
&binlog_bytes_written,
|
||||
&rows_fetched,
|
||||
&rows_updated,
|
||||
&table_rows_read,
|
||||
&select_commands,
|
||||
&update_commands,
|
||||
&other_commands,
|
||||
&commit_transactions,
|
||||
&rollback_transactions,
|
||||
&denied_connections,
|
||||
&lost_connections,
|
||||
&access_denied,
|
||||
&empty_queries,
|
||||
&total_ssl_connections,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Not Supported - %d columns", l)
|
||||
}
|
||||
|
||||
// gatherPerfTableIOWaits can be used to get total count and time
|
||||
// of I/O wait event for each table and process
|
||||
func (m *Mysql) gatherPerfTableIOWaits(db *sql.DB, serv string, acc telegraf.Accumulator) error {
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestMysqlGetDSNTag(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"tcp(localhost)/",
|
||||
"localhost",
|
||||
"localhost:3306",
|
||||
},
|
||||
{
|
||||
"root:passwd@tcp(192.168.1.1:3306)/?tls=false",
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
"github.com/nats-io/nats"
|
||||
nats "github.com/nats-io/go-nats"
|
||||
)
|
||||
|
||||
type natsError struct {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/nats-io/nats"
|
||||
nats "github.com/nats-io/go-nats"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
@@ -17,16 +17,17 @@ This plugin uses a query on the [`nvidia-smi`](https://developer.nvidia.com/nvid
|
||||
### Metrics
|
||||
- measurement: `nvidia_smi`
|
||||
- tags
|
||||
- `name` (type of GPU e.g. `GeForce GTX 170 Ti`)
|
||||
- `name` (type of GPU e.g. `GeForce GTX 1070 Ti`)
|
||||
- `compute_mode` (The compute mode of the GPU e.g. `Default`)
|
||||
- `index` (The port index where the GPU is connected to the motherboard e.g. `1`)
|
||||
- `pstate` (Overclocking state for the GPU e.g. `P0`)
|
||||
- `uuid` (A unique identifier for the GPU e.g. `GPU-f9ba66fc-a7f5-94c5-da19-019ef2f9c665`)
|
||||
- fields
|
||||
- `fan_speed` (integer, percentage)
|
||||
- `memory_free` (integer, KB)
|
||||
- `memory_used` (integer, KB)
|
||||
- `memory_total` (integer, KB)
|
||||
- `memory_free` (integer, MiB)
|
||||
- `memory_used` (integer, MiB)
|
||||
- `memory_total` (integer, MiB)
|
||||
- `power_draw` (float, W)
|
||||
- `temperature_gpu` (integer, degrees C)
|
||||
- `utilization_gpu` (integer, percentage)
|
||||
- `utilization_memory` (integer, percentage)
|
||||
|
||||
@@ -16,20 +16,21 @@ import (
|
||||
|
||||
var (
|
||||
measurement = "nvidia_smi"
|
||||
metrics = "fan.speed,memory.total,memory.used,memory.free,pstate,temperature.gpu,name,uuid,compute_mode,utilization.gpu,utilization.memory,index"
|
||||
metrics = "fan.speed,memory.total,memory.used,memory.free,pstate,temperature.gpu,name,uuid,compute_mode,utilization.gpu,utilization.memory,index,power.draw"
|
||||
metricNames = [][]string{
|
||||
[]string{"fan_speed", "field"},
|
||||
[]string{"memory_total", "field"},
|
||||
[]string{"memory_used", "field"},
|
||||
[]string{"memory_free", "field"},
|
||||
[]string{"fan_speed", "integer"},
|
||||
[]string{"memory_total", "integer"},
|
||||
[]string{"memory_used", "integer"},
|
||||
[]string{"memory_free", "integer"},
|
||||
[]string{"pstate", "tag"},
|
||||
[]string{"temperature_gpu", "field"},
|
||||
[]string{"temperature_gpu", "integer"},
|
||||
[]string{"name", "tag"},
|
||||
[]string{"uuid", "tag"},
|
||||
[]string{"compute_mode", "tag"},
|
||||
[]string{"utilization_gpu", "field"},
|
||||
[]string{"utilization_memory", "field"},
|
||||
[]string{"utilization_gpu", "integer"},
|
||||
[]string{"utilization_memory", "integer"},
|
||||
[]string{"index", "tag"},
|
||||
[]string{"power_draw", "float"},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -127,7 +128,7 @@ func parseLine(line string) (map[string]string, map[string]interface{}, error) {
|
||||
for i, m := range metricNames {
|
||||
col := strings.TrimSpace(met[i])
|
||||
|
||||
// First handle the tags
|
||||
// Handle the tags
|
||||
if m[1] == "tag" {
|
||||
tags[m[0]] = col
|
||||
continue
|
||||
@@ -137,12 +138,23 @@ func parseLine(line string) (map[string]string, map[string]interface{}, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Then parse the integers out of the fields
|
||||
out, err := strconv.ParseInt(col, 10, 64)
|
||||
if err != nil {
|
||||
return tags, fields, err
|
||||
// Parse the integers
|
||||
if m[1] == "integer" {
|
||||
out, err := strconv.ParseInt(col, 10, 64)
|
||||
if err != nil {
|
||||
return tags, fields, err
|
||||
}
|
||||
fields[m[0]] = out
|
||||
}
|
||||
|
||||
// Parse the floats
|
||||
if m[1] == "float" {
|
||||
out, err := strconv.ParseFloat(col, 64)
|
||||
if err != nil {
|
||||
return tags, fields, err
|
||||
}
|
||||
fields[m[0]] = out
|
||||
}
|
||||
fields[m[0]] = out
|
||||
}
|
||||
|
||||
// Return the tags and fields
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func TestParseLineStandard(t *testing.T) {
|
||||
line := "85, 8114, 553, 7561, P2, 61, GeForce GTX 1070 Ti, GPU-d1911b8a-f5c8-5e66-057c-486561269de8, Default, 100, 93, 1\n"
|
||||
line := "85, 8114, 553, 7561, P2, 61, GeForce GTX 1070 Ti, GPU-d1911b8a-f5c8-5e66-057c-486561269de8, Default, 100, 93, 1, 0.0\n"
|
||||
tags, fields, err := parseLine(line)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
@@ -37,7 +37,7 @@ func TestParseLineBad(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestParseLineNotSupported(t *testing.T) {
|
||||
line := "[Not Supported], 7606, 0, 7606, P0, 38, Tesla P4, GPU-xxx, Default, 0, 0, 0\n"
|
||||
line := "[Not Supported], 7606, 0, 7606, P0, 38, Tesla P4, GPU-xxx, Default, 0, 0, 0, 0.0\n"
|
||||
_, fields, err := parseLine(line)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, nil, fields["fan_speed"])
|
||||
|
||||
@@ -14,7 +14,7 @@ To use this plugin you must enable the [monitoring](https://www.openldap.org/dev
|
||||
# ldaps, starttls, or no encryption. default is an empty string, disabling all encryption.
|
||||
# note that port will likely need to be changed to 636 for ldaps
|
||||
# valid options: "" | "starttls" | "ldaps"
|
||||
ssl = ""
|
||||
tls = ""
|
||||
|
||||
# skip peer certificate verification. Default is false.
|
||||
insecure_skip_verify = false
|
||||
|
||||
@@ -15,9 +15,11 @@ import (
|
||||
type Openldap struct {
|
||||
Host string
|
||||
Port int
|
||||
Ssl string
|
||||
SSL string `toml:"ssl"` // Deprecated in 1.7; use TLS
|
||||
TLS string `toml:"tls"`
|
||||
InsecureSkipVerify bool
|
||||
SslCa string
|
||||
SSLCA string `toml:"ssl_ca"` // Deprecated in 1.7; use TLSCA
|
||||
TLSCA string `toml:"tls_ca"`
|
||||
BindDn string
|
||||
BindPassword string
|
||||
ReverseMetricNames bool
|
||||
@@ -30,7 +32,7 @@ const sampleConfig string = `
|
||||
# ldaps, starttls, or no encryption. default is an empty string, disabling all encryption.
|
||||
# note that port will likely need to be changed to 636 for ldaps
|
||||
# valid options: "" | "starttls" | "ldaps"
|
||||
ssl = ""
|
||||
tls = ""
|
||||
|
||||
# skip peer certificate verification. Default is false.
|
||||
insecure_skip_verify = false
|
||||
@@ -70,9 +72,11 @@ func NewOpenldap() *Openldap {
|
||||
return &Openldap{
|
||||
Host: "localhost",
|
||||
Port: 389,
|
||||
Ssl: "",
|
||||
SSL: "",
|
||||
TLS: "",
|
||||
InsecureSkipVerify: false,
|
||||
SslCa: "",
|
||||
SSLCA: "",
|
||||
TLSCA: "",
|
||||
BindDn: "",
|
||||
BindPassword: "",
|
||||
ReverseMetricNames: false,
|
||||
@@ -81,12 +85,19 @@ func NewOpenldap() *Openldap {
|
||||
|
||||
// gather metrics
|
||||
func (o *Openldap) Gather(acc telegraf.Accumulator) error {
|
||||
if o.TLS == "" {
|
||||
o.TLS = o.SSL
|
||||
}
|
||||
if o.TLSCA == "" {
|
||||
o.TLSCA = o.SSLCA
|
||||
}
|
||||
|
||||
var err error
|
||||
var l *ldap.Conn
|
||||
if o.Ssl != "" {
|
||||
if o.TLS != "" {
|
||||
// build tls config
|
||||
clientTLSConfig := tls.ClientConfig{
|
||||
SSLCA: o.SslCa,
|
||||
TLSCA: o.TLSCA,
|
||||
InsecureSkipVerify: o.InsecureSkipVerify,
|
||||
}
|
||||
tlsConfig, err := clientTLSConfig.TLSConfig()
|
||||
@@ -94,13 +105,13 @@ func (o *Openldap) Gather(acc telegraf.Accumulator) error {
|
||||
acc.AddError(err)
|
||||
return nil
|
||||
}
|
||||
if o.Ssl == "ldaps" {
|
||||
if o.TLS == "ldaps" {
|
||||
l, err = ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", o.Host, o.Port), tlsConfig)
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
return nil
|
||||
}
|
||||
} else if o.Ssl == "starttls" {
|
||||
} else if o.TLS == "starttls" {
|
||||
l, err = ldap.Dial("tcp", fmt.Sprintf("%s:%d", o.Host, o.Port))
|
||||
if err != nil {
|
||||
acc.AddError(err)
|
||||
@@ -108,7 +119,7 @@ func (o *Openldap) Gather(acc telegraf.Accumulator) error {
|
||||
}
|
||||
err = l.StartTLS(tlsConfig)
|
||||
} else {
|
||||
acc.AddError(fmt.Errorf("Invalid setting for ssl: %s", o.Ssl))
|
||||
acc.AddError(fmt.Errorf("Invalid setting for ssl: %s", o.TLS))
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package openldap
|
||||
|
||||
import (
|
||||
"gopkg.in/ldap.v2"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/ldap.v2"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -74,7 +75,7 @@ func TestOpenldapStartTLS(t *testing.T) {
|
||||
o := &Openldap{
|
||||
Host: testutil.GetLocalHost(),
|
||||
Port: 389,
|
||||
Ssl: "starttls",
|
||||
SSL: "starttls",
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ func TestOpenldapLDAPS(t *testing.T) {
|
||||
o := &Openldap{
|
||||
Host: testutil.GetLocalHost(),
|
||||
Port: 636,
|
||||
Ssl: "ldaps",
|
||||
SSL: "ldaps",
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ func TestOpenldapInvalidSSL(t *testing.T) {
|
||||
o := &Openldap{
|
||||
Host: testutil.GetLocalHost(),
|
||||
Port: 636,
|
||||
Ssl: "invalid",
|
||||
SSL: "invalid",
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ func TestOpenldapBind(t *testing.T) {
|
||||
o := &Openldap{
|
||||
Host: testutil.GetLocalHost(),
|
||||
Port: 389,
|
||||
Ssl: "",
|
||||
SSL: "",
|
||||
InsecureSkipVerify: true,
|
||||
BindDn: "cn=manager,cn=config",
|
||||
BindPassword: "secret",
|
||||
@@ -157,7 +158,7 @@ func TestOpenldapReverseMetrics(t *testing.T) {
|
||||
o := &Openldap{
|
||||
Host: testutil.GetLocalHost(),
|
||||
Port: 389,
|
||||
Ssl: "",
|
||||
SSL: "",
|
||||
InsecureSkipVerify: true,
|
||||
BindDn: "cn=manager,cn=config",
|
||||
BindPassword: "secret",
|
||||
|
||||
@@ -175,7 +175,7 @@ func (p *Ping) args(url string) []string {
|
||||
}
|
||||
if p.Timeout > 0 {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "freebsd", "netbsd", "openbsd":
|
||||
args = append(args, "-W", strconv.FormatFloat(p.Timeout*1000, 'f', -1, 64))
|
||||
case "linux":
|
||||
args = append(args, "-W", strconv.FormatFloat(p.Timeout, 'f', -1, 64))
|
||||
@@ -186,7 +186,7 @@ func (p *Ping) args(url string) []string {
|
||||
}
|
||||
if p.Deadline > 0 {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "freebsd", "netbsd", "openbsd":
|
||||
args = append(args, "-t", strconv.Itoa(p.Deadline))
|
||||
case "linux":
|
||||
args = append(args, "-w", strconv.Itoa(p.Deadline))
|
||||
@@ -197,10 +197,10 @@ func (p *Ping) args(url string) []string {
|
||||
}
|
||||
if p.Interface != "" {
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "freebsd", "netbsd", "openbsd":
|
||||
args = append(args, "-S", p.Interface)
|
||||
case "linux":
|
||||
args = append(args, "-I", p.Interface)
|
||||
case "freebsd", "darwin":
|
||||
args = append(args, "-S", p.Interface)
|
||||
default:
|
||||
// Not sure the best option here, just assume GNU ping?
|
||||
args = append(args, "-I", p.Interface)
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -28,36 +28,37 @@ func getQueueDirectory() (string, error) {
|
||||
return strings.TrimSpace(string(qd)), nil
|
||||
}
|
||||
|
||||
func qScan(path string) (int64, int64, int64, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
finfos, err := f.Readdir(-1)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
func qScan(path string, acc telegraf.Accumulator) (int64, int64, int64, error) {
|
||||
var length, size int64
|
||||
var oldest time.Time
|
||||
for _, finfo := range finfos {
|
||||
err := filepath.Walk(path, func(_ string, finfo os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("error scanning %s: %s", path, err))
|
||||
return nil
|
||||
}
|
||||
if finfo.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
length++
|
||||
size += finfo.Size()
|
||||
|
||||
ctime := statCTime(finfo.Sys())
|
||||
if ctime.IsZero() {
|
||||
continue
|
||||
return nil
|
||||
}
|
||||
if oldest.IsZero() || ctime.Before(oldest) {
|
||||
oldest = ctime
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
var age int64
|
||||
if !oldest.IsZero() {
|
||||
age = int64(time.Now().Sub(oldest) / time.Second)
|
||||
} else if len(finfos) != 0 {
|
||||
} else if length != 0 {
|
||||
// system doesn't support ctime
|
||||
age = -1
|
||||
}
|
||||
@@ -77,8 +78,8 @@ func (p *Postfix) Gather(acc telegraf.Accumulator) error {
|
||||
}
|
||||
}
|
||||
|
||||
for _, q := range []string{"active", "hold", "incoming", "maildrop"} {
|
||||
length, size, age, err := qScan(path.Join(p.QueueDirectory, q))
|
||||
for _, q := range []string{"active", "hold", "incoming", "maildrop", "deferred"} {
|
||||
length, size, age, err := qScan(filepath.Join(p.QueueDirectory, q), acc)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("error scanning queue %s: %s", q, err))
|
||||
continue
|
||||
@@ -90,30 +91,6 @@ func (p *Postfix) Gather(acc telegraf.Accumulator) error {
|
||||
acc.AddFields("postfix_queue", fields, map[string]string{"queue": q})
|
||||
}
|
||||
|
||||
var dLength, dSize int64
|
||||
dAge := int64(-1)
|
||||
for _, q := range []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"} {
|
||||
length, size, age, err := qScan(path.Join(p.QueueDirectory, "deferred", q))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
// the directories are created on first use
|
||||
continue
|
||||
}
|
||||
acc.AddError(fmt.Errorf("error scanning queue deferred/%s: %s", q, err))
|
||||
return nil
|
||||
}
|
||||
dLength += length
|
||||
dSize += size
|
||||
if age > dAge {
|
||||
dAge = age
|
||||
}
|
||||
}
|
||||
fields := map[string]interface{}{"length": dLength, "size": dSize}
|
||||
if dAge != -1 {
|
||||
fields["age"] = dAge
|
||||
}
|
||||
acc.AddFields("postfix_queue", fields, map[string]string{"queue": "deferred"})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package postfix
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
@@ -16,19 +16,16 @@ func TestGather(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
for _, q := range []string{"active", "hold", "incoming", "maildrop", "deferred"} {
|
||||
require.NoError(t, os.Mkdir(path.Join(td, q), 0755))
|
||||
}
|
||||
for _, q := range []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "F"} { // "E" deliberately left off
|
||||
require.NoError(t, os.Mkdir(path.Join(td, "deferred", q), 0755))
|
||||
for _, q := range []string{"active", "hold", "incoming", "maildrop", "deferred/0/0", "deferred/F/F"} {
|
||||
require.NoError(t, os.MkdirAll(filepath.FromSlash(td+"/"+q), 0755))
|
||||
}
|
||||
|
||||
require.NoError(t, ioutil.WriteFile(path.Join(td, "active", "01"), []byte("abc"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(path.Join(td, "active", "02"), []byte("defg"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(path.Join(td, "hold", "01"), []byte("abc"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(path.Join(td, "incoming", "01"), []byte("abcd"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(path.Join(td, "deferred", "0", "01"), []byte("abc"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(path.Join(td, "deferred", "F", "F1"), []byte("abc"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.FromSlash(td+"/active/01"), []byte("abc"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.FromSlash(td+"/active/02"), []byte("defg"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.FromSlash(td+"/hold/01"), []byte("abc"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.FromSlash(td+"/incoming/01"), []byte("abcd"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.FromSlash(td+"/deferred/0/0/01"), []byte("abc"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.FromSlash(td+"/deferred/F/F/F1"), []byte("abc"), 0644))
|
||||
|
||||
p := Postfix{
|
||||
QueueDirectory: td,
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
)
|
||||
|
||||
// Implemention of PIDGatherer that execs pgrep to find processes
|
||||
@@ -62,6 +64,12 @@ func find(path string, args []string) ([]PID, error) {
|
||||
|
||||
func run(path string, args []string) (string, error) {
|
||||
out, err := exec.Command(path, args...).Output()
|
||||
|
||||
//if exit code 1, ie no processes found, do not return error
|
||||
if i, _ := internal.ExitStatus(err); i == 1 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error running %s: %s", path, err)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ func (p *Procstat) Gather(acc telegraf.Accumulator) error {
|
||||
p.createProcess = defaultProcess
|
||||
}
|
||||
|
||||
procs, err := p.updateProcesses(p.procs)
|
||||
procs, err := p.updateProcesses(acc, p.procs)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("E! Error: procstat getting process, exe: [%s] pidfile: [%s] pattern: [%s] user: [%s] %s",
|
||||
p.Exe, p.PidFile, p.Pattern, p.User, err.Error()))
|
||||
@@ -230,8 +230,8 @@ func (p *Procstat) addMetrics(proc Process, acc telegraf.Accumulator) {
|
||||
}
|
||||
|
||||
// Update monitored Processes
|
||||
func (p *Procstat) updateProcesses(prevInfo map[PID]Process) (map[PID]Process, error) {
|
||||
pids, tags, err := p.findPids()
|
||||
func (p *Procstat) updateProcesses(acc telegraf.Accumulator, prevInfo map[PID]Process) (map[PID]Process, error) {
|
||||
pids, tags, err := p.findPids(acc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -281,9 +281,9 @@ func (p *Procstat) getPIDFinder() (PIDFinder, error) {
|
||||
}
|
||||
|
||||
// Get matching PIDs and their initial tags
|
||||
func (p *Procstat) findPids() ([]PID, map[string]string, error) {
|
||||
func (p *Procstat) findPids(acc telegraf.Accumulator) ([]PID, map[string]string, error) {
|
||||
var pids []PID
|
||||
var tags map[string]string
|
||||
tags := make(map[string]string)
|
||||
var err error
|
||||
|
||||
f, err := p.getPIDFinder()
|
||||
@@ -313,7 +313,18 @@ func (p *Procstat) findPids() ([]PID, map[string]string, error) {
|
||||
err = fmt.Errorf("Either exe, pid_file, user, pattern, systemd_unit, or cgroup must be specified")
|
||||
}
|
||||
|
||||
return pids, tags, err
|
||||
rTags := make(map[string]string)
|
||||
for k, v := range tags {
|
||||
rTags[k] = v
|
||||
}
|
||||
|
||||
//adds a metric with info on the pgrep query
|
||||
fields := make(map[string]interface{})
|
||||
tags["pid_finder"] = p.PidFinder
|
||||
fields["pid_count"] = len(pids)
|
||||
acc.AddFields("procstat_lookup", fields, tags)
|
||||
|
||||
return pids, rTags, err
|
||||
}
|
||||
|
||||
// execCommand is so tests can mock out exec.Command usage.
|
||||
|
||||
@@ -343,7 +343,8 @@ func TestGather_systemdUnitPIDs(t *testing.T) {
|
||||
createPIDFinder: pidFinder([]PID{}, nil),
|
||||
SystemdUnit: "TestGather_systemdUnitPIDs",
|
||||
}
|
||||
pids, tags, err := p.findPids()
|
||||
var acc testutil.Accumulator
|
||||
pids, tags, err := p.findPids(&acc)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []PID{11408}, pids)
|
||||
assert.Equal(t, "TestGather_systemdUnitPIDs", tags["systemd_unit"])
|
||||
@@ -364,8 +365,20 @@ func TestGather_cgroupPIDs(t *testing.T) {
|
||||
createPIDFinder: pidFinder([]PID{}, nil),
|
||||
CGroup: td,
|
||||
}
|
||||
pids, tags, err := p.findPids()
|
||||
var acc testutil.Accumulator
|
||||
pids, tags, err := p.findPids(&acc)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []PID{1234, 5678}, pids)
|
||||
assert.Equal(t, td, tags["cgroup"])
|
||||
}
|
||||
|
||||
func TestProcstatLookupMetric(t *testing.T) {
|
||||
p := Procstat{
|
||||
createPIDFinder: pidFinder([]PID{543}, nil),
|
||||
Exe: "-Gsys",
|
||||
}
|
||||
var acc testutil.Accumulator
|
||||
err := acc.GatherError(p.Gather)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(p.procs)+1, len(acc.Metrics))
|
||||
}
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
## If no servers are specified, then localhost is used as the host.
|
||||
## If no port is specified, 6379 is used
|
||||
servers = ["tcp://localhost:6379"]
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## Use TLS but skip chain & host verification
|
||||
# insecure_skip_verify = true
|
||||
```
|
||||
|
||||
### Measurements & Fields:
|
||||
|
||||
@@ -13,11 +13,13 @@ import (
|
||||
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal/tls"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
type Redis struct {
|
||||
Servers []string
|
||||
tls.ClientConfig
|
||||
|
||||
clients []Client
|
||||
initialized bool
|
||||
@@ -56,6 +58,13 @@ var sampleConfig = `
|
||||
## If no servers are specified, then localhost is used as the host.
|
||||
## If no port is specified, 6379 is used
|
||||
servers = ["tcp://localhost:6379"]
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## Use TLS but skip chain & host verification
|
||||
# insecure_skip_verify = true
|
||||
`
|
||||
|
||||
func (r *Redis) SampleConfig() string {
|
||||
@@ -109,12 +118,18 @@ func (r *Redis) init(acc telegraf.Accumulator) error {
|
||||
address = u.Host
|
||||
}
|
||||
|
||||
tlsConfig, err := r.ClientConfig.TLSConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := redis.NewClient(
|
||||
&redis.Options{
|
||||
Addr: address,
|
||||
Password: password,
|
||||
Network: u.Scheme,
|
||||
PoolSize: 1,
|
||||
Addr: address,
|
||||
Password: password,
|
||||
Network: u.Scheme,
|
||||
PoolSize: 1,
|
||||
TLSConfig: tlsConfig,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ The [solr](http://lucene.apache.org/solr/) plugin collects stats via the
|
||||
|
||||
More about [performance statistics](https://cwiki.apache.org/confluence/display/solr/Performance+Statistics+Reference)
|
||||
|
||||
Tested from 3.5 to 6.*
|
||||
Tested from 3.5 to 7.*
|
||||
|
||||
### Configuration:
|
||||
|
||||
|
||||
@@ -113,20 +113,7 @@ type Hitratio interface{}
|
||||
// Cache is an exported type that
|
||||
// contains cache metrics
|
||||
type Cache struct {
|
||||
Stats struct {
|
||||
CumulativeEvictions int64 `json:"cumulative_evictions"`
|
||||
CumulativeHitratio Hitratio `json:"cumulative_hitratio"`
|
||||
CumulativeHits int64 `json:"cumulative_hits"`
|
||||
CumulativeInserts int64 `json:"cumulative_inserts"`
|
||||
CumulativeLookups int64 `json:"cumulative_lookups"`
|
||||
Evictions int64 `json:"evictions"`
|
||||
Hitratio Hitratio `json:"hitratio"`
|
||||
Hits int64 `json:"hits"`
|
||||
Inserts int64 `json:"inserts"`
|
||||
Lookups int64 `json:"lookups"`
|
||||
Size int64 `json:"size"`
|
||||
WarmupTime int64 `json:"warmupTime"`
|
||||
} `json:"stats"`
|
||||
Stats map[string]interface{} `json:"stats"`
|
||||
}
|
||||
|
||||
// NewSolr return a new instance of Solr
|
||||
@@ -424,21 +411,30 @@ func addCacheMetricsToAcc(acc telegraf.Accumulator, core string, mBeansData *MBe
|
||||
return err
|
||||
}
|
||||
for name, metrics := range cacheMetrics {
|
||||
cumulativeHits := getFloat(metrics.Stats.CumulativeHitratio)
|
||||
hitratio := getFloat(metrics.Stats.Hitratio)
|
||||
coreFields := map[string]interface{}{
|
||||
"cumulative_evictions": metrics.Stats.CumulativeEvictions,
|
||||
"cumulative_hitratio": cumulativeHits,
|
||||
"cumulative_hits": metrics.Stats.CumulativeHits,
|
||||
"cumulative_inserts": metrics.Stats.CumulativeInserts,
|
||||
"cumulative_lookups": metrics.Stats.CumulativeLookups,
|
||||
"evictions": metrics.Stats.Evictions,
|
||||
"hitratio": hitratio,
|
||||
"hits": metrics.Stats.Hits,
|
||||
"inserts": metrics.Stats.Inserts,
|
||||
"lookups": metrics.Stats.Lookups,
|
||||
"size": metrics.Stats.Size,
|
||||
"warmup_time": metrics.Stats.WarmupTime,
|
||||
coreFields := make(map[string]interface{})
|
||||
for key, value := range metrics.Stats {
|
||||
splitKey := strings.Split(key, ".")
|
||||
newKey := splitKey[len(splitKey)-1]
|
||||
switch newKey {
|
||||
case "cumulative_evictions",
|
||||
"cumulative_hits",
|
||||
"cumulative_inserts",
|
||||
"cumulative_lookups",
|
||||
"eviction",
|
||||
"hits",
|
||||
"inserts",
|
||||
"lookups",
|
||||
"size",
|
||||
"evictions":
|
||||
coreFields[newKey] = getInt(value)
|
||||
case "hitratio",
|
||||
"cumulative_hitratio":
|
||||
coreFields[newKey] = getFloat(value)
|
||||
case "warmupTime":
|
||||
coreFields["warmup_time"] = getInt(value)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
acc.AddFields(
|
||||
"solr_cache",
|
||||
|
||||
@@ -43,6 +43,17 @@ func TestGatherStats(t *testing.T) {
|
||||
map[string]string{"core": "main", "handler": "filterCache"})
|
||||
}
|
||||
|
||||
func TestSolr7MbeansStats(t *testing.T) {
|
||||
ts := createMockSolr7Server()
|
||||
solr := NewSolr()
|
||||
solr.Servers = []string{ts.URL}
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, solr.Gather(&acc))
|
||||
acc.AssertContainsTaggedFields(t, "solr_cache",
|
||||
solr7CacheExpected,
|
||||
map[string]string{"core": "main", "handler": "documentCache"})
|
||||
}
|
||||
|
||||
func TestSolr3GatherStats(t *testing.T) {
|
||||
ts := createMockSolr3Server()
|
||||
solr := NewSolr()
|
||||
@@ -150,3 +161,18 @@ func createMockSolr3Server() *httptest.Server {
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func createMockSolr7Server() *httptest.Server {
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.Contains(r.URL.Path, "/solr/admin/cores") {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, statusResponse)
|
||||
} else if strings.Contains(r.URL.Path, "solr/main/admin") {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, mBeansSolr7Response)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
fmt.Fprintln(w, "nope")
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
60
plugins/inputs/solr/testdata7_test.go
Normal file
60
plugins/inputs/solr/testdata7_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package solr
|
||||
|
||||
const mBeansSolr7Response = `
|
||||
{
|
||||
"responseHeader":{
|
||||
"status":0,
|
||||
"QTime":2
|
||||
},
|
||||
"solr-mbeans":[
|
||||
"CORE",
|
||||
{
|
||||
|
||||
},
|
||||
"QUERYHANDLER",
|
||||
{
|
||||
|
||||
},
|
||||
"UPDATEHANDLER",
|
||||
{
|
||||
|
||||
},
|
||||
"CACHE",
|
||||
{
|
||||
"documentCache":{
|
||||
"class":"org.apache.solr.search.LRUCache",
|
||||
"description":"LRU Cache(maxSize=16384, initialSize=4096)",
|
||||
"stats":{
|
||||
"CACHE.searcher.documentCache.evictions": 141485,
|
||||
"CACHE.searcher.documentCache.cumulative_lookups": 265132,
|
||||
"CACHE.searcher.documentCache.hitratio": 0.44,
|
||||
"CACHE.searcher.documentCache.size": 8192,
|
||||
"CACHE.searcher.documentCache.cumulative_hitratio": 0.42,
|
||||
"CACHE.searcher.documentCache.lookups": 1234,
|
||||
"CACHE.searcher.documentCache.warmupTime": 1,
|
||||
"CACHE.searcher.documentCache.inserts": 987,
|
||||
"CACHE.searcher.documentCache.hits": 1111,
|
||||
"CACHE.searcher.documentCache.cumulative_hits": 115364,
|
||||
"CACHE.searcher.documentCache.cumulative_inserts": 149768,
|
||||
"CACHE.searcher.documentCache.cumulative_evictions": 141486
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
var solr7CacheExpected = map[string]interface{}{
|
||||
"evictions": int64(141485),
|
||||
"cumulative_evictions": int64(141486),
|
||||
"cumulative_hitratio": float64(0.42),
|
||||
"cumulative_hits": int64(115364),
|
||||
"cumulative_inserts": int64(149768),
|
||||
"cumulative_lookups": int64(265132),
|
||||
"hitratio": float64(0.44),
|
||||
"hits": int64(1111),
|
||||
"inserts": int64(987),
|
||||
"lookups": int64(1234),
|
||||
"size": int64(8192),
|
||||
"warmup_time": int64(1),
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package syslog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -279,20 +280,51 @@ func (s *Syslog) handle(conn net.Conn, acc telegraf.Accumulator) {
|
||||
conn.Close()
|
||||
}()
|
||||
|
||||
if s.ReadTimeout != nil && s.ReadTimeout.Duration > 0 {
|
||||
conn.SetReadDeadline(time.Now().Add(s.ReadTimeout.Duration))
|
||||
}
|
||||
for {
|
||||
data := &bytes.Buffer{}
|
||||
|
||||
var p *rfc5425.Parser
|
||||
if s.BestEffort {
|
||||
p = rfc5425.NewParser(conn, rfc5425.WithBestEffort())
|
||||
} else {
|
||||
p = rfc5425.NewParser(conn)
|
||||
}
|
||||
// read the data
|
||||
if s.ReadTimeout != nil && s.ReadTimeout.Duration > 0 {
|
||||
conn.SetReadDeadline(time.Now().Add(s.ReadTimeout.Duration))
|
||||
}
|
||||
|
||||
p.ParseExecuting(func(r *rfc5425.Result) {
|
||||
s.store(*r, acc)
|
||||
})
|
||||
n, err := io.Copy(data, conn)
|
||||
if err != nil {
|
||||
// read timeout reached, parse what we have
|
||||
if er, ok := err.(net.Error); ok && er.Timeout() {
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
goto parseMsg
|
||||
}
|
||||
// client has closed connection, return
|
||||
if err == io.EOF {
|
||||
if n > 0 {
|
||||
goto parseMsg
|
||||
}
|
||||
return
|
||||
}
|
||||
// other error, log and return
|
||||
s.store(rfc5425.Result{Error: fmt.Errorf("failed reading from syslog client - %s", err.Error())}, acc)
|
||||
return
|
||||
}
|
||||
// handle client disconnect
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
parseMsg:
|
||||
var p *rfc5425.Parser
|
||||
if s.BestEffort {
|
||||
p = rfc5425.NewParser(data, rfc5425.WithBestEffort())
|
||||
} else {
|
||||
p = rfc5425.NewParser(data)
|
||||
}
|
||||
|
||||
p.ParseExecuting(func(r *rfc5425.Result) {
|
||||
s.store(*r, acc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Syslog) setKeepAlive(c *net.TCPConn) error {
|
||||
@@ -361,7 +393,7 @@ func fields(msg rfc5424.SyslogMessage, s *Syslog) map[string]interface{} {
|
||||
}
|
||||
|
||||
if msg.Message() != nil {
|
||||
flds["message"] = *msg.Message()
|
||||
flds["message"] = strings.TrimSpace(*msg.Message())
|
||||
}
|
||||
|
||||
if msg.StructuredData() != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ https://en.wikipedia.org/wiki/Df_(Unix) for more details.
|
||||
# mount_points = ["/"]
|
||||
|
||||
## Ignore mount points by filesystem type.
|
||||
ignore_fs = ["tmpfs", "devtmpfs", "devfs"]
|
||||
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs"]
|
||||
```
|
||||
|
||||
#### Docker container
|
||||
|
||||
30
plugins/inputs/system/SWAP_README.md
Normal file
30
plugins/inputs/system/SWAP_README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Swap Input Plugin
|
||||
|
||||
The swap plugin collects system swap metrics.
|
||||
|
||||
For a more information on what swap memory is, read [All about Linux swap space](https://www.linux.com/news/all-about-linux-swap-space).
|
||||
|
||||
### Configuration:
|
||||
|
||||
```toml
|
||||
# Read metrics about swap memory usage
|
||||
[[inputs.swap]]
|
||||
# no configuration
|
||||
```
|
||||
|
||||
### Metrics:
|
||||
|
||||
- swap
|
||||
- fields:
|
||||
- free (int)
|
||||
- total (int)
|
||||
- used (int)
|
||||
- used_percent (float)
|
||||
- in (int)
|
||||
- out (int)
|
||||
|
||||
### Example Output:
|
||||
|
||||
```
|
||||
swap total=20855394304i,used_percent=45.43883523785713,used=9476448256i,free=1715331072i 1511894782000000000
|
||||
```
|
||||
@@ -28,7 +28,7 @@ var diskSampleConfig = `
|
||||
# mount_points = ["/"]
|
||||
|
||||
## Ignore mount points by filesystem type.
|
||||
ignore_fs = ["tmpfs", "devtmpfs", "devfs"]
|
||||
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs"]
|
||||
`
|
||||
|
||||
func (_ *DiskStats) SampleConfig() string {
|
||||
|
||||
@@ -42,45 +42,9 @@ func (s *MemStats) Gather(acc telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type SwapStats struct {
|
||||
ps PS
|
||||
}
|
||||
|
||||
func (_ *SwapStats) Description() string {
|
||||
return "Read metrics about swap memory usage"
|
||||
}
|
||||
|
||||
func (_ *SwapStats) SampleConfig() string { return "" }
|
||||
|
||||
func (s *SwapStats) Gather(acc telegraf.Accumulator) error {
|
||||
swap, err := s.ps.SwapStat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting swap memory info: %s", err)
|
||||
}
|
||||
|
||||
fieldsG := map[string]interface{}{
|
||||
"total": swap.Total,
|
||||
"used": swap.Used,
|
||||
"free": swap.Free,
|
||||
"used_percent": swap.UsedPercent,
|
||||
}
|
||||
fieldsC := map[string]interface{}{
|
||||
"in": swap.Sin,
|
||||
"out": swap.Sout,
|
||||
}
|
||||
acc.AddGauge("swap", fieldsG, nil)
|
||||
acc.AddCounter("swap", fieldsC, nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
ps := newSystemPS()
|
||||
inputs.Add("mem", func() telegraf.Input {
|
||||
return &MemStats{ps: ps}
|
||||
})
|
||||
|
||||
inputs.Add("swap", func() telegraf.Input {
|
||||
return &SwapStats{ps: ps}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -30,17 +30,6 @@ func TestMemStats(t *testing.T) {
|
||||
|
||||
mps.On("VMStat").Return(vms, nil)
|
||||
|
||||
sms := &mem.SwapMemoryStat{
|
||||
Total: 8123,
|
||||
Used: 1232,
|
||||
Free: 6412,
|
||||
UsedPercent: 12.2,
|
||||
Sin: 7,
|
||||
Sout: 830,
|
||||
}
|
||||
|
||||
mps.On("SwapStat").Return(sms, nil)
|
||||
|
||||
err = (&MemStats{&mps}).Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -61,15 +50,4 @@ func TestMemStats(t *testing.T) {
|
||||
acc.AssertContainsTaggedFields(t, "mem", memfields, make(map[string]string))
|
||||
|
||||
acc.Metrics = nil
|
||||
|
||||
err = (&SwapStats{&mps}).Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
swapfields := map[string]interface{}{
|
||||
"total": uint64(8123),
|
||||
"used": uint64(1232),
|
||||
"used_percent": float64(12.2),
|
||||
"free": uint64(6412),
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "swap", swapfields, make(map[string]string))
|
||||
}
|
||||
|
||||
47
plugins/inputs/system/swap.go
Normal file
47
plugins/inputs/system/swap.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
type SwapStats struct {
|
||||
ps PS
|
||||
}
|
||||
|
||||
func (_ *SwapStats) Description() string {
|
||||
return "Read metrics about swap memory usage"
|
||||
}
|
||||
|
||||
func (_ *SwapStats) SampleConfig() string { return "" }
|
||||
|
||||
func (s *SwapStats) Gather(acc telegraf.Accumulator) error {
|
||||
swap, err := s.ps.SwapStat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting swap memory info: %s", err)
|
||||
}
|
||||
|
||||
fieldsG := map[string]interface{}{
|
||||
"total": swap.Total,
|
||||
"used": swap.Used,
|
||||
"free": swap.Free,
|
||||
"used_percent": swap.UsedPercent,
|
||||
}
|
||||
fieldsC := map[string]interface{}{
|
||||
"in": swap.Sin,
|
||||
"out": swap.Sout,
|
||||
}
|
||||
acc.AddGauge("swap", fieldsG, nil)
|
||||
acc.AddCounter("swap", fieldsC, nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
ps := newSystemPS()
|
||||
inputs.Add("swap", func() telegraf.Input {
|
||||
return &SwapStats{ps: ps}
|
||||
})
|
||||
}
|
||||
38
plugins/inputs/system/swap_test.go
Normal file
38
plugins/inputs/system/swap_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSwapStats(t *testing.T) {
|
||||
var mps MockPS
|
||||
var err error
|
||||
defer mps.AssertExpectations(t)
|
||||
var acc testutil.Accumulator
|
||||
|
||||
sms := &mem.SwapMemoryStat{
|
||||
Total: 8123,
|
||||
Used: 1232,
|
||||
Free: 6412,
|
||||
UsedPercent: 12.2,
|
||||
Sin: 7,
|
||||
Sout: 830,
|
||||
}
|
||||
|
||||
mps.On("SwapStat").Return(sms, nil)
|
||||
|
||||
err = (&SwapStats{&mps}).Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
swapfields := map[string]interface{}{
|
||||
"total": uint64(8123),
|
||||
"used": uint64(1232),
|
||||
"used_percent": float64(12.2),
|
||||
"free": uint64(6412),
|
||||
}
|
||||
acc.AssertContainsTaggedFields(t, "swap", swapfields, make(map[string]string))
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
# tail Input Plugin
|
||||
# Tail Input Plugin
|
||||
|
||||
The tail plugin "tails" a logfile and parses each log message.
|
||||
|
||||
@@ -49,3 +49,7 @@ The plugin expects messages in one of the
|
||||
data_format = "influx"
|
||||
```
|
||||
|
||||
### Metrics:
|
||||
|
||||
Metrics are produced according to the `data_format` option. Additionally a
|
||||
tag labeled `path` is added to the metric containing the filename being tailed.
|
||||
|
||||
@@ -146,7 +146,11 @@ func (t *Tail) receiver(tailer *tail.Tail) {
|
||||
|
||||
m, err = t.parser.ParseLine(text)
|
||||
if err == nil {
|
||||
t.acc.AddFields(m.Name(), m.Fields(), m.Tags(), m.Time())
|
||||
if m != nil {
|
||||
tags := m.Tags()
|
||||
tags["path"] = tailer.Filename
|
||||
t.acc.AddFields(m.Name(), m.Fields(), tags, m.Time())
|
||||
}
|
||||
} else {
|
||||
t.acc.AddError(fmt.Errorf("E! Malformed log line in %s: [%s], Error: %s\n",
|
||||
tailer.Filename, line.Text, err))
|
||||
|
||||
71
plugins/inputs/tengine/README.md
Normal file
71
plugins/inputs/tengine/README.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Tengine Input Plugin
|
||||
|
||||
The tengine plugin gathers metrics from the
|
||||
[Tengine Web Server](http://tengine.taobao.org/) via the
|
||||
[reqstat](http://tengine.taobao.org/document/http_reqstat.html) module.
|
||||
|
||||
### Configuration:
|
||||
|
||||
```toml
|
||||
# Read Tengine's basic status information (ngx_http_reqstat_module)
|
||||
[[inputs.tengine]]
|
||||
## An array of Tengine reqstat module URI to gather stats.
|
||||
urls = ["http://127.0.0.1/us"]
|
||||
|
||||
## HTTP response timeout (default: 5s)
|
||||
# response_timeout = "5s"
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.pem"
|
||||
# tls_key = "/etc/telegraf/key.pem"
|
||||
## Use TLS but skip chain & host verification
|
||||
# insecure_skip_verify = false
|
||||
```
|
||||
|
||||
### Metrics:
|
||||
|
||||
- Measurement
|
||||
- tags:
|
||||
- port
|
||||
- server
|
||||
- server_name
|
||||
- fields:
|
||||
- bytes_in (integer, total number of bytes received from client)
|
||||
- bytes_out (integer, total number of bytes sent to client)
|
||||
- conn_total (integer, total number of accepted connections)
|
||||
- req_total (integer, total number of processed requests)
|
||||
- http_2xx (integer, total number of 2xx requests)
|
||||
- http_3xx (integer, total number of 3xx requests)
|
||||
- http_4xx (integer, total number of 4xx requests)
|
||||
- http_5xx (integer, total number of 5xx requests)
|
||||
- http_other_status (integer, total number of other requests)
|
||||
- rt (integer, accumulation or rt)
|
||||
- ups_req (integer, total number of requests calling for upstream)
|
||||
- ups_rt (integer, accumulation or upstream rt)
|
||||
- ups_tries (integer, total number of times calling for upstream)
|
||||
- http_200 (integer, total number of 200 requests)
|
||||
- http_206 (integer, total number of 206 requests)
|
||||
- http_302 (integer, total number of 302 requests)
|
||||
- http_304 (integer, total number of 304 requests)
|
||||
- http_403 (integer, total number of 403 requests)
|
||||
- http_404 (integer, total number of 404 requests)
|
||||
- http_416 (integer, total number of 416 requests)
|
||||
- http_499 (integer, total number of 499 requests)
|
||||
- http_500 (integer, total number of 500 requests)
|
||||
- http_502 (integer, total number of 502 requests)
|
||||
- http_503 (integer, total number of 503 requests)
|
||||
- http_504 (integer, total number of 504 requests)
|
||||
- http_508 (integer, total number of 508 requests)
|
||||
- http_other_detail_status (integer, total number of requests of other status codes*http_ups_4xx total number of requests of upstream 4xx)
|
||||
- http_ups_5xx (integer, total number of requests of upstream 5xx)
|
||||
|
||||
### Example Output:
|
||||
|
||||
```
|
||||
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=localhost bytes_in=9129i,bytes_out=56334i,conn_total=14i,http_200=90i,http_206=0i,http_2xx=90i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=0i,http_416=0i,http_499=0i,http_4xx=0i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=90i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
|
||||
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=28.79.190.35.bc.googleusercontent.com bytes_in=1500i,bytes_out=3009i,conn_total=4i,http_200=1i,http_206=0i,http_2xx=1i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=1i,http_416=0i,http_499=0i,http_4xx=3i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=4i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
|
||||
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=www.google.com bytes_in=372i,bytes_out=786i,conn_total=1i,http_200=1i,http_206=0i,http_2xx=1i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=0i,http_416=0i,http_499=0i,http_4xx=0i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=1i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
|
||||
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=35.190.79.28 bytes_in=4433i,bytes_out=10259i,conn_total=5i,http_200=3i,http_206=0i,http_2xx=3i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=11i,http_416=0i,http_499=0i,http_4xx=11i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=14i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
|
||||
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=tenka-prod-api.txwy.tw bytes_in=3014397400i,bytes_out=14279992835i,conn_total=36844i,http_200=3177339i,http_206=0i,http_2xx=3177339i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=123i,http_416=0i,http_499=0i,http_4xx=123i,http_500=17214i,http_502=4453i,http_503=80i,http_504=0i,http_508=0i,http_5xx=21747i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=123i,http_ups_5xx=21747i,req_total=3199209i,rt=245874536i,ups_req=2685076i,ups_rt=245858217i,ups_tries=2685076i 1526546308000000000
|
||||
```
|
||||
338
plugins/inputs/tengine/tengine.go
Normal file
338
plugins/inputs/tengine/tengine.go
Normal file
@@ -0,0 +1,338 @@
|
||||
package tengine
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"io"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/tls"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
type Tengine struct {
|
||||
Urls []string
|
||||
ResponseTimeout internal.Duration
|
||||
tls.ClientConfig
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
var sampleConfig = `
|
||||
# An array of Tengine reqstat module URI to gather stats.
|
||||
urls = ["http://127.0.0.1/us"]
|
||||
|
||||
# HTTP response timeout (default: 5s)
|
||||
# response_timeout = "5s"
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = "/etc/telegraf/ca.pem"
|
||||
# tls_cert = "/etc/telegraf/cert.cer"
|
||||
# tls_key = "/etc/telegraf/key.key"
|
||||
## Use TLS but skip chain & host verification
|
||||
# insecure_skip_verify = false
|
||||
`
|
||||
|
||||
func (n *Tengine) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (n *Tengine) Description() string {
|
||||
return "Read Tengine's basic status information (ngx_http_reqstat_module)"
|
||||
}
|
||||
|
||||
func (n *Tengine) Gather(acc telegraf.Accumulator) error {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Create an HTTP client that is re-used for each
|
||||
// collection interval
|
||||
if n.client == nil {
|
||||
client, err := n.createHttpClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.client = client
|
||||
}
|
||||
|
||||
for _, u := range n.Urls {
|
||||
addr, err := url.Parse(u)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("Unable to parse address '%s': %s", u, err))
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(addr *url.URL) {
|
||||
defer wg.Done()
|
||||
acc.AddError(n.gatherUrl(addr, acc))
|
||||
}(addr)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Tengine) createHttpClient() (*http.Client, error) {
|
||||
tlsCfg, err := n.ClientConfig.TLSConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if n.ResponseTimeout.Duration < time.Second {
|
||||
n.ResponseTimeout.Duration = time.Second * 5
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsCfg,
|
||||
},
|
||||
Timeout: n.ResponseTimeout.Duration,
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
type TengineSatus struct {
|
||||
host string
|
||||
bytes_in uint64
|
||||
bytes_out uint64
|
||||
conn_total uint64
|
||||
req_total uint64
|
||||
http_2xx uint64
|
||||
http_3xx uint64
|
||||
http_4xx uint64
|
||||
http_5xx uint64
|
||||
http_other_status uint64
|
||||
rt uint64
|
||||
ups_req uint64
|
||||
ups_rt uint64
|
||||
ups_tries uint64
|
||||
http_200 uint64
|
||||
http_206 uint64
|
||||
http_302 uint64
|
||||
http_304 uint64
|
||||
http_403 uint64
|
||||
http_404 uint64
|
||||
http_416 uint64
|
||||
http_499 uint64
|
||||
http_500 uint64
|
||||
http_502 uint64
|
||||
http_503 uint64
|
||||
http_504 uint64
|
||||
http_508 uint64
|
||||
http_other_detail_status uint64
|
||||
http_ups_4xx uint64
|
||||
http_ups_5xx uint64
|
||||
}
|
||||
|
||||
func (n *Tengine) gatherUrl(addr *url.URL, acc telegraf.Accumulator) error {
|
||||
var tenginestatus TengineSatus
|
||||
resp, err := n.client.Get(addr.String())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error making HTTP request to %s: %s", addr.String(), err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("%s returned HTTP status %s", addr.String(), resp.Status)
|
||||
}
|
||||
r := bufio.NewReader(resp.Body)
|
||||
|
||||
for {
|
||||
line, err := r.ReadString('\n')
|
||||
|
||||
if err != nil || io.EOF == err {
|
||||
break
|
||||
}
|
||||
line_split := strings.Split(strings.TrimSpace(line), ",")
|
||||
if len(line_split) != 30 {
|
||||
continue
|
||||
}
|
||||
tenginestatus.host = line_split[0]
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.bytes_in, err = strconv.ParseUint(line_split[1], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.bytes_out, err = strconv.ParseUint(line_split[2], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.conn_total, err = strconv.ParseUint(line_split[3], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.req_total, err = strconv.ParseUint(line_split[4], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_2xx, err = strconv.ParseUint(line_split[5], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_3xx, err = strconv.ParseUint(line_split[6], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_4xx, err = strconv.ParseUint(line_split[7], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_5xx, err = strconv.ParseUint(line_split[8], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_other_status, err = strconv.ParseUint(line_split[9], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.rt, err = strconv.ParseUint(line_split[10], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.ups_req, err = strconv.ParseUint(line_split[11], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.ups_rt, err = strconv.ParseUint(line_split[12], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.ups_tries, err = strconv.ParseUint(line_split[13], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_200, err = strconv.ParseUint(line_split[14], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_206, err = strconv.ParseUint(line_split[15], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_302, err = strconv.ParseUint(line_split[16], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_304, err = strconv.ParseUint(line_split[17], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_403, err = strconv.ParseUint(line_split[18], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_404, err = strconv.ParseUint(line_split[19], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_416, err = strconv.ParseUint(line_split[20], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_499, err = strconv.ParseUint(line_split[21], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_500, err = strconv.ParseUint(line_split[22], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_502, err = strconv.ParseUint(line_split[23], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_503, err = strconv.ParseUint(line_split[24], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_504, err = strconv.ParseUint(line_split[25], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_508, err = strconv.ParseUint(line_split[26], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_other_detail_status, err = strconv.ParseUint(line_split[27], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_ups_4xx, err = strconv.ParseUint(line_split[28], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tenginestatus.http_ups_5xx, err = strconv.ParseUint(line_split[29], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tags := getTags(addr, tenginestatus.host)
|
||||
fields := map[string]interface{}{
|
||||
"bytes_in": tenginestatus.bytes_in,
|
||||
"bytes_out": tenginestatus.bytes_out,
|
||||
"conn_total": tenginestatus.conn_total,
|
||||
"req_total": tenginestatus.req_total,
|
||||
"http_2xx": tenginestatus.http_2xx,
|
||||
"http_3xx": tenginestatus.http_3xx,
|
||||
"http_4xx": tenginestatus.http_4xx,
|
||||
"http_5xx": tenginestatus.http_5xx,
|
||||
"http_other_status": tenginestatus.http_other_status,
|
||||
"rt": tenginestatus.rt,
|
||||
"ups_req": tenginestatus.ups_req,
|
||||
"ups_rt": tenginestatus.ups_rt,
|
||||
"ups_tries": tenginestatus.ups_tries,
|
||||
"http_200": tenginestatus.http_200,
|
||||
"http_206": tenginestatus.http_206,
|
||||
"http_302": tenginestatus.http_302,
|
||||
"http_304": tenginestatus.http_304,
|
||||
"http_403": tenginestatus.http_403,
|
||||
"http_404": tenginestatus.http_404,
|
||||
"http_416": tenginestatus.http_416,
|
||||
"http_499": tenginestatus.http_499,
|
||||
"http_500": tenginestatus.http_500,
|
||||
"http_502": tenginestatus.http_502,
|
||||
"http_503": tenginestatus.http_503,
|
||||
"http_504": tenginestatus.http_504,
|
||||
"http_508": tenginestatus.http_508,
|
||||
"http_other_detail_status": tenginestatus.http_other_detail_status,
|
||||
"http_ups_4xx": tenginestatus.http_ups_4xx,
|
||||
"http_ups_5xx": tenginestatus.http_ups_5xx,
|
||||
}
|
||||
acc.AddFields("tengine", fields, tags)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get tag(s) for the tengine plugin
|
||||
func getTags(addr *url.URL, server_name string) map[string]string {
|
||||
h := addr.Host
|
||||
host, port, err := net.SplitHostPort(h)
|
||||
if err != nil {
|
||||
host = addr.Host
|
||||
if addr.Scheme == "http" {
|
||||
port = "80"
|
||||
} else if addr.Scheme == "https" {
|
||||
port = "443"
|
||||
} else {
|
||||
port = ""
|
||||
}
|
||||
}
|
||||
return map[string]string{"server": host, "port": port, "server_name": server_name}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("tengine", func() telegraf.Input {
|
||||
return &Tengine{}
|
||||
})
|
||||
}
|
||||
97
plugins/inputs/tengine/tengine_test.go
Normal file
97
plugins/inputs/tengine/tengine_test.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package tengine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const tengineSampleResponse = `127.0.0.1,784,1511,2,2,1,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0`
|
||||
|
||||
// Verify that tengine tags are properly parsed based on the server
|
||||
func TestTengineTags(t *testing.T) {
|
||||
urls := []string{"http://localhost/us", "http://localhost:80/us"}
|
||||
var addr *url.URL
|
||||
for _, url1 := range urls {
|
||||
addr, _ = url.Parse(url1)
|
||||
tagMap := getTags(addr, "127.0.0.1")
|
||||
assert.Contains(t, tagMap["server"], "localhost")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTengineGeneratesMetrics(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var rsp string
|
||||
rsp = tengineSampleResponse
|
||||
fmt.Fprintln(w, rsp)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
n := &Tengine{
|
||||
Urls: []string{fmt.Sprintf("%s/us", ts.URL)},
|
||||
}
|
||||
|
||||
var acc_tengine testutil.Accumulator
|
||||
|
||||
err_tengine := acc_tengine.GatherError(n.Gather)
|
||||
|
||||
require.NoError(t, err_tengine)
|
||||
|
||||
fields_tengine := map[string]interface{}{
|
||||
"bytes_in": uint64(784),
|
||||
"bytes_out": uint64(1511),
|
||||
"conn_total": uint64(2),
|
||||
"req_total": uint64(2),
|
||||
"http_2xx": uint64(1),
|
||||
"http_3xx": uint64(0),
|
||||
"http_4xx": uint64(1),
|
||||
"http_5xx": uint64(0),
|
||||
"http_other_status": uint64(0),
|
||||
"rt": uint64(0),
|
||||
"ups_req": uint64(0),
|
||||
"ups_rt": uint64(0),
|
||||
"ups_tries": uint64(0),
|
||||
"http_200": uint64(1),
|
||||
"http_206": uint64(0),
|
||||
"http_302": uint64(0),
|
||||
"http_304": uint64(0),
|
||||
"http_403": uint64(0),
|
||||
"http_404": uint64(1),
|
||||
"http_416": uint64(0),
|
||||
"http_499": uint64(0),
|
||||
"http_500": uint64(0),
|
||||
"http_502": uint64(0),
|
||||
"http_503": uint64(0),
|
||||
"http_504": uint64(0),
|
||||
"http_508": uint64(0),
|
||||
"http_other_detail_status": uint64(0),
|
||||
"http_ups_4xx": uint64(0),
|
||||
"http_ups_5xx": uint64(0),
|
||||
}
|
||||
|
||||
addr, err := url.Parse(ts.URL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(addr.Host)
|
||||
if err != nil {
|
||||
host = addr.Host
|
||||
if addr.Scheme == "http" {
|
||||
port = "80"
|
||||
} else if addr.Scheme == "https" {
|
||||
port = "443"
|
||||
} else {
|
||||
port = ""
|
||||
}
|
||||
}
|
||||
tags := map[string]string{"server": host, "port": port, "server_name": "127.0.0.1"}
|
||||
acc_tengine.AssertContainsTaggedFields(t, "tengine", fields_tengine, tags)
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
# win_perf_counters readme
|
||||
|
||||
Input plugin to read Performance Counters on Windows operating systems.
|
||||
This document presents the input plugin to read Performance Counters on Windows operating systems.
|
||||
|
||||
Configuration is parsed and then tested for validity such as
|
||||
The configuration is parsed and then tested for validity, such as
|
||||
whether the Object, Instance and Counter exist on Telegraf startup.
|
||||
|
||||
Counter paths are refreshed periodically, see [CountersRefreshInterval](#countersrefreshinterval)
|
||||
Counter paths are refreshed periodically, see the [CountersRefreshInterval](#countersrefreshinterval)
|
||||
configuration parameter for more info.
|
||||
|
||||
Wildcards can be used in instance and counter names. Partial wildcards are supported only
|
||||
in instance names on Windows Vista and newer.
|
||||
|
||||
In case of query for all instances `["*"]`, the plugin does not return the instance `_Total`
|
||||
by default. See [IncludeTotal](#includetotal) for more info.
|
||||
|
||||
@@ -19,7 +16,7 @@ by default. See [IncludeTotal](#includetotal) for more info.
|
||||
The examples contained in this file have been found on the internet
|
||||
as counters used when performance monitoring
|
||||
Active Directory and IIS in particular.
|
||||
There are a lot other good objects to monitor, if you know what to look for.
|
||||
There are a lot of other good objects to monitor, if you know what to look for.
|
||||
This file is likely to be updated in the future with more examples for
|
||||
useful configurations for separate scenarios.
|
||||
|
||||
@@ -34,40 +31,67 @@ Bool, if set to `true` will print out all matching performance objects.
|
||||
Example:
|
||||
`PrintValid=true`
|
||||
|
||||
#### UseWildcardsExpansion
|
||||
|
||||
If `UseWildcardsExpansion` is set to true, wildcards can be used in the
|
||||
instance name and the counter name. When using localized Windows, counters
|
||||
will be also be localized. Instance indexes will also be returned in the
|
||||
instance name.
|
||||
|
||||
Partial wildcards (e.g. `chrome*`) are supported only in the instance name on Windows Vista and newer.
|
||||
|
||||
If disabled, wildcards (not partial) in instance names can still be used, but
|
||||
instance indexes will not be returned in the instance names.
|
||||
|
||||
Example:
|
||||
`UseWildcardsExpansion=true`
|
||||
|
||||
#### CountersRefreshInterval
|
||||
|
||||
Configured counters are matched against available counters at the interval
|
||||
specified by the `CountersRefreshInterval` parameter. Default value is `1m` (1 minute).
|
||||
specified by the `CountersRefreshInterval` parameter. The default value is `1m` (1 minute).
|
||||
|
||||
If wildcards are used in instance or counter names, they are expanded at this point.
|
||||
If wildcards are used in instance or counter names, they are expanded at this point, if the `UseWildcardsExpansion` param is set to `true`.
|
||||
|
||||
Setting `CountersRefreshInterval` too low (order of seconds) can cause Telegraf to create
|
||||
Setting the `CountersRefreshInterval` too low (order of seconds) can cause Telegraf to create
|
||||
a high CPU load.
|
||||
|
||||
Set to `0s` to disable periodic refreshing.
|
||||
Set it to `0s` to disable periodic refreshing.
|
||||
|
||||
Example:
|
||||
`CountersRefreshInterval=1m`
|
||||
|
||||
#### PreVistaSupport
|
||||
|
||||
_Deprecated. Necessary features on Windows Vista and newer are checked dynamically_
|
||||
|
||||
Bool, if set to `true` will use the localized PerfCounter interface that has been present since before Vista for backwards compatability.
|
||||
Bool, if set to `true`, the plugin will use the localized PerfCounter interface that has been present since before Vista for backwards compatability.
|
||||
|
||||
It is recommended NOT to use this on OSes starting with Vista and newer because it requires more configuration to use this than the newer interface present since Vista.
|
||||
|
||||
Example for Windows Server 2003, this would be set to true:
|
||||
`PreVistaSupport=true`
|
||||
|
||||
#### UsePerfCounterTime
|
||||
|
||||
Bool, if set to `true` will request a timestamp along with the PerfCounter data.
|
||||
If se to `false`, current time will be used.
|
||||
|
||||
Supported on Windows Vista/Windows Server 2008 and newer
|
||||
Example:
|
||||
`UsePerfCounterTime=true`
|
||||
|
||||
### Object
|
||||
|
||||
See Entry below.
|
||||
|
||||
### Entry
|
||||
A new configuration entry consists of the TOML header to start with,
|
||||
A new configuration entry consists of the TOML header starting with,
|
||||
`[[inputs.win_perf_counters.object]]`.
|
||||
This must follow before other plugin configurations,
|
||||
beneath the main win_perf_counters entry, `[[inputs.win_perf_counters]]`.
|
||||
|
||||
Following this are 3 required key/value pairs and the three optional parameters and their usage.
|
||||
Following this are 3 required key/value pairs and three optional parameters and their usage.
|
||||
|
||||
#### ObjectName
|
||||
**Required**
|
||||
@@ -79,16 +103,18 @@ Example: `ObjectName = "LogicalDisk"`
|
||||
#### Instances
|
||||
**Required**
|
||||
|
||||
Instances key (this is an array) is the instances of a counter you would like returned,
|
||||
The instances key (this is an array) declares the instances of a counter you would like returned,
|
||||
it can be one or more values.
|
||||
|
||||
Example, `Instances = ["C:","D:","E:"]` will return only for the instances
|
||||
Example: `Instances = ["C:","D:","E:"]`
|
||||
|
||||
This will return only for the instances
|
||||
C:, D: and E: where relevant. To get all instances of a Counter, use `["*"]` only.
|
||||
By default any results containing `_Total` are stripped,
|
||||
unless this is specified as the wanted instance.
|
||||
Alternatively see the option `IncludeTotal` below.
|
||||
|
||||
It is also possible to set partial wildcards, eg. `["chrome*"]`
|
||||
It is also possible to set partial wildcards, eg. `["chrome*"]`, if the `UseWildcardsExpansion` param is set to `true`
|
||||
|
||||
Some Objects do not have instances to select from at all.
|
||||
Here only one option is valid if you want data back,
|
||||
@@ -97,41 +123,43 @@ and that is to specify `Instances = ["------"]`.
|
||||
#### Counters
|
||||
**Required**
|
||||
|
||||
Counters key (this is an array) is the counters of the ObjectName
|
||||
The Counters key (this is an array) declares the counters of the ObjectName
|
||||
you would like returned, it can also be one or more values.
|
||||
|
||||
Example: `Counters = ["% Idle Time", "% Disk Read Time", "% Disk Write Time"]`
|
||||
This must be specified for every counter you want the results of,
|
||||
or use `["*"]` for all the counters for object.
|
||||
|
||||
This must be specified for every counter you want the results of, or use
|
||||
`["*"]` for all the counters of the object, if the `UseWildcardsExpansion` param
|
||||
is set to `true`.
|
||||
|
||||
#### Measurement
|
||||
*Optional*
|
||||
|
||||
This key is optional, if it is not set it will be `win_perf_counters`.
|
||||
In InfluxDB this is the key by which the returned data is stored underneath,
|
||||
so for ordering your data in a good manner,
|
||||
This key is optional. If it is not set it will be `win_perf_counters`.
|
||||
In InfluxDB this is the key underneath which the returned data is stored.
|
||||
So for ordering your data in a good manner,
|
||||
this is a good key to set with a value when you want your IIS and Disk results stored
|
||||
separately from Processor results.
|
||||
|
||||
Example: `Measurement = "win_disk"
|
||||
Example: `Measurement = "win_disk"``
|
||||
|
||||
#### IncludeTotal
|
||||
*Optional*
|
||||
|
||||
This key is optional, it is a simple bool.
|
||||
This key is optional. It is a simple bool.
|
||||
If it is not set to true or included it is treated as false.
|
||||
This key only has an effect if the Instances key is set to `["*"]`
|
||||
and you would also like all instances containing `_Total` returned,
|
||||
This key only has effect if the Instances key is set to `["*"]`
|
||||
and you would also like all instances containing `_Total` to be returned,
|
||||
like `_Total`, `0,_Total` and so on where applicable
|
||||
(Processor Information is one example).
|
||||
|
||||
#### WarnOnMissing
|
||||
*Optional*
|
||||
|
||||
This key is optional, it is a simple bool.
|
||||
This key is optional. It is a simple bool.
|
||||
If it is not set to true or included it is treated as false.
|
||||
This only has an effect on the first execution of the plugin,
|
||||
it will print out any ObjectName/Instance/Counter combinations
|
||||
This only has effect on the first execution of the plugin.
|
||||
It will print out any ObjectName/Instance/Counter combinations
|
||||
asked for that do not match. Useful when debugging new configurations.
|
||||
|
||||
#### FailOnMissing
|
||||
|
||||
73
plugins/inputs/win_perf_counters/kernel32.go
Normal file
73
plugins/inputs/win_perf_counters/kernel32.go
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2010 The win Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. The names of the authors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is the official list of 'win' authors for copyright purposes.
|
||||
//
|
||||
// Alexander Neumann <an2048@googlemail.com>
|
||||
// Joseph Watson <jtwatson@linux-consulting.us>
|
||||
// Kevin Pors <krpors@gmail.com>
|
||||
|
||||
// +build windows
|
||||
|
||||
package win_perf_counters
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type SYSTEMTIME struct {
|
||||
wYear uint16
|
||||
wMonth uint16
|
||||
wDayOfWeek uint16
|
||||
wDay uint16
|
||||
wHour uint16
|
||||
wMinute uint16
|
||||
wSecond uint16
|
||||
wMilliseconds uint16
|
||||
}
|
||||
|
||||
type FILETIME struct {
|
||||
dwLowDateTime uint32
|
||||
dwHighDateTime uint32
|
||||
}
|
||||
|
||||
var (
|
||||
// Library
|
||||
libkrnDll *syscall.DLL
|
||||
|
||||
// Functions
|
||||
krn_FileTimeToSystemTime *syscall.Proc
|
||||
krn_FileTimeToLocalFileTime *syscall.Proc
|
||||
krn_LocalFileTimeToFileTime *syscall.Proc
|
||||
krn_WideCharToMultiByte *syscall.Proc
|
||||
)
|
||||
|
||||
func init() {
|
||||
libkrnDll = syscall.MustLoadDLL("Kernel32.dll")
|
||||
|
||||
krn_FileTimeToSystemTime = libkrnDll.MustFindProc("FileTimeToSystemTime")
|
||||
krn_FileTimeToLocalFileTime = libkrnDll.MustFindProc("FileTimeToLocalFileTime")
|
||||
krn_LocalFileTimeToFileTime = libkrnDll.MustFindProc("LocalFileTimeToFileTime")
|
||||
krn_WideCharToMultiByte = libkrnDll.MustFindProc("WideCharToMultiByte")
|
||||
}
|
||||
@@ -38,12 +38,15 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Error codes
|
||||
const (
|
||||
ERROR_SUCCESS = 0
|
||||
ERROR_INVALID_FUNCTION = 1
|
||||
ERROR_SUCCESS = 0
|
||||
ERROR_FAILURE = 1
|
||||
ERROR_INVALID_FUNCTION = 1
|
||||
EPOCH_DIFFERENCE_MICROS int64 = 11644473600000000
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -170,6 +173,7 @@ var (
|
||||
pdh_AddEnglishCounterW *syscall.Proc
|
||||
pdh_CloseQuery *syscall.Proc
|
||||
pdh_CollectQueryData *syscall.Proc
|
||||
pdh_CollectQueryDataWithTime *syscall.Proc
|
||||
pdh_GetFormattedCounterValue *syscall.Proc
|
||||
pdh_GetFormattedCounterArrayW *syscall.Proc
|
||||
pdh_OpenQuery *syscall.Proc
|
||||
@@ -187,6 +191,7 @@ func init() {
|
||||
pdh_AddEnglishCounterW, _ = libpdhDll.FindProc("PdhAddEnglishCounterW") // XXX: only supported on versions > Vista.
|
||||
pdh_CloseQuery = libpdhDll.MustFindProc("PdhCloseQuery")
|
||||
pdh_CollectQueryData = libpdhDll.MustFindProc("PdhCollectQueryData")
|
||||
pdh_CollectQueryDataWithTime, _ = libpdhDll.FindProc("PdhCollectQueryDataWithTime")
|
||||
pdh_GetFormattedCounterValue = libpdhDll.MustFindProc("PdhGetFormattedCounterValue")
|
||||
pdh_GetFormattedCounterArrayW = libpdhDll.MustFindProc("PdhGetFormattedCounterArrayW")
|
||||
pdh_OpenQuery = libpdhDll.MustFindProc("PdhOpenQuery")
|
||||
@@ -303,6 +308,37 @@ func PdhCollectQueryData(hQuery PDH_HQUERY) uint32 {
|
||||
return uint32(ret)
|
||||
}
|
||||
|
||||
// PdhCollectQueryDataWithTime queries data from perfmon, retrieving the device/windows timestamp from the node it was collected on.
|
||||
// Converts the filetime structure to a GO time class and returns the native time.
|
||||
//
|
||||
func PdhCollectQueryDataWithTime(hQuery PDH_HQUERY) (uint32, time.Time) {
|
||||
var localFileTime FILETIME
|
||||
ret, _, _ := pdh_CollectQueryDataWithTime.Call(uintptr(hQuery), uintptr(unsafe.Pointer(&localFileTime)))
|
||||
|
||||
if ret == ERROR_SUCCESS {
|
||||
var utcFileTime FILETIME
|
||||
ret, _, _ := krn_LocalFileTimeToFileTime.Call(
|
||||
uintptr(unsafe.Pointer(&localFileTime)),
|
||||
uintptr(unsafe.Pointer(&utcFileTime)))
|
||||
|
||||
if ret == 0 {
|
||||
return uint32(ERROR_FAILURE), time.Now()
|
||||
}
|
||||
|
||||
// First convert 100-ns intervals to microseconds, then adjust for the
|
||||
// epoch difference
|
||||
var totalMicroSeconds int64
|
||||
totalMicroSeconds = ((int64(utcFileTime.dwHighDateTime) << 32) | int64(utcFileTime.dwLowDateTime)) / 10
|
||||
totalMicroSeconds -= EPOCH_DIFFERENCE_MICROS
|
||||
|
||||
retTime := time.Unix(0, totalMicroSeconds*1000)
|
||||
|
||||
return uint32(ERROR_SUCCESS), retTime
|
||||
}
|
||||
|
||||
return uint32(ret), time.Now()
|
||||
}
|
||||
|
||||
// PdhGetFormattedCounterValueDouble formats the given hCounter using a 'double'. The result is set into the specialized union struct pValue.
|
||||
// This function does not directly translate to a Windows counterpart due to union specialization tricks.
|
||||
func PdhGetFormattedCounterValueDouble(hCounter PDH_HCOUNTER, lpdwType *uint32, pValue *PDH_FMT_COUNTERVALUE_DOUBLE) uint32 {
|
||||
@@ -352,7 +388,7 @@ func PdhGetFormattedCounterValueDouble(hCounter PDH_HCOUNTER, lpdwType *uint32,
|
||||
// time.Sleep(2000 * time.Millisecond)
|
||||
// }
|
||||
// }
|
||||
func PdhGetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *PDH_FMT_COUNTERVALUE_ITEM_DOUBLE) uint32 {
|
||||
func PdhGetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *byte) uint32 {
|
||||
ret, _, _ := pdh_GetFormattedCounterArrayW.Call(
|
||||
uintptr(hCounter),
|
||||
uintptr(PDH_FMT_DOUBLE|PDH_FMT_NOCAP100),
|
||||
|
||||
@@ -6,9 +6,16 @@ package win_perf_counters
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//PerformanceQuery is abstraction for PDH_FMT_COUNTERVALUE_ITEM_DOUBLE
|
||||
type CounterValue struct {
|
||||
InstanceName string
|
||||
Value float64
|
||||
}
|
||||
|
||||
//PerformanceQuery provides wrappers around Windows performance counters API for easy usage in GO
|
||||
type PerformanceQuery interface {
|
||||
Open() error
|
||||
@@ -18,8 +25,10 @@ type PerformanceQuery interface {
|
||||
GetCounterPath(counterHandle PDH_HCOUNTER) (string, error)
|
||||
ExpandWildCardPath(counterPath string) ([]string, error)
|
||||
GetFormattedCounterValueDouble(hCounter PDH_HCOUNTER) (float64, error)
|
||||
GetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER) ([]CounterValue, error)
|
||||
CollectData() error
|
||||
AddEnglishCounterSupported() bool
|
||||
CollectDataWithTime() (time.Time, error)
|
||||
IsVistaOrNewer() bool
|
||||
}
|
||||
|
||||
//PdhError represents error returned from Performance Counters API
|
||||
@@ -54,8 +63,8 @@ func (m *PerformanceQueryImpl) Open() error {
|
||||
}
|
||||
}
|
||||
var handle PDH_HQUERY
|
||||
ret := PdhOpenQuery(0, 0, &handle)
|
||||
if ret != ERROR_SUCCESS {
|
||||
|
||||
if ret := PdhOpenQuery(0, 0, &handle); ret != ERROR_SUCCESS {
|
||||
return NewPdhError(ret)
|
||||
}
|
||||
m.query = handle
|
||||
@@ -67,8 +76,8 @@ func (m *PerformanceQueryImpl) Close() error {
|
||||
if m.query == 0 {
|
||||
return errors.New("uninitialised query")
|
||||
}
|
||||
ret := PdhCloseQuery(m.query)
|
||||
if ret != ERROR_SUCCESS {
|
||||
|
||||
if ret := PdhCloseQuery(m.query); ret != ERROR_SUCCESS {
|
||||
return NewPdhError(ret)
|
||||
}
|
||||
m.query = 0
|
||||
@@ -80,8 +89,8 @@ func (m *PerformanceQueryImpl) AddCounterToQuery(counterPath string) (PDH_HCOUNT
|
||||
if m.query == 0 {
|
||||
return 0, errors.New("uninitialised query")
|
||||
}
|
||||
ret := PdhAddCounter(m.query, counterPath, 0, &counterHandle)
|
||||
if ret != ERROR_SUCCESS {
|
||||
|
||||
if ret := PdhAddCounter(m.query, counterPath, 0, &counterHandle); ret != ERROR_SUCCESS {
|
||||
return 0, NewPdhError(ret)
|
||||
}
|
||||
return counterHandle, nil
|
||||
@@ -92,8 +101,7 @@ func (m *PerformanceQueryImpl) AddEnglishCounterToQuery(counterPath string) (PDH
|
||||
if m.query == 0 {
|
||||
return 0, errors.New("uninitialised query")
|
||||
}
|
||||
ret := PdhAddEnglishCounter(m.query, counterPath, 0, &counterHandle)
|
||||
if ret != ERROR_SUCCESS {
|
||||
if ret := PdhAddEnglishCounter(m.query, counterPath, 0, &counterHandle); ret != ERROR_SUCCESS {
|
||||
return 0, NewPdhError(ret)
|
||||
}
|
||||
return counterHandle, nil
|
||||
@@ -103,13 +111,11 @@ func (m *PerformanceQueryImpl) AddEnglishCounterToQuery(counterPath string) (PDH
|
||||
func (m *PerformanceQueryImpl) GetCounterPath(counterHandle PDH_HCOUNTER) (string, error) {
|
||||
var bufSize uint32
|
||||
var buff []byte
|
||||
|
||||
ret := PdhGetCounterInfo(counterHandle, 0, &bufSize, nil)
|
||||
if ret == PDH_MORE_DATA {
|
||||
var ret uint32
|
||||
if ret = PdhGetCounterInfo(counterHandle, 0, &bufSize, nil); ret == PDH_MORE_DATA {
|
||||
buff = make([]byte, bufSize)
|
||||
bufSize = uint32(len(buff))
|
||||
ret = PdhGetCounterInfo(counterHandle, 0, &bufSize, &buff[0])
|
||||
if ret == ERROR_SUCCESS {
|
||||
if ret = PdhGetCounterInfo(counterHandle, 0, &bufSize, &buff[0]); ret == ERROR_SUCCESS {
|
||||
ci := (*PDH_COUNTER_INFO)(unsafe.Pointer(&buff[0]))
|
||||
return UTF16PtrToString(ci.SzFullPath), nil
|
||||
}
|
||||
@@ -121,9 +127,9 @@ func (m *PerformanceQueryImpl) GetCounterPath(counterHandle PDH_HCOUNTER) (strin
|
||||
func (m *PerformanceQueryImpl) ExpandWildCardPath(counterPath string) ([]string, error) {
|
||||
var bufSize uint32
|
||||
var buff []uint16
|
||||
var ret uint32
|
||||
|
||||
ret := PdhExpandWildCardPath(counterPath, nil, &bufSize)
|
||||
if ret == PDH_MORE_DATA {
|
||||
if ret = PdhExpandWildCardPath(counterPath, nil, &bufSize); ret == PDH_MORE_DATA {
|
||||
buff = make([]uint16, bufSize)
|
||||
bufSize = uint32(len(buff))
|
||||
ret = PdhExpandWildCardPath(counterPath, &buff[0], &bufSize)
|
||||
@@ -139,8 +145,9 @@ func (m *PerformanceQueryImpl) ExpandWildCardPath(counterPath string) ([]string,
|
||||
func (m *PerformanceQueryImpl) GetFormattedCounterValueDouble(hCounter PDH_HCOUNTER) (float64, error) {
|
||||
var counterType uint32
|
||||
var value PDH_FMT_COUNTERVALUE_DOUBLE
|
||||
ret := PdhGetFormattedCounterValueDouble(hCounter, &counterType, &value)
|
||||
if ret == ERROR_SUCCESS {
|
||||
var ret uint32
|
||||
|
||||
if ret = PdhGetFormattedCounterValueDouble(hCounter, &counterType, &value); ret == ERROR_SUCCESS {
|
||||
if value.CStatus == PDH_CSTATUS_VALID_DATA || value.CStatus == PDH_CSTATUS_NEW_DATA {
|
||||
return value.DoubleValue, nil
|
||||
} else {
|
||||
@@ -151,18 +158,53 @@ func (m *PerformanceQueryImpl) GetFormattedCounterValueDouble(hCounter PDH_HCOUN
|
||||
}
|
||||
}
|
||||
|
||||
func (m *PerformanceQueryImpl) GetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER) ([]CounterValue, error) {
|
||||
var buffSize uint32
|
||||
var itemCount uint32
|
||||
var ret uint32
|
||||
|
||||
if ret = PdhGetFormattedCounterArrayDouble(hCounter, &buffSize, &itemCount, nil); ret == PDH_MORE_DATA {
|
||||
buff := make([]byte, buffSize)
|
||||
|
||||
if ret = PdhGetFormattedCounterArrayDouble(hCounter, &buffSize, &itemCount, &buff[0]); ret == ERROR_SUCCESS {
|
||||
items := (*[1 << 20]PDH_FMT_COUNTERVALUE_ITEM_DOUBLE)(unsafe.Pointer(&buff[0]))[:itemCount]
|
||||
values := make([]CounterValue, 0, itemCount)
|
||||
for _, item := range items {
|
||||
if item.FmtValue.CStatus == PDH_CSTATUS_VALID_DATA || item.FmtValue.CStatus == PDH_CSTATUS_NEW_DATA {
|
||||
val := CounterValue{UTF16PtrToString(item.SzName), item.FmtValue.DoubleValue}
|
||||
values = append(values, val)
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
}
|
||||
return nil, NewPdhError(ret)
|
||||
}
|
||||
|
||||
func (m *PerformanceQueryImpl) CollectData() error {
|
||||
var ret uint32
|
||||
if m.query == 0 {
|
||||
return errors.New("uninitialised query")
|
||||
}
|
||||
ret := PdhCollectQueryData(m.query)
|
||||
if ret != ERROR_SUCCESS {
|
||||
|
||||
if ret = PdhCollectQueryData(m.query); ret != ERROR_SUCCESS {
|
||||
return NewPdhError(ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PerformanceQueryImpl) AddEnglishCounterSupported() bool {
|
||||
func (m *PerformanceQueryImpl) CollectDataWithTime() (time.Time, error) {
|
||||
if m.query == 0 {
|
||||
return time.Now(), errors.New("uninitialised query")
|
||||
}
|
||||
ret, mtime := PdhCollectQueryDataWithTime(m.query)
|
||||
if ret != ERROR_SUCCESS {
|
||||
return time.Now(), NewPdhError(ret)
|
||||
}
|
||||
return mtime, nil
|
||||
}
|
||||
|
||||
func (m *PerformanceQueryImpl) IsVistaOrNewer() bool {
|
||||
return PdhAddEnglishCounterSupported()
|
||||
}
|
||||
|
||||
@@ -181,7 +223,7 @@ func UTF16ToStringArray(buf []uint16) []string {
|
||||
stringLine := UTF16PtrToString(&buf[0])
|
||||
for stringLine != "" {
|
||||
strings = append(strings, stringLine)
|
||||
nextLineStart += len(stringLine) + 1
|
||||
nextLineStart += len([]rune(stringLine)) + 1
|
||||
remainingBuf := buf[nextLineStart:]
|
||||
stringLine = UTF16PtrToString(&remainingBuf[0])
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@ package win_perf_counters
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
var sampleConfig = `
|
||||
@@ -22,6 +23,12 @@ var sampleConfig = `
|
||||
## agent, it will not be gathered.
|
||||
## Settings:
|
||||
# PrintValid = false # Print All matching performance counters
|
||||
# Whether request a timestamp along with the PerfCounter data or just use current time
|
||||
# UsePerfCounterTime=true
|
||||
# If UseWildcardsExpansion params is set to true, wildcards (partial wildcards in instance names and wildcards in counters names) in configured counter paths will be expanded
|
||||
# and in case of localized Windows, counter paths will be also localized. It also returns instance indexes in instance names.
|
||||
# If false, wildcards (not partial) in instance names will still be expanded, but instance indexes will not be returned in instance names.
|
||||
#UseWildcardsExpansion = false
|
||||
# Period after which counters will be reread from configuration and wildcards in counter paths expanded
|
||||
CountersRefreshInterval="1m"
|
||||
|
||||
@@ -73,8 +80,10 @@ type Win_PerfCounters struct {
|
||||
PrintValid bool
|
||||
//deprecated: determined dynamically
|
||||
PreVistaSupport bool
|
||||
UsePerfCounterTime bool
|
||||
Object []perfobject
|
||||
CountersRefreshInterval internal.Duration
|
||||
UseWildcardsExpansion bool
|
||||
|
||||
lastRefreshed time.Time
|
||||
counters []*counter
|
||||
@@ -101,6 +110,12 @@ type counter struct {
|
||||
counterHandle PDH_HCOUNTER
|
||||
}
|
||||
|
||||
type instanceGrouping struct {
|
||||
name string
|
||||
instance string
|
||||
objectname string
|
||||
}
|
||||
|
||||
var sanitizedChars = strings.NewReplacer("/sec", "_persec", "/Sec", "_persec",
|
||||
" ", "_", "%", "Percent", `\`, "")
|
||||
|
||||
@@ -137,45 +152,59 @@ func (m *Win_PerfCounters) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (m *Win_PerfCounters) AddItem(counterPath string, instance string, measurement string, includeTotal bool) error {
|
||||
if !m.query.AddEnglishCounterSupported() {
|
||||
_, err := m.query.AddCounterToQuery(counterPath)
|
||||
//objectName string, counter string, instance string, measurement string, include_total bool
|
||||
func (m *Win_PerfCounters) AddItem(counterPath string, objectName string, instance string, counterName string, measurement string, includeTotal bool) error {
|
||||
var err error
|
||||
var counterHandle PDH_HCOUNTER
|
||||
if !m.query.IsVistaOrNewer() {
|
||||
counterHandle, err = m.query.AddCounterToQuery(counterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
counterHandle, err := m.query.AddEnglishCounterToQuery(counterPath)
|
||||
counterHandle, err = m.query.AddEnglishCounterToQuery(counterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if m.UseWildcardsExpansion {
|
||||
origInstance := instance
|
||||
counterPath, err = m.query.GetCounterPath(counterHandle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
counters, err := m.query.ExpandWildCardPath(counterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, counterPath := range counters {
|
||||
var err error
|
||||
counterHandle, err := m.query.AddCounterToQuery(counterPath)
|
||||
|
||||
parsedObjectName, parsedInstance, parsedCounter, err := extractObjectInstanceCounterFromQuery(counterPath)
|
||||
counters, err := m.query.ExpandWildCardPath(counterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if parsedInstance == "_Total" && instance == "*" && !includeTotal {
|
||||
continue
|
||||
}
|
||||
for _, counterPath := range counters {
|
||||
var err error
|
||||
counterHandle, err := m.query.AddCounterToQuery(counterPath)
|
||||
|
||||
newItem := &counter{counterPath, parsedObjectName, parsedCounter, parsedInstance, measurement,
|
||||
objectName, instance, counterName, err = extractObjectInstanceCounterFromQuery(counterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if instance == "_Total" && origInstance == "*" && !includeTotal {
|
||||
continue
|
||||
}
|
||||
|
||||
newItem := &counter{counterPath, objectName, counterName, instance, measurement,
|
||||
includeTotal, counterHandle}
|
||||
m.counters = append(m.counters, newItem)
|
||||
|
||||
if m.PrintValid {
|
||||
log.Printf("Valid: %s\n", counterPath)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newItem := &counter{counterPath, objectName, counterName, instance, measurement,
|
||||
includeTotal, counterHandle}
|
||||
m.counters = append(m.counters, newItem)
|
||||
|
||||
if m.PrintValid {
|
||||
log.Printf("Valid: %s\n", counterPath)
|
||||
}
|
||||
@@ -199,7 +228,7 @@ func (m *Win_PerfCounters) ParseConfig() error {
|
||||
counterPath = "\\" + objectname + "(" + instance + ")\\" + counter
|
||||
}
|
||||
|
||||
err := m.AddItem(counterPath, instance, PerfObject.Measurement, PerfObject.IncludeTotal)
|
||||
err := m.AddItem(counterPath, objectname, instance, counter, PerfObject.Measurement, PerfObject.IncludeTotal)
|
||||
|
||||
if err != nil {
|
||||
if PerfObject.FailOnMissing || PerfObject.WarnOnMissing {
|
||||
@@ -225,20 +254,19 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
|
||||
var err error
|
||||
|
||||
if m.lastRefreshed.IsZero() || (m.CountersRefreshInterval.Duration.Nanoseconds() > 0 && m.lastRefreshed.Add(m.CountersRefreshInterval.Duration).Before(time.Now())) {
|
||||
m.counters = m.counters[:0]
|
||||
if m.counters != nil {
|
||||
m.counters = m.counters[:0]
|
||||
}
|
||||
|
||||
err = m.query.Open()
|
||||
if err != nil {
|
||||
if err = m.query.Open(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.ParseConfig()
|
||||
if err != nil {
|
||||
if err = m.ParseConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
//some counters need two data samples before computing a value
|
||||
err = m.query.CollectData()
|
||||
if err != nil {
|
||||
if err = m.query.CollectData(); err != nil {
|
||||
return err
|
||||
}
|
||||
m.lastRefreshed = time.Now()
|
||||
@@ -246,37 +274,66 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
type InstanceGrouping struct {
|
||||
name string
|
||||
instance string
|
||||
objectname string
|
||||
var collectFields = make(map[instanceGrouping]map[string]interface{})
|
||||
|
||||
var timestamp time.Time
|
||||
if m.UsePerfCounterTime && m.query.IsVistaOrNewer() {
|
||||
timestamp, err = m.query.CollectDataWithTime()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
timestamp = time.Now()
|
||||
if err = m.query.CollectData(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var collectFields = make(map[InstanceGrouping]map[string]interface{})
|
||||
|
||||
err = m.query.CollectData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// For iterate over the known metrics and get the samples.
|
||||
for _, metric := range m.counters {
|
||||
// collect
|
||||
value, err := m.query.GetFormattedCounterValueDouble(metric.counterHandle)
|
||||
if err == nil {
|
||||
measurement := sanitizedChars.Replace(metric.measurement)
|
||||
if measurement == "" {
|
||||
measurement = "win_perf_counters"
|
||||
if m.UseWildcardsExpansion {
|
||||
value, err := m.query.GetFormattedCounterValueDouble(metric.counterHandle)
|
||||
if err == nil {
|
||||
addCounterMeasurement(metric, metric.instance, value, collectFields)
|
||||
} else {
|
||||
//ignore invalid data as some counters from process instances returns this sometimes
|
||||
if !isKnownCounterDataError(err) {
|
||||
return fmt.Errorf("error while getting value for counter %s: %v", metric.counterPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
var instance = InstanceGrouping{measurement, metric.instance, metric.objectName}
|
||||
if collectFields[instance] == nil {
|
||||
collectFields[instance] = make(map[string]interface{})
|
||||
}
|
||||
collectFields[instance][sanitizedChars.Replace(metric.counter)] = float32(value)
|
||||
} else {
|
||||
//ignore invalid data from as some counters from process instances returns this sometimes
|
||||
if phderr, ok := err.(*PdhError); ok && phderr.ErrorCode != PDH_INVALID_DATA && phderr.ErrorCode != PDH_CALC_NEGATIVE_VALUE {
|
||||
return fmt.Errorf("error while getting value for counter %s: %v", metric.counterPath, err)
|
||||
counterValues, err := m.query.GetFormattedCounterArrayDouble(metric.counterHandle)
|
||||
if err == nil {
|
||||
for _, cValue := range counterValues {
|
||||
var add bool
|
||||
if metric.includeTotal {
|
||||
// If IncludeTotal is set, include all.
|
||||
add = true
|
||||
} else if metric.instance == "*" && !strings.Contains(cValue.InstanceName, "_Total") {
|
||||
// Catch if set to * and that it is not a '*_Total*' instance.
|
||||
add = true
|
||||
} else if metric.instance == cValue.InstanceName {
|
||||
// Catch if we set it to total or some form of it
|
||||
add = true
|
||||
} else if strings.Contains(metric.instance, "#") && strings.HasPrefix(metric.instance, cValue.InstanceName) {
|
||||
// If you are using a multiple instance identifier such as "w3wp#1"
|
||||
// phd.dll returns only the first 2 characters of the identifier.
|
||||
add = true
|
||||
cValue.InstanceName = metric.instance
|
||||
} else if metric.instance == "------" {
|
||||
add = true
|
||||
}
|
||||
|
||||
if add {
|
||||
addCounterMeasurement(metric, cValue.InstanceName, cValue.Value, collectFields)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//ignore invalid data as some counters from process instances returns this sometimes
|
||||
if !isKnownCounterDataError(err) {
|
||||
return fmt.Errorf("error while getting value for counter %s: %v", metric.counterPath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,12 +345,33 @@ func (m *Win_PerfCounters) Gather(acc telegraf.Accumulator) error {
|
||||
if len(instance.instance) > 0 {
|
||||
tags["instance"] = instance.instance
|
||||
}
|
||||
acc.AddFields(instance.name, fields, tags)
|
||||
acc.AddFields(instance.name, fields, tags, timestamp)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addCounterMeasurement(metric *counter, instanceName string, value float64, collectFields map[instanceGrouping]map[string]interface{}) {
|
||||
measurement := sanitizedChars.Replace(metric.measurement)
|
||||
if measurement == "" {
|
||||
measurement = "win_perf_counters"
|
||||
}
|
||||
var instance = instanceGrouping{measurement, instanceName, metric.objectName}
|
||||
if collectFields[instance] == nil {
|
||||
collectFields[instance] = make(map[string]interface{})
|
||||
}
|
||||
collectFields[instance][sanitizedChars.Replace(metric.counter)] = float32(value)
|
||||
}
|
||||
|
||||
func isKnownCounterDataError(err error) bool {
|
||||
if pdhErr, ok := err.(*PdhError); ok && (pdhErr.ErrorCode == PDH_INVALID_DATA ||
|
||||
pdhErr.ErrorCode == PDH_CALC_NEGATIVE_VALUE ||
|
||||
pdhErr.ErrorCode == PDH_CSTATUS_INVALID_DATA) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("win_perf_counters", func() telegraf.Input {
|
||||
return &Win_PerfCounters{query: &PerformanceQueryImpl{}, CountersRefreshInterval: internal.Duration{Duration: time.Second * 60}}
|
||||
|
||||
@@ -70,6 +70,11 @@ func TestWinPerformanceQueryImpl(t *testing.T) {
|
||||
_, err = query.GetFormattedCounterValueDouble(hCounter)
|
||||
require.NoError(t, err)
|
||||
|
||||
now := time.Now()
|
||||
mtime, err := query.CollectDataWithTime()
|
||||
require.NoError(t, err)
|
||||
assert.True(t, mtime.Sub(now) < time.Second)
|
||||
|
||||
counterPath = "\\Process(*)\\% Processor Time"
|
||||
paths, err := query.ExpandWildCardPath(counterPath)
|
||||
require.NoError(t, err)
|
||||
@@ -81,6 +86,33 @@ func TestWinPerformanceQueryImpl(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, paths)
|
||||
assert.True(t, len(paths) > 1)
|
||||
|
||||
err = query.Open()
|
||||
require.NoError(t, err)
|
||||
|
||||
counterPath = "\\Process(*)\\% Processor Time"
|
||||
hCounter, err = query.AddEnglishCounterToQuery(counterPath)
|
||||
require.NoError(t, err)
|
||||
assert.NotEqual(t, 0, hCounter)
|
||||
|
||||
err = query.CollectData()
|
||||
require.NoError(t, err)
|
||||
time.Sleep(time.Second)
|
||||
|
||||
err = query.CollectData()
|
||||
require.NoError(t, err)
|
||||
|
||||
arr, err := query.GetFormattedCounterArrayDouble(hCounter)
|
||||
if phderr, ok := err.(*PdhError); ok && phderr.ErrorCode != PDH_INVALID_DATA && phderr.ErrorCode != PDH_CALC_NEGATIVE_VALUE {
|
||||
time.Sleep(time.Second)
|
||||
arr, err = query.GetFormattedCounterArrayDouble(hCounter)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
assert.True(t, len(arr) > 0, "Too")
|
||||
|
||||
err = query.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestWinPerfcountersConfigGet1(t *testing.T) {
|
||||
@@ -573,7 +605,7 @@ func TestWinPerfcountersCollect2(t *testing.T) {
|
||||
|
||||
perfobjects[0] = PerfObject
|
||||
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfobjects, query: &PerformanceQueryImpl{}}
|
||||
m := Win_PerfCounters{PrintValid: false, UsePerfCounterTime: true, Object: perfobjects, query: &PerformanceQueryImpl{}, UseWildcardsExpansion: true}
|
||||
var acc testutil.Accumulator
|
||||
err := m.Gather(&acc)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -19,10 +19,20 @@ type testCounter struct {
|
||||
value float64
|
||||
}
|
||||
type FakePerformanceQuery struct {
|
||||
counters map[string]testCounter
|
||||
addEnglishSupported bool
|
||||
expandPaths map[string][]string
|
||||
openCalled bool
|
||||
counters map[string]testCounter
|
||||
vistaAndNewer bool
|
||||
expandPaths map[string][]string
|
||||
openCalled bool
|
||||
}
|
||||
|
||||
var MetricTime = time.Date(2018, 5, 28, 12, 0, 0, 0, time.UTC)
|
||||
|
||||
func (m *testCounter) ToCounterValue() *CounterValue {
|
||||
_, inst, _, _ := extractObjectInstanceCounterFromQuery(m.path)
|
||||
if inst == "" {
|
||||
inst = "--"
|
||||
}
|
||||
return &CounterValue{inst, m.value}
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) Open() error {
|
||||
@@ -94,14 +104,68 @@ func (m *FakePerformanceQuery) GetFormattedCounterValueDouble(counterHandle PDH_
|
||||
} else {
|
||||
if counter.value == 0 {
|
||||
return 0, NewPdhError(PDH_INVALID_DATA)
|
||||
} else {
|
||||
} else if counter.value == -1 {
|
||||
return 0, NewPdhError(PDH_CALC_NEGATIVE_VALUE)
|
||||
} else {
|
||||
return 0, NewPdhError(PDH_ACCESS_DENIED)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("GetFormattedCounterValueDouble: invalid handle: %d", counterHandle)
|
||||
}
|
||||
func (m *FakePerformanceQuery) findCounterByPath(counterPath string) *testCounter {
|
||||
for _, c := range m.counters {
|
||||
if c.path == counterPath {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) findCounterByHandle(counterHandle PDH_HCOUNTER) *testCounter {
|
||||
for _, c := range m.counters {
|
||||
if c.handle == counterHandle {
|
||||
return &c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) GetFormattedCounterArrayDouble(hCounter PDH_HCOUNTER) ([]CounterValue, error) {
|
||||
if !m.openCalled {
|
||||
return nil, errors.New("GetFormattedCounterArrayDouble: uninitialised query")
|
||||
}
|
||||
for _, c := range m.counters {
|
||||
if c.handle == hCounter {
|
||||
if e, ok := m.expandPaths[c.path]; ok {
|
||||
counters := make([]CounterValue, 0, len(e))
|
||||
for _, p := range e {
|
||||
counter := m.findCounterByPath(p)
|
||||
if counter != nil {
|
||||
if counter.value > 0 {
|
||||
counters = append(counters, *counter.ToCounterValue())
|
||||
} else {
|
||||
if counter.value == 0 {
|
||||
return nil, NewPdhError(PDH_INVALID_DATA)
|
||||
} else if counter.value == -1 {
|
||||
return nil, NewPdhError(PDH_CALC_NEGATIVE_VALUE)
|
||||
} else {
|
||||
return nil, NewPdhError(PDH_ACCESS_DENIED)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %s", p)
|
||||
}
|
||||
}
|
||||
return counters, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %d", hCounter)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("GetFormattedCounterArrayDouble: invalid counter : %d, no paths found", hCounter)
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) CollectData() error {
|
||||
if !m.openCalled {
|
||||
@@ -110,8 +174,15 @@ func (m *FakePerformanceQuery) CollectData() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) AddEnglishCounterSupported() bool {
|
||||
return m.addEnglishSupported
|
||||
func (m *FakePerformanceQuery) CollectDataWithTime() (time.Time, error) {
|
||||
if !m.openCalled {
|
||||
return time.Now(), errors.New("CollectData: uninitialised query")
|
||||
}
|
||||
return MetricTime, nil
|
||||
}
|
||||
|
||||
func (m *FakePerformanceQuery) IsVistaOrNewer() bool {
|
||||
return m.vistaAndNewer
|
||||
}
|
||||
|
||||
func createPerfObject(measurement string, object string, instances []string, counters []string, failOnMissing bool, includeTotal bool) []perfobject {
|
||||
@@ -148,11 +219,11 @@ func TestAddItemSimple(t *testing.T) {
|
||||
expandPaths: map[string][]string{
|
||||
cps1[0]: cps1,
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.AddItem(cps1[0], "I", "test", false)
|
||||
err = m.AddItem(cps1[0], "O", "I", "c", "test", false)
|
||||
require.NoError(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
@@ -161,16 +232,16 @@ func TestAddItemSimple(t *testing.T) {
|
||||
func TestAddItemInvalidCountPath(t *testing.T) {
|
||||
var err error
|
||||
cps1 := []string{"\\O\\C"}
|
||||
m := Win_PerfCounters{PrintValid: false, Object: nil, query: &FakePerformanceQuery{
|
||||
m := Win_PerfCounters{PrintValid: false, Object: nil, UseWildcardsExpansion: true, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap(cps1, []float64{1.1}),
|
||||
expandPaths: map[string][]string{
|
||||
cps1[0]: {"\\O/C"},
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.AddItem("\\O\\C", "*", "test", false)
|
||||
err = m.AddItem("\\O\\C", "O", "------", "C", "test", false)
|
||||
require.Error(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
@@ -188,7 +259,7 @@ func TestParseConfigBasic(t *testing.T) {
|
||||
cps1[2]: {cps1[2]},
|
||||
cps1[3]: {cps1[3]},
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
@@ -197,19 +268,30 @@ func TestParseConfigBasic(t *testing.T) {
|
||||
assert.Len(t, m.counters, 4)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, m.counters, 4)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestParseConfigNoInstance(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"------"}, []string{"C1", "C2"}, false, false)
|
||||
cps1 := []string{"\\O\\C1", "\\O\\C2"}
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, UseWildcardsExpansion: false, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap(cps1, []float64{1.1, 1.2}),
|
||||
expandPaths: map[string][]string{
|
||||
cps1[0]: {cps1[0]},
|
||||
cps1[1]: {cps1[1]},
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
@@ -218,6 +300,17 @@ func TestParseConfigNoInstance(t *testing.T) {
|
||||
assert.Len(t, m.counters, 2)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, m.counters, 2)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestParseConfigInvalidCounterError(t *testing.T) {
|
||||
@@ -231,7 +324,7 @@ func TestParseConfigInvalidCounterError(t *testing.T) {
|
||||
cps1[1]: {cps1[1]},
|
||||
cps1[2]: {cps1[2]},
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
@@ -239,6 +332,16 @@ func TestParseConfigInvalidCounterError(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.ParseConfig()
|
||||
require.Error(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
||||
@@ -252,7 +355,7 @@ func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
||||
cps1[1]: {cps1[1]},
|
||||
cps1[2]: {cps1[2]},
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
@@ -260,18 +363,29 @@ func TestParseConfigInvalidCounterNoError(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
err = m.ParseConfig()
|
||||
require.NoError(t, err)
|
||||
err = m.query.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestParseConfigTotal(t *testing.T) {
|
||||
func TestParseConfigTotalExpansion(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, true, true)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
m := Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: true, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\*": cps1,
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
@@ -283,12 +397,12 @@ func TestParseConfigTotal(t *testing.T) {
|
||||
|
||||
perfObjects[0].IncludeTotal = false
|
||||
|
||||
m = Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
m = Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: true, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\*": cps1,
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
@@ -303,12 +417,12 @@ func TestParseConfigExpand(t *testing.T) {
|
||||
var err error
|
||||
perfObjects := createPerfObject("m", "O", []string{"*"}, []string{"*"}, false, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
m := Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: true, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\*": cps1,
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
err = m.query.Open()
|
||||
require.NoError(t, err)
|
||||
@@ -332,7 +446,7 @@ func TestSimpleGather(t *testing.T) {
|
||||
expandPaths: map[string][]string{
|
||||
cp1: {cp1},
|
||||
},
|
||||
addEnglishSupported: false,
|
||||
vistaAndNewer: false,
|
||||
}}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
@@ -346,6 +460,75 @@ func TestSimpleGather(t *testing.T) {
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
m.lastRefreshed = time.Time{}
|
||||
|
||||
var acc2 testutil.Accumulator
|
||||
|
||||
err = m.Gather(&acc2)
|
||||
require.NoError(t, err)
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
}
|
||||
|
||||
func TestSimpleGatherWithTimestamp(t *testing.T) {
|
||||
var err error
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false)
|
||||
cp1 := "\\O(I)\\C"
|
||||
m := Win_PerfCounters{PrintValid: false, UsePerfCounterTime: true, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap([]string{cp1}, []float64{1.2}),
|
||||
expandPaths: map[string][]string{
|
||||
cp1: {cp1},
|
||||
},
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
require.NoError(t, err)
|
||||
|
||||
fields1 := map[string]interface{}{
|
||||
"C": float32(1.2),
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I",
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
assert.True(t, acc1.HasTimestamp(measurement, MetricTime))
|
||||
}
|
||||
|
||||
func TestGatherError(t *testing.T) {
|
||||
var err error
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"I"}, []string{"C"}, false, false)
|
||||
cp1 := "\\O(I)\\C"
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap([]string{cp1}, []float64{-2}),
|
||||
expandPaths: map[string][]string{
|
||||
cp1: {cp1},
|
||||
},
|
||||
vistaAndNewer: false,
|
||||
}}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
require.Error(t, err)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
m.lastRefreshed = time.Time{}
|
||||
|
||||
var acc2 testutil.Accumulator
|
||||
|
||||
err = m.Gather(&acc2)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestGatherInvalidDataIgnore(t *testing.T) {
|
||||
@@ -363,7 +546,7 @@ func TestGatherInvalidDataIgnore(t *testing.T) {
|
||||
cps1[1]: {cps1[1]},
|
||||
cps1[2]: {cps1[2]},
|
||||
},
|
||||
addEnglishSupported: false,
|
||||
vistaAndNewer: false,
|
||||
}}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
@@ -377,24 +560,34 @@ func TestGatherInvalidDataIgnore(t *testing.T) {
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
m.UseWildcardsExpansion = true
|
||||
m.counters = nil
|
||||
m.lastRefreshed = time.Time{}
|
||||
|
||||
var acc2 testutil.Accumulator
|
||||
err = m.Gather(&acc2)
|
||||
require.NoError(t, err)
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
}
|
||||
|
||||
func TestGatherRefreshing(t *testing.T) {
|
||||
//tests with expansion
|
||||
func TestGatherRefreshingWithExpansion(t *testing.T) {
|
||||
var err error
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"*"}, false, false)
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"*"}, true, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
fpm := &FakePerformanceQuery{
|
||||
counters: createCounterMap(append(cps1, "\\O(*)\\*"), []float64{1.1, 1.2, 1.3, 1.4, 0}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\*": cps1,
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, query: fpm, CountersRefreshInterval: internal.Duration{Duration: time.Second * 10}}
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, UseWildcardsExpansion: true, query: fpm, CountersRefreshInterval: internal.Duration{Duration: time.Second * 10}}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
assert.Len(t, m.counters, 4)
|
||||
@@ -426,7 +619,7 @@ func TestGatherRefreshing(t *testing.T) {
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\*": cps2,
|
||||
},
|
||||
addEnglishSupported: true,
|
||||
vistaAndNewer: true,
|
||||
}
|
||||
m.query = fpm
|
||||
fpm.Open()
|
||||
@@ -463,3 +656,211 @@ func TestGatherRefreshing(t *testing.T) {
|
||||
acc3.AssertContainsTaggedFields(t, measurement, fields3, tags3)
|
||||
|
||||
}
|
||||
|
||||
func TestGatherRefreshingWithoutExpansion(t *testing.T) {
|
||||
var err error
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping long taking test in short mode")
|
||||
}
|
||||
measurement := "test"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, false)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2"}
|
||||
fpm := &FakePerformanceQuery{
|
||||
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2"}, cps1...), []float64{0, 0, 1.1, 1.2, 1.3, 1.4}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\C1": {cps1[0], cps1[2]},
|
||||
"\\O(*)\\C2": {cps1[1], cps1[3]},
|
||||
},
|
||||
vistaAndNewer: true,
|
||||
}
|
||||
m := Win_PerfCounters{PrintValid: false, Object: perfObjects, UseWildcardsExpansion: false, query: fpm, CountersRefreshInterval: internal.Duration{Duration: time.Second * 10}}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
assert.Len(t, m.counters, 2)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, acc1.Metrics, 2)
|
||||
|
||||
fields1 := map[string]interface{}{
|
||||
"C1": float32(1.1),
|
||||
"C2": float32(1.2),
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I1",
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
fields2 := map[string]interface{}{
|
||||
"C1": float32(1.3),
|
||||
"C2": float32(1.4),
|
||||
}
|
||||
tags2 := map[string]string{
|
||||
"instance": "I2",
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||
//test finding new instance
|
||||
cps2 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I2)\\C1", "\\O(I2)\\C2", "\\O(I3)\\C1", "\\O(I3)\\C2"}
|
||||
fpm = &FakePerformanceQuery{
|
||||
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2"}, cps2...), []float64{0, 0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\C1": {cps2[0], cps2[2], cps2[4]},
|
||||
"\\O(*)\\C2": {cps2[1], cps2[3], cps2[5]},
|
||||
},
|
||||
vistaAndNewer: true,
|
||||
}
|
||||
m.query = fpm
|
||||
fpm.Open()
|
||||
var acc2 testutil.Accumulator
|
||||
|
||||
fields3 := map[string]interface{}{
|
||||
"C1": float32(1.5),
|
||||
"C2": float32(1.6),
|
||||
}
|
||||
tags3 := map[string]string{
|
||||
"instance": "I3",
|
||||
"objectname": "O",
|
||||
}
|
||||
|
||||
//test before elapsing CounterRefreshRate counters are not refreshed
|
||||
err = m.Gather(&acc2)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, m.counters, 2)
|
||||
assert.Len(t, acc2.Metrics, 3)
|
||||
|
||||
acc2.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
acc2.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||
acc2.AssertContainsTaggedFields(t, measurement, fields3, tags3)
|
||||
//test changed configuration
|
||||
perfObjects = createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2", "C3"}, true, false)
|
||||
cps3 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(I1)\\C3", "\\O(I2)\\C1", "\\O(I2)\\C2", "\\O(I2)\\C3"}
|
||||
fpm = &FakePerformanceQuery{
|
||||
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2", "\\O(*)\\C3"}, cps3...), []float64{0, 0, 0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\C1": {cps3[0], cps3[3]},
|
||||
"\\O(*)\\C2": {cps3[1], cps3[4]},
|
||||
"\\O(*)\\C3": {cps3[2], cps3[5]},
|
||||
},
|
||||
vistaAndNewer: true,
|
||||
}
|
||||
m.query = fpm
|
||||
m.Object = perfObjects
|
||||
|
||||
fpm.Open()
|
||||
|
||||
time.Sleep(m.CountersRefreshInterval.Duration)
|
||||
|
||||
var acc3 testutil.Accumulator
|
||||
err = m.Gather(&acc3)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, acc3.Metrics, 2)
|
||||
fields4 := map[string]interface{}{
|
||||
"C1": float32(1.1),
|
||||
"C2": float32(1.2),
|
||||
"C3": float32(1.3),
|
||||
}
|
||||
tags4 := map[string]string{
|
||||
"instance": "I1",
|
||||
"objectname": "O",
|
||||
}
|
||||
fields5 := map[string]interface{}{
|
||||
"C1": float32(1.4),
|
||||
"C2": float32(1.5),
|
||||
"C3": float32(1.6),
|
||||
}
|
||||
tags5 := map[string]string{
|
||||
"instance": "I2",
|
||||
"objectname": "O",
|
||||
}
|
||||
|
||||
acc3.AssertContainsTaggedFields(t, measurement, fields4, tags4)
|
||||
acc3.AssertContainsTaggedFields(t, measurement, fields5, tags5)
|
||||
|
||||
}
|
||||
|
||||
func TestGatherTotalNoExpansion(t *testing.T) {
|
||||
var err error
|
||||
measurement := "m"
|
||||
perfObjects := createPerfObject(measurement, "O", []string{"*"}, []string{"C1", "C2"}, true, true)
|
||||
cps1 := []string{"\\O(I1)\\C1", "\\O(I1)\\C2", "\\O(_Total)\\C1", "\\O(_Total)\\C2"}
|
||||
m := Win_PerfCounters{PrintValid: false, UseWildcardsExpansion: false, Object: perfObjects, query: &FakePerformanceQuery{
|
||||
counters: createCounterMap(append([]string{"\\O(*)\\C1", "\\O(*)\\C2"}, cps1...), []float64{0, 0, 1.1, 1.2, 1.3, 1.4}),
|
||||
expandPaths: map[string][]string{
|
||||
"\\O(*)\\C1": {cps1[0], cps1[2]},
|
||||
"\\O(*)\\C2": {cps1[1], cps1[3]},
|
||||
},
|
||||
vistaAndNewer: true,
|
||||
}}
|
||||
var acc1 testutil.Accumulator
|
||||
err = m.Gather(&acc1)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, m.counters, 2)
|
||||
assert.Len(t, acc1.Metrics, 2)
|
||||
fields1 := map[string]interface{}{
|
||||
"C1": float32(1.1),
|
||||
"C2": float32(1.2),
|
||||
}
|
||||
tags1 := map[string]string{
|
||||
"instance": "I1",
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
fields2 := map[string]interface{}{
|
||||
"C1": float32(1.3),
|
||||
"C2": float32(1.4),
|
||||
}
|
||||
tags2 := map[string]string{
|
||||
"instance": "_Total",
|
||||
"objectname": "O",
|
||||
}
|
||||
acc1.AssertContainsTaggedFields(t, measurement, fields2, tags2)
|
||||
|
||||
perfObjects[0].IncludeTotal = false
|
||||
|
||||
m.counters = nil
|
||||
m.lastRefreshed = time.Time{}
|
||||
|
||||
var acc2 testutil.Accumulator
|
||||
err = m.Gather(&acc2)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, m.counters, 2)
|
||||
assert.Len(t, acc2.Metrics, 1)
|
||||
|
||||
acc2.AssertContainsTaggedFields(t, measurement, fields1, tags1)
|
||||
|
||||
acc2.AssertDoesNotContainsTaggedFields(t, measurement, fields2, tags2)
|
||||
}
|
||||
|
||||
// list of nul terminated strings from WinAPI
|
||||
var unicodeStringListWithEnglishChars = []uint16{0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x28, 0x30, 0x20, 0x43, 0x3a, 0x29, 0x5c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x28, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x29, 0x5c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0}
|
||||
var unicodeStringListWithCzechChars = []uint16{0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x46, 0x79, 0x7a, 0x69, 0x63, 0x6b, 0xfd, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x28, 0x30, 0x20, 0x43, 0x3a, 0x29, 0x5c, 0x41, 0x6b, 0x74, 0x75, 0xe1, 0x6c, 0x6e, 0xed, 0x20, 0x64, 0xe9, 0x6c, 0x6b, 0x61, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x75, 0x0, 0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x46, 0x79, 0x7a, 0x69, 0x63, 0x6b, 0xfd, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x28, 0x5f, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x29, 0x5c, 0x41, 0x6b, 0x74, 0x75, 0xe1, 0x6c, 0x6e, 0xed, 0x20, 0x64, 0xe9, 0x6c, 0x6b, 0x61, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x79, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x75, 0x0, 0x0}
|
||||
var unicodeStringListSingleItem = []uint16{0x5c, 0x5c, 0x54, 0x34, 0x38, 0x30, 0x5c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x44, 0x69, 0x73, 0x6b, 0x28, 0x30, 0x20, 0x43, 0x3a, 0x29, 0x5c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x0}
|
||||
var unicodeStringListNoItem = []uint16{0x0}
|
||||
|
||||
var stringArrayWithEnglishChars = []string{
|
||||
"\\\\T480\\PhysicalDisk(0 C:)\\Current Disk Queue Length",
|
||||
"\\\\T480\\PhysicalDisk(_Total)\\Current Disk Queue Length",
|
||||
}
|
||||
var stringArrayWithCzechChars = []string{
|
||||
"\\\\T480\\Fyzick\u00fd disk(0 C:)\\Aktu\u00e1ln\u00ed d\u00e9lka fronty disku",
|
||||
"\\\\T480\\Fyzick\u00fd disk(_Total)\\Aktu\u00e1ln\u00ed d\u00e9lka fronty disku",
|
||||
}
|
||||
|
||||
var stringArraySingleItem = []string{
|
||||
"\\\\T480\\PhysicalDisk(0 C:)\\Current Disk Queue Length",
|
||||
}
|
||||
|
||||
func TestUTF16ToStringArray(t *testing.T) {
|
||||
singleItem := UTF16ToStringArray(unicodeStringListSingleItem)
|
||||
assert.True(t, assert.ObjectsAreEqual(singleItem, stringArraySingleItem), "Not equal single arrays")
|
||||
|
||||
noItem := UTF16ToStringArray(unicodeStringListNoItem)
|
||||
assert.Nil(t, noItem)
|
||||
|
||||
engStrings := UTF16ToStringArray(unicodeStringListWithEnglishChars)
|
||||
assert.True(t, assert.ObjectsAreEqual(engStrings, stringArrayWithEnglishChars), "Not equal eng arrays")
|
||||
|
||||
czechStrings := UTF16ToStringArray(unicodeStringListWithCzechChars)
|
||||
assert.True(t, assert.ObjectsAreEqual(czechStrings, stringArrayWithCzechChars), "Not equal czech arrays")
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf/plugins/inputs/zipkin/trace"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
|
||||
)
|
||||
|
||||
//now is a mockable time for now
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf/plugins/inputs/zipkin/codec"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
|
||||
)
|
||||
|
||||
// JSON decodes spans from bodies `POST`ed to the spans endpoint
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/influxdata/telegraf/plugins/inputs/zipkin/codec"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
|
||||
)
|
||||
|
||||
// UnmarshalThrift converts raw bytes in thrift format to a slice of spans
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
|
||||
"github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
|
||||
)
|
||||
|
||||
func Test_endpointHost(t *testing.T) {
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestPartitionKey(t *testing.T) {
|
||||
partitionKey := k.getPartitionKey(testPoint)
|
||||
u, err := uuid.FromString(partitionKey)
|
||||
assert.Nil(err, "Issue parsing UUID")
|
||||
assert.Equal(uint(4), u.Version(), "PartitionKey should be UUIDv4")
|
||||
assert.Equal(byte(4), u.Version(), "PartitionKey should be UUIDv4")
|
||||
|
||||
k = KinesisOutput{
|
||||
PartitionKey: "-",
|
||||
@@ -72,6 +72,5 @@ func TestPartitionKey(t *testing.T) {
|
||||
partitionKey = k.getPartitionKey(testPoint)
|
||||
u, err = uuid.FromString(partitionKey)
|
||||
assert.Nil(err, "Issue parsing UUID")
|
||||
assert.Equal(uint(4), u.Version(), "PartitionKey should be UUIDv4")
|
||||
|
||||
assert.Equal(byte(4), u.Version(), "PartitionKey should be UUIDv4")
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ func (m *MQTT) publish(topic string, body []byte) error {
|
||||
|
||||
func (m *MQTT) createOpts() (*paho.ClientOptions, error) {
|
||||
opts := paho.NewClientOptions()
|
||||
opts.KeepAlive = 0 * time.Second
|
||||
opts.KeepAlive = 0
|
||||
|
||||
if m.Timeout.Duration < time.Second {
|
||||
m.Timeout.Duration = 5 * time.Second
|
||||
|
||||
@@ -3,7 +3,7 @@ package nats
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
nats_client "github.com/nats-io/nats"
|
||||
nats_client "github.com/nats-io/go-nats"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal/tls"
|
||||
|
||||
@@ -22,6 +22,7 @@ var (
|
||||
`%`, "-",
|
||||
"#", "-",
|
||||
"$", "-")
|
||||
defaultHttpPath = "/api/put"
|
||||
defaultSeperator = "_"
|
||||
)
|
||||
|
||||
@@ -31,7 +32,8 @@ type OpenTSDB struct {
|
||||
Host string
|
||||
Port int
|
||||
|
||||
HttpBatchSize int
|
||||
HttpBatchSize int // deprecated httpBatchSize form in 1.8
|
||||
HttpPath string
|
||||
|
||||
Debug bool
|
||||
|
||||
@@ -52,7 +54,11 @@ var sampleConfig = `
|
||||
|
||||
## Number of data points to send to OpenTSDB in Http requests.
|
||||
## Not used with telnet API.
|
||||
httpBatchSize = 50
|
||||
http_batch_size = 50
|
||||
|
||||
## URI Path for Http requests to OpenTSDB.
|
||||
## Used in cases where OpenTSDB is located behind a reverse proxy.
|
||||
http_path = "/api/put"
|
||||
|
||||
## Debug true - Prints OpenTSDB communication
|
||||
debug = false
|
||||
@@ -121,6 +127,7 @@ func (o *OpenTSDB) WriteHttp(metrics []telegraf.Metric, u *url.URL) error {
|
||||
Scheme: u.Scheme,
|
||||
User: u.User,
|
||||
BatchSize: o.HttpBatchSize,
|
||||
Path: o.HttpPath,
|
||||
Debug: o.Debug,
|
||||
}
|
||||
|
||||
@@ -260,6 +267,7 @@ func sanitize(value string) string {
|
||||
func init() {
|
||||
outputs.Add("opentsdb", func() telegraf.Output {
|
||||
return &OpenTSDB{
|
||||
HttpPath: defaultHttpPath,
|
||||
Separator: defaultSeperator,
|
||||
}
|
||||
})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user