Add prometheus remote write serializer (#8360)
This commit is contained in:
parent
945b556330
commit
045c3c18b8
|
|
@ -71,6 +71,7 @@ following works:
|
||||||
- github.com/googleapis/gax-go [BSD 3-Clause "New" or "Revised" License](https://github.com/googleapis/gax-go/blob/master/LICENSE)
|
- github.com/googleapis/gax-go [BSD 3-Clause "New" or "Revised" License](https://github.com/googleapis/gax-go/blob/master/LICENSE)
|
||||||
- github.com/gopcua/opcua [MIT License](https://github.com/gopcua/opcua/blob/master/LICENSE)
|
- github.com/gopcua/opcua [MIT License](https://github.com/gopcua/opcua/blob/master/LICENSE)
|
||||||
- github.com/gorilla/mux [BSD 3-Clause "New" or "Revised" License](https://github.com/gorilla/mux/blob/master/LICENSE)
|
- github.com/gorilla/mux [BSD 3-Clause "New" or "Revised" License](https://github.com/gorilla/mux/blob/master/LICENSE)
|
||||||
|
- github.com/grpc-ecosystem/grpc-gateway [BSD 3-Clause "New" or "Revised" License](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt)
|
||||||
- github.com/hailocab/go-hostpool [MIT License](https://github.com/hailocab/go-hostpool/blob/master/LICENSE)
|
- github.com/hailocab/go-hostpool [MIT License](https://github.com/hailocab/go-hostpool/blob/master/LICENSE)
|
||||||
- github.com/harlow/kinesis-consumer [MIT License](https://github.com/harlow/kinesis-consumer/blob/master/MIT-LICENSE)
|
- github.com/harlow/kinesis-consumer [MIT License](https://github.com/harlow/kinesis-consumer/blob/master/MIT-LICENSE)
|
||||||
- github.com/hashicorp/consul [Mozilla Public License 2.0](https://github.com/hashicorp/consul/blob/master/LICENSE)
|
- github.com/hashicorp/consul [Mozilla Public License 2.0](https://github.com/hashicorp/consul/blob/master/LICENSE)
|
||||||
|
|
@ -122,6 +123,7 @@ following works:
|
||||||
- github.com/prometheus/client_model [Apache License 2.0](https://github.com/prometheus/client_model/blob/master/LICENSE)
|
- github.com/prometheus/client_model [Apache License 2.0](https://github.com/prometheus/client_model/blob/master/LICENSE)
|
||||||
- github.com/prometheus/common [Apache License 2.0](https://github.com/prometheus/common/blob/master/LICENSE)
|
- github.com/prometheus/common [Apache License 2.0](https://github.com/prometheus/common/blob/master/LICENSE)
|
||||||
- github.com/prometheus/procfs [Apache License 2.0](https://github.com/prometheus/procfs/blob/master/LICENSE)
|
- github.com/prometheus/procfs [Apache License 2.0](https://github.com/prometheus/procfs/blob/master/LICENSE)
|
||||||
|
- github.com/prometheus/prometheus [Apache License 2.0](https://github.com/prometheus/prometheus/blob/master/LICENSE)
|
||||||
- github.com/rcrowley/go-metrics [MIT License](https://github.com/rcrowley/go-metrics/blob/master/LICENSE)
|
- github.com/rcrowley/go-metrics [MIT License](https://github.com/rcrowley/go-metrics/blob/master/LICENSE)
|
||||||
- github.com/riemann/riemann-go-client [MIT License](https://github.com/riemann/riemann-go-client/blob/master/LICENSE)
|
- github.com/riemann/riemann-go-client [MIT License](https://github.com/riemann/riemann-go-client/blob/master/LICENSE)
|
||||||
- github.com/safchain/ethtool [Apache License 2.0](https://github.com/safchain/ethtool/blob/master/LICENSE)
|
- github.com/safchain/ethtool [Apache License 2.0](https://github.com/safchain/ethtool/blob/master/LICENSE)
|
||||||
|
|
|
||||||
7
go.mod
7
go.mod
|
|
@ -61,10 +61,12 @@ require (
|
||||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d
|
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d
|
||||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec
|
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec
|
||||||
github.com/golang/protobuf v1.3.5
|
github.com/golang/protobuf v1.3.5
|
||||||
|
github.com/golang/snappy v0.0.1
|
||||||
github.com/google/go-cmp v0.5.2
|
github.com/google/go-cmp v0.5.2
|
||||||
github.com/google/go-github/v32 v32.1.0
|
github.com/google/go-github/v32 v32.1.0
|
||||||
github.com/gopcua/opcua v0.1.12
|
github.com/gopcua/opcua v0.1.12
|
||||||
github.com/gorilla/mux v1.6.2
|
github.com/gorilla/mux v1.6.2
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
|
||||||
github.com/harlow/kinesis-consumer v0.3.1-0.20181230152818-2f58b136fee0
|
github.com/harlow/kinesis-consumer v0.3.1-0.20181230152818-2f58b136fee0
|
||||||
github.com/hashicorp/consul v1.2.1
|
github.com/hashicorp/consul v1.2.1
|
||||||
|
|
@ -108,6 +110,7 @@ require (
|
||||||
github.com/prometheus/client_model v0.2.0
|
github.com/prometheus/client_model v0.2.0
|
||||||
github.com/prometheus/common v0.9.1
|
github.com/prometheus/common v0.9.1
|
||||||
github.com/prometheus/procfs v0.0.8
|
github.com/prometheus/procfs v0.0.8
|
||||||
|
github.com/prometheus/prometheus v2.5.0+incompatible
|
||||||
github.com/riemann/riemann-go-client v0.5.0
|
github.com/riemann/riemann-go-client v0.5.0
|
||||||
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664
|
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect
|
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect
|
||||||
|
|
@ -142,8 +145,8 @@ require (
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200205215550-e35592f146e4
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200205215550-e35592f146e4
|
||||||
gonum.org/v1/gonum v0.6.2 // indirect
|
gonum.org/v1/gonum v0.6.2 // indirect
|
||||||
google.golang.org/api v0.20.0
|
google.golang.org/api v0.20.0
|
||||||
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884
|
||||||
google.golang.org/grpc v1.28.0
|
google.golang.org/grpc v1.33.1
|
||||||
gopkg.in/fatih/pool.v2 v2.0.0 // indirect
|
gopkg.in/fatih/pool.v2 v2.0.0 // indirect
|
||||||
gopkg.in/gorethink/gorethink.v3 v3.0.5
|
gopkg.in/gorethink/gorethink.v3 v3.0.5
|
||||||
gopkg.in/ldap.v3 v3.1.0
|
gopkg.in/ldap.v3 v3.1.0
|
||||||
|
|
|
||||||
19
go.sum
19
go.sum
|
|
@ -103,6 +103,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1C
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/amir/raidman v0.0.0-20170415203553-1ccc43bfb9c9 h1:FXrPTd8Rdlc94dKccl7KPmdmIbVh/OjelJ8/vgMRzcQ=
|
github.com/amir/raidman v0.0.0-20170415203553-1ccc43bfb9c9 h1:FXrPTd8Rdlc94dKccl7KPmdmIbVh/OjelJ8/vgMRzcQ=
|
||||||
github.com/amir/raidman v0.0.0-20170415203553-1ccc43bfb9c9/go.mod h1:eliMa/PW+RDr2QLWRmLH1R1ZA4RInpmvOzDDXtaIZkc=
|
github.com/amir/raidman v0.0.0-20170415203553-1ccc43bfb9c9/go.mod h1:eliMa/PW+RDr2QLWRmLH1R1ZA4RInpmvOzDDXtaIZkc=
|
||||||
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
|
github.com/apache/thrift v0.12.0 h1:pODnxUFNcjP9UTLZGTdeh+j16A8lJbRvD3rOtrk/7bs=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3 h1:Bmjk+DjIi3tTAU0wxGaFbfjGUqlxxSXARq9A96Kgoos=
|
github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3 h1:Bmjk+DjIi3tTAU0wxGaFbfjGUqlxxSXARq9A96Kgoos=
|
||||||
|
|
@ -204,6 +205,7 @@ github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
|
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
|
||||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||||
github.com/glinton/ping v0.1.4-0.20200311211934-5ac87da8cd96 h1:YpooqMW354GG47PXNBiaCv6yCQizyP3MXD9NUPrCEQ8=
|
github.com/glinton/ping v0.1.4-0.20200311211934-5ac87da8cd96 h1:YpooqMW354GG47PXNBiaCv6yCQizyP3MXD9NUPrCEQ8=
|
||||||
|
|
@ -300,6 +302,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||||
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc=
|
github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||||
|
|
@ -311,6 +315,8 @@ github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
github.com/harlow/kinesis-consumer v0.3.1-0.20181230152818-2f58b136fee0 h1:U0KvGD9CJIl1nbgu9yLsfWxMT6WqL8fG0IBB7RvOZZQ=
|
github.com/harlow/kinesis-consumer v0.3.1-0.20181230152818-2f58b136fee0 h1:U0KvGD9CJIl1nbgu9yLsfWxMT6WqL8fG0IBB7RvOZZQ=
|
||||||
|
|
@ -534,6 +540,8 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
|
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
|
||||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||||
|
github.com/prometheus/prometheus v2.5.0+incompatible h1:7QPitgO2kOFG8ecuRn9O/4L9+10He72rVRJvMXrE9Hg=
|
||||||
|
github.com/prometheus/prometheus v2.5.0+incompatible/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||||
|
|
@ -542,6 +550,7 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/riemann/riemann-go-client v0.5.0 h1:yPP7tz1vSYJkSZvZFCsMiDsHHXX57x8/fEX3qyEXuAA=
|
github.com/riemann/riemann-go-client v0.5.0 h1:yPP7tz1vSYJkSZvZFCsMiDsHHXX57x8/fEX3qyEXuAA=
|
||||||
github.com/riemann/riemann-go-client v0.5.0/go.mod h1:FMiaOL8dgBnRfgwENzV0xlYJ2eCbV1o7yqVwOBLbShQ=
|
github.com/riemann/riemann-go-client v0.5.0/go.mod h1:FMiaOL8dgBnRfgwENzV0xlYJ2eCbV1o7yqVwOBLbShQ=
|
||||||
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664 h1:gvolwzuDhul9qK6/oHqxCHD5TEYfsWNBGidOeG6kvpk=
|
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664 h1:gvolwzuDhul9qK6/oHqxCHD5TEYfsWNBGidOeG6kvpk=
|
||||||
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||||
|
|
@ -698,6 +707,7 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
|
@ -856,8 +866,8 @@ google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvx
|
||||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24 h1:IGPykv426z7LZSVPlaPufOyphngM4at5uZ7x5alaFvE=
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 h1:fiNLklpBwWK1mth30Hlwk+fcdBmIALlgF5iy77O37Ig=
|
||||||
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
|
@ -868,8 +878,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
|
google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
|
||||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||||
|
|
@ -914,6 +924,7 @@ gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 h1:yiW+nvdHb9LVqSHQBXfZCieqV
|
||||||
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk=
|
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Prometheus
|
||||||
|
|
||||||
|
The `prometheusremotewrite` data format converts metrics into the Prometheus protobuf
|
||||||
|
exposition format.
|
||||||
|
|
||||||
|
**Warning**: When generating histogram and summary types, output may
|
||||||
|
not be correct if the metric spans multiple batches. This issue can be
|
||||||
|
somewhat, but not fully, mitigated by using outputs that support writing in
|
||||||
|
"batch format". When using histogram and summary types, it is recommended to
|
||||||
|
use only the `prometheus_client` output.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[outputs.http]]
|
||||||
|
url = "https://cortex/api/prom/push"
|
||||||
|
data_format = "prometheusremotewrite"
|
||||||
|
tls_ca = "/etc/telegraf/ca.pem"
|
||||||
|
tls_cert = "/etc/telegraf/cert.pem"
|
||||||
|
tls_key = "/etc/telegraf/key.pem"
|
||||||
|
[outputs.http.headers]
|
||||||
|
Content-Type = "application/x-protobuf"
|
||||||
|
Content-Encoding = "snappy"
|
||||||
|
X-Prometheus-Remote-Write-Version = "0.1.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Metrics
|
||||||
|
|
||||||
|
A Prometheus metric is created for each integer, float, boolean or unsigned
|
||||||
|
field. Boolean values are converted to *1.0* for true and *0.0* for false.
|
||||||
|
|
||||||
|
The Prometheus metric names are produced by joining the measurement name with
|
||||||
|
the field key. In the special case where the measurement name is `prometheus`
|
||||||
|
it is not included in the final metric name.
|
||||||
|
|
||||||
|
Prometheus labels are produced for each tag.
|
||||||
|
|
||||||
|
**Note:** String fields are ignored and do not produce Prometheus metrics.
|
||||||
|
|
@ -0,0 +1,341 @@
|
||||||
|
package prometheusremotewrite
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
|
"github.com/golang/snappy"
|
||||||
|
"github.com/influxdata/telegraf/plugins/serializers/prometheus"
|
||||||
|
"hash/fnv"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/prometheus/prometheus/prompb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MetricKey uint64
|
||||||
|
|
||||||
|
// MetricSortOrder controls if the output is sorted.
|
||||||
|
type MetricSortOrder int
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoSortMetrics MetricSortOrder = iota
|
||||||
|
SortMetrics
|
||||||
|
)
|
||||||
|
|
||||||
|
// StringHandling defines how to process string fields.
|
||||||
|
type StringHandling int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DiscardStrings StringHandling = iota
|
||||||
|
StringAsLabel
|
||||||
|
)
|
||||||
|
|
||||||
|
type FormatConfig struct {
|
||||||
|
MetricSortOrder MetricSortOrder
|
||||||
|
StringHandling StringHandling
|
||||||
|
}
|
||||||
|
|
||||||
|
type Serializer struct {
|
||||||
|
config FormatConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSerializer(config FormatConfig) (*Serializer, error) {
|
||||||
|
s := &Serializer{config: config}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Serializer) Serialize(metric telegraf.Metric) ([]byte, error) {
|
||||||
|
return s.SerializeBatch([]telegraf.Metric{metric})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Serializer) SerializeBatch(metrics []telegraf.Metric) ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
var entries = make(map[MetricKey]*prompb.TimeSeries)
|
||||||
|
for _, metric := range metrics {
|
||||||
|
commonLabels := s.createLabels(metric)
|
||||||
|
var metrickey MetricKey
|
||||||
|
var promts *prompb.TimeSeries
|
||||||
|
for _, field := range metric.FieldList() {
|
||||||
|
metricName := prometheus.MetricName(metric.Name(), field.Key, metric.Type())
|
||||||
|
metricName, ok := prometheus.SanitizeMetricName(metricName)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch metric.Type() {
|
||||||
|
case telegraf.Counter:
|
||||||
|
fallthrough
|
||||||
|
case telegraf.Gauge:
|
||||||
|
fallthrough
|
||||||
|
case telegraf.Untyped:
|
||||||
|
value, ok := prometheus.SampleValue(field.Value)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
metrickey, promts = getPromTS(metricName, commonLabels, value, metric.Time())
|
||||||
|
case telegraf.Histogram:
|
||||||
|
switch {
|
||||||
|
case strings.HasSuffix(field.Key, "_bucket"):
|
||||||
|
// if bucket only, init sum, count, inf
|
||||||
|
metrickeysum, promtssum := getPromTS(fmt.Sprintf("%s_sum", metricName), commonLabels, float64(0), metric.Time())
|
||||||
|
if _, ok = entries[metrickeysum]; !ok {
|
||||||
|
entries[metrickeysum] = promtssum
|
||||||
|
}
|
||||||
|
metrickeycount, promtscount := getPromTS(fmt.Sprintf("%s_count", metricName), commonLabels, float64(0), metric.Time())
|
||||||
|
if _, ok = entries[metrickeycount]; !ok {
|
||||||
|
entries[metrickeycount] = promtscount
|
||||||
|
}
|
||||||
|
labels := make([]*prompb.Label, len(commonLabels), len(commonLabels)+1)
|
||||||
|
copy(labels, commonLabels)
|
||||||
|
labels = append(labels, &prompb.Label{
|
||||||
|
Name: "le",
|
||||||
|
Value: "+Inf",
|
||||||
|
})
|
||||||
|
metrickeyinf, promtsinf := getPromTS(fmt.Sprintf("%s_bucket", metricName), labels, float64(0), metric.Time())
|
||||||
|
if _, ok = entries[metrickeyinf]; !ok {
|
||||||
|
entries[metrickeyinf] = promtsinf
|
||||||
|
}
|
||||||
|
|
||||||
|
le, ok := metric.GetTag("le")
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
bound, err := strconv.ParseFloat(le, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
count, ok := prometheus.SampleCount(field.Value)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
labels = make([]*prompb.Label, len(commonLabels), len(commonLabels)+1)
|
||||||
|
copy(labels, commonLabels)
|
||||||
|
labels = append(labels, &prompb.Label{
|
||||||
|
Name: "le",
|
||||||
|
Value: fmt.Sprint(bound),
|
||||||
|
})
|
||||||
|
metrickey, promts = getPromTS(fmt.Sprintf("%s_bucket", metricName), labels, float64(count), metric.Time())
|
||||||
|
case strings.HasSuffix(field.Key, "_sum"):
|
||||||
|
sum, ok := prometheus.SampleSum(field.Value)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
metrickey, promts = getPromTS(fmt.Sprintf("%s_sum", metricName), commonLabels, sum, metric.Time())
|
||||||
|
case strings.HasSuffix(field.Key, "_count"):
|
||||||
|
count, ok := prometheus.SampleCount(field.Value)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no bucket generate +Inf entry
|
||||||
|
labels := make([]*prompb.Label, len(commonLabels), len(commonLabels)+1)
|
||||||
|
copy(labels, commonLabels)
|
||||||
|
labels = append(labels, &prompb.Label{
|
||||||
|
Name: "le",
|
||||||
|
Value: "+Inf",
|
||||||
|
})
|
||||||
|
metrickeyinf, promtsinf := getPromTS(fmt.Sprintf("%s_bucket", metricName), labels, float64(count), metric.Time())
|
||||||
|
if minf, ok := entries[metrickeyinf]; !ok || minf.Samples[0].Value == 0 {
|
||||||
|
entries[metrickeyinf] = promtsinf
|
||||||
|
}
|
||||||
|
|
||||||
|
metrickey, promts = getPromTS(fmt.Sprintf("%s_count", metricName), commonLabels, float64(count), metric.Time())
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case telegraf.Summary:
|
||||||
|
switch {
|
||||||
|
case strings.HasSuffix(field.Key, "_sum"):
|
||||||
|
sum, ok := prometheus.SampleSum(field.Value)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
metrickey, promts = getPromTS(fmt.Sprintf("%s_sum", metricName), commonLabels, sum, metric.Time())
|
||||||
|
case strings.HasSuffix(field.Key, "_count"):
|
||||||
|
count, ok := prometheus.SampleCount(field.Value)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
metrickey, promts = getPromTS(fmt.Sprintf("%s_count", metricName), commonLabels, float64(count), metric.Time())
|
||||||
|
default:
|
||||||
|
quantileTag, ok := metric.GetTag("quantile")
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
quantile, err := strconv.ParseFloat(quantileTag, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value, ok := prometheus.SampleValue(field.Value)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := make([]*prompb.Label, len(commonLabels), len(commonLabels)+1)
|
||||||
|
copy(labels, commonLabels)
|
||||||
|
labels = append(labels, &prompb.Label{
|
||||||
|
Name: "quantile",
|
||||||
|
Value: fmt.Sprint(quantile),
|
||||||
|
})
|
||||||
|
metrickey, promts = getPromTS(metricName, labels, value, metric.Time())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Unknown type %v", metric.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// A batch of metrics can contain multiple values for a single
|
||||||
|
// Prometheus sample. If this metric is older than the existing
|
||||||
|
// sample then we can skip over it.
|
||||||
|
m, ok := entries[metrickey]
|
||||||
|
if ok {
|
||||||
|
if metric.Time().Before(time.Unix(m.Samples[0].Timestamp, 0)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entries[metrickey] = promts
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var promTS = make([]*prompb.TimeSeries, len(entries))
|
||||||
|
var i int64 = 0
|
||||||
|
for _, promts := range entries {
|
||||||
|
promTS[i] = promts
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
switch s.config.MetricSortOrder {
|
||||||
|
case SortMetrics:
|
||||||
|
sort.Slice(promTS, func(i, j int) bool {
|
||||||
|
lhs := promTS[i].Labels
|
||||||
|
rhs := promTS[j].Labels
|
||||||
|
if len(lhs) != len(rhs) {
|
||||||
|
return len(lhs) < len(rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
for index := range lhs {
|
||||||
|
l := lhs[index]
|
||||||
|
r := rhs[index]
|
||||||
|
|
||||||
|
if l.Name != r.Name {
|
||||||
|
return l.Name < r.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.Value != r.Value {
|
||||||
|
return l.Value < r.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
data, err := proto.Marshal(&prompb.WriteRequest{Timeseries: promTS})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to marshal protobuf: %v", err)
|
||||||
|
}
|
||||||
|
encoded := snappy.Encode(nil, data)
|
||||||
|
buf.Write(encoded)
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasLabel(name string, labels []*prompb.Label) bool {
|
||||||
|
for _, label := range labels {
|
||||||
|
if name == label.Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Serializer) createLabels(metric telegraf.Metric) []*prompb.Label {
|
||||||
|
labels := make([]*prompb.Label, 0, len(metric.TagList()))
|
||||||
|
for _, tag := range metric.TagList() {
|
||||||
|
// Ignore special tags for histogram and summary types.
|
||||||
|
switch metric.Type() {
|
||||||
|
case telegraf.Histogram:
|
||||||
|
if tag.Key == "le" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case telegraf.Summary:
|
||||||
|
if tag.Key == "quantile" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name, ok := prometheus.SanitizeLabelName(tag.Key)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
labels = append(labels, &prompb.Label{Name: name, Value: tag.Value})
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.config.StringHandling != StringAsLabel {
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
addedFieldLabel := false
|
||||||
|
for _, field := range metric.FieldList() {
|
||||||
|
value, ok := field.Value.(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name, ok := prometheus.SanitizeLabelName(field.Key)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a tag with the same name as the string field, discard
|
||||||
|
// the field and use the tag instead.
|
||||||
|
if hasLabel(name, labels) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
labels = append(labels, &prompb.Label{Name: name, Value: value})
|
||||||
|
addedFieldLabel = true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if addedFieldLabel {
|
||||||
|
sort.Slice(labels, func(i, j int) bool {
|
||||||
|
return labels[i].Name < labels[j].Name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeMetricKey(labels []*prompb.Label) MetricKey {
|
||||||
|
h := fnv.New64a()
|
||||||
|
for _, label := range labels {
|
||||||
|
h.Write([]byte(label.Name))
|
||||||
|
h.Write([]byte("\x00"))
|
||||||
|
h.Write([]byte(label.Value))
|
||||||
|
h.Write([]byte("\x00"))
|
||||||
|
}
|
||||||
|
return MetricKey(h.Sum64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPromTS(name string, labels []*prompb.Label, value float64, ts time.Time) (MetricKey, *prompb.TimeSeries) {
|
||||||
|
sample := []prompb.Sample{{
|
||||||
|
// Timestamp is int milliseconds for remote write.
|
||||||
|
Timestamp: ts.UnixNano() / int64(time.Millisecond),
|
||||||
|
Value: value,
|
||||||
|
}}
|
||||||
|
labelscopy := make([]*prompb.Label, len(labels), len(labels)+1)
|
||||||
|
copy(labelscopy, labels)
|
||||||
|
labels = append(labelscopy, &prompb.Label{
|
||||||
|
Name: "__name__",
|
||||||
|
Value: name,
|
||||||
|
})
|
||||||
|
return MakeMetricKey(labels), &prompb.TimeSeries{Labels: labels, Samples: sample}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,674 @@
|
||||||
|
package prometheusremotewrite
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
|
"github.com/golang/snappy"
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
|
"github.com/prometheus/prometheus/prompb"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/testutil"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRemoteWriteSerialize(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config FormatConfig
|
||||||
|
metric telegraf.Metric
|
||||||
|
expected []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple",
|
||||||
|
metric: testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"host": "example.org",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle{host="example.org"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prometheus input untyped",
|
||||||
|
metric: testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{
|
||||||
|
"code": "400",
|
||||||
|
"method": "post",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_requests_total": 3.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Untyped,
|
||||||
|
),
|
||||||
|
expected: []byte(`
|
||||||
|
http_requests_total{code="400", method="post"} 3
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prometheus input counter",
|
||||||
|
metric: testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{
|
||||||
|
"code": "400",
|
||||||
|
"method": "post",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_requests_total": 3.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Counter,
|
||||||
|
),
|
||||||
|
expected: []byte(`
|
||||||
|
http_requests_total{code="400", method="post"} 3
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prometheus input gauge",
|
||||||
|
metric: testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{
|
||||||
|
"code": "400",
|
||||||
|
"method": "post",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_requests_total": 3.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Gauge,
|
||||||
|
),
|
||||||
|
expected: []byte(`
|
||||||
|
http_requests_total{code="400", method="post"} 3
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prometheus input histogram no buckets",
|
||||||
|
metric: testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_sum": 53423,
|
||||||
|
"http_request_duration_seconds_count": 144320,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
expected: []byte(`
|
||||||
|
http_request_duration_seconds_count 144320
|
||||||
|
http_request_duration_seconds_sum 53423
|
||||||
|
http_request_duration_seconds_bucket{le="+Inf"} 144320
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prometheus input histogram only bucket",
|
||||||
|
metric: testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{
|
||||||
|
"le": "0.5",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_bucket": 129389.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
expected: []byte(`
|
||||||
|
http_request_duration_seconds_count 0
|
||||||
|
http_request_duration_seconds_sum 0
|
||||||
|
http_request_duration_seconds_bucket{le="+Inf"} 0
|
||||||
|
http_request_duration_seconds_bucket{le="0.5"} 129389
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
s, err := NewSerializer(FormatConfig{
|
||||||
|
MetricSortOrder: SortMetrics,
|
||||||
|
StringHandling: tt.config.StringHandling,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
data, err := s.Serialize(tt.metric)
|
||||||
|
actual, err := prompbToText(data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, strings.TrimSpace(string(tt.expected)),
|
||||||
|
strings.TrimSpace(string(actual)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteWriteSerializeBatch(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
config FormatConfig
|
||||||
|
metrics []telegraf.Metric
|
||||||
|
expected []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"host": "one.example.org",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"host": "two.example.org",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle{host="one.example.org"} 42
|
||||||
|
cpu_time_idle{host="two.example.org"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple metric families",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"host": "one.example.org",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
"time_guest": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_guest{host="one.example.org"} 42
|
||||||
|
cpu_time_idle{host="one.example.org"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "histogram",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_sum": 53423,
|
||||||
|
"http_request_duration_seconds_count": 144320,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"le": "0.05"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_bucket": 24054.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"le": "0.1"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_bucket": 33444.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"le": "0.2"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_bucket": 100392.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"le": "0.5"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_bucket": 129389.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"le": "1.0"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_bucket": 133988.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"le": "+Inf"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"http_request_duration_seconds_bucket": 144320.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Histogram,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
http_request_duration_seconds_count 144320
|
||||||
|
http_request_duration_seconds_sum 53423
|
||||||
|
http_request_duration_seconds_bucket{le="+Inf"} 144320
|
||||||
|
http_request_duration_seconds_bucket{le="0.05"} 24054
|
||||||
|
http_request_duration_seconds_bucket{le="0.1"} 33444
|
||||||
|
http_request_duration_seconds_bucket{le="0.2"} 100392
|
||||||
|
http_request_duration_seconds_bucket{le="0.5"} 129389
|
||||||
|
http_request_duration_seconds_bucket{le="1"} 133988
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "summary with quantile",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"rpc_duration_seconds_sum": 1.7560473e+07,
|
||||||
|
"rpc_duration_seconds_count": 2693,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Summary,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"quantile": "0.01"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"rpc_duration_seconds": 3102.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Summary,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"quantile": "0.05"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"rpc_duration_seconds": 3272.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Summary,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"quantile": "0.5"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"rpc_duration_seconds": 4773.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Summary,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"quantile": "0.9"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"rpc_duration_seconds": 9001.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Summary,
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{"quantile": "0.99"},
|
||||||
|
map[string]interface{}{
|
||||||
|
"rpc_duration_seconds": 76656.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Summary,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
rpc_duration_seconds_count 2693
|
||||||
|
rpc_duration_seconds_sum 17560473
|
||||||
|
rpc_duration_seconds{quantile="0.01"} 3102
|
||||||
|
rpc_duration_seconds{quantile="0.05"} 3272
|
||||||
|
rpc_duration_seconds{quantile="0.5"} 4773
|
||||||
|
rpc_duration_seconds{quantile="0.9"} 9001
|
||||||
|
rpc_duration_seconds{quantile="0.99"} 76656
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "newer sample",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 43.0,
|
||||||
|
},
|
||||||
|
time.Unix(1, 0),
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle 43
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "colons are not replaced in metric name from measurement",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu::xyzzy",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu::xyzzy_time_idle 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "colons are not replaced in metric name from field",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time:idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time:idle 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid label",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"host-name": "example.org",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle{host_name="example.org"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "colons are replaced in label name",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"host:name": "example.org",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle{host_name="example.org"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "discard strings",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
"cpu": "cpu0",
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string as label",
|
||||||
|
config: FormatConfig{
|
||||||
|
MetricSortOrder: SortMetrics,
|
||||||
|
StringHandling: StringAsLabel,
|
||||||
|
},
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
"cpu": "cpu0",
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle{cpu="cpu0"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string as label duplicate tag",
|
||||||
|
config: FormatConfig{
|
||||||
|
MetricSortOrder: SortMetrics,
|
||||||
|
StringHandling: StringAsLabel,
|
||||||
|
},
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"cpu": "cpu0",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_idle": 42.0,
|
||||||
|
"cpu": "cpu1",
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle{cpu="cpu0"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "replace characters when using string as label",
|
||||||
|
config: FormatConfig{
|
||||||
|
MetricSortOrder: SortMetrics,
|
||||||
|
StringHandling: StringAsLabel,
|
||||||
|
},
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"host:name": "example.org",
|
||||||
|
"time_idle": 42.0,
|
||||||
|
},
|
||||||
|
time.Unix(1574279268, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_idle{host_name="example.org"} 42
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple fields grouping",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"cpu": "cpu0",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_guest": 8106.04,
|
||||||
|
"time_system": 26271.4,
|
||||||
|
"time_user": 92904.33,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"cpu": "cpu1",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_guest": 8181.63,
|
||||||
|
"time_system": 25351.49,
|
||||||
|
"time_user": 96912.57,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"cpu": "cpu2",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_guest": 7470.04,
|
||||||
|
"time_system": 24998.43,
|
||||||
|
"time_user": 96034.08,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
testutil.MustMetric(
|
||||||
|
"cpu",
|
||||||
|
map[string]string{
|
||||||
|
"cpu": "cpu3",
|
||||||
|
},
|
||||||
|
map[string]interface{}{
|
||||||
|
"time_guest": 7517.95,
|
||||||
|
"time_system": 24970.82,
|
||||||
|
"time_user": 94148,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
cpu_time_guest{cpu="cpu0"} 8106.04
|
||||||
|
cpu_time_system{cpu="cpu0"} 26271.4
|
||||||
|
cpu_time_user{cpu="cpu0"} 92904.33
|
||||||
|
cpu_time_guest{cpu="cpu1"} 8181.63
|
||||||
|
cpu_time_system{cpu="cpu1"} 25351.49
|
||||||
|
cpu_time_user{cpu="cpu1"} 96912.57
|
||||||
|
cpu_time_guest{cpu="cpu2"} 7470.04
|
||||||
|
cpu_time_system{cpu="cpu2"} 24998.43
|
||||||
|
cpu_time_user{cpu="cpu2"} 96034.08
|
||||||
|
cpu_time_guest{cpu="cpu3"} 7517.95
|
||||||
|
cpu_time_system{cpu="cpu3"} 24970.82
|
||||||
|
cpu_time_user{cpu="cpu3"} 94148
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "summary with no quantile",
|
||||||
|
metrics: []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"prometheus",
|
||||||
|
map[string]string{},
|
||||||
|
map[string]interface{}{
|
||||||
|
"rpc_duration_seconds_sum": 1.7560473e+07,
|
||||||
|
"rpc_duration_seconds_count": 2693,
|
||||||
|
},
|
||||||
|
time.Unix(0, 0),
|
||||||
|
telegraf.Summary,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
expected: []byte(`
|
||||||
|
rpc_duration_seconds_count 2693
|
||||||
|
rpc_duration_seconds_sum 17560473
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
s, err := NewSerializer(FormatConfig{
|
||||||
|
MetricSortOrder: SortMetrics,
|
||||||
|
StringHandling: tt.config.StringHandling,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
data, err := s.SerializeBatch(tt.metrics)
|
||||||
|
require.NoError(t, err)
|
||||||
|
actual, err := prompbToText(data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t,
|
||||||
|
strings.TrimSpace(string(tt.expected)),
|
||||||
|
strings.TrimSpace(string(actual)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prompbToText(data []byte) ([]byte, error) {
|
||||||
|
var buf = bytes.Buffer{}
|
||||||
|
protobuff, err := snappy.Decode(nil, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var req prompb.WriteRequest
|
||||||
|
err = proto.Unmarshal(protobuff, &req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
samples := protoToSamples(&req)
|
||||||
|
for _, sample := range samples {
|
||||||
|
buf.Write([]byte(fmt.Sprintf("%s %s\n", sample.Metric.String(), sample.Value.String())))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func protoToSamples(req *prompb.WriteRequest) model.Samples {
|
||||||
|
var samples model.Samples
|
||||||
|
for _, ts := range req.Timeseries {
|
||||||
|
metric := make(model.Metric, len(ts.Labels))
|
||||||
|
for _, l := range ts.Labels {
|
||||||
|
metric[model.LabelName(l.Name)] = model.LabelValue(l.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range ts.Samples {
|
||||||
|
samples = append(samples, &model.Sample{
|
||||||
|
Metric: metric,
|
||||||
|
Value: model.SampleValue(s.Value),
|
||||||
|
Timestamp: model.Time(s.Timestamp),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return samples
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package serializers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/influxdata/telegraf/plugins/serializers/prometheusremotewrite"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
|
|
@ -126,12 +127,31 @@ func NewSerializer(config *Config) (Serializer, error) {
|
||||||
serializer, err = NewWavefrontSerializer(config.Prefix, config.WavefrontUseStrict, config.WavefrontSourceOverride)
|
serializer, err = NewWavefrontSerializer(config.Prefix, config.WavefrontUseStrict, config.WavefrontSourceOverride)
|
||||||
case "prometheus":
|
case "prometheus":
|
||||||
serializer, err = NewPrometheusSerializer(config)
|
serializer, err = NewPrometheusSerializer(config)
|
||||||
|
case "prometheusremotewrite":
|
||||||
|
serializer, err = NewPrometheusRemoteWriteSerializer(config)
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("Invalid data format: %s", config.DataFormat)
|
err = fmt.Errorf("Invalid data format: %s", config.DataFormat)
|
||||||
}
|
}
|
||||||
return serializer, err
|
return serializer, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPrometheusRemoteWriteSerializer(config *Config) (Serializer, error) {
|
||||||
|
sortMetrics := prometheusremotewrite.NoSortMetrics
|
||||||
|
if config.PrometheusExportTimestamp {
|
||||||
|
sortMetrics = prometheusremotewrite.SortMetrics
|
||||||
|
}
|
||||||
|
|
||||||
|
stringAsLabels := prometheusremotewrite.DiscardStrings
|
||||||
|
if config.PrometheusStringAsLabel {
|
||||||
|
stringAsLabels = prometheusremotewrite.StringAsLabel
|
||||||
|
}
|
||||||
|
|
||||||
|
return prometheusremotewrite.NewSerializer(prometheusremotewrite.FormatConfig{
|
||||||
|
MetricSortOrder: sortMetrics,
|
||||||
|
StringHandling: stringAsLabels,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func NewPrometheusSerializer(config *Config) (Serializer, error) {
|
func NewPrometheusSerializer(config *Config) (Serializer, error) {
|
||||||
exportTimestamp := prometheus.NoExportTimestamp
|
exportTimestamp := prometheus.NoExportTimestamp
|
||||||
if config.PrometheusExportTimestamp {
|
if config.PrometheusExportTimestamp {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue