From 97283b00593f767175912fb9d4d8b8029e0c430c Mon Sep 17 00:00:00 2001 From: Oleg Ozimok Date: Sat, 14 Sep 2019 17:16:04 +0300 Subject: [PATCH 01/44] v0.1.0 --- .gitignore | 15 +++++ README.md | 1 + exporter.go | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 10 +++ go.sum | 69 ++++++++++++++++++++ 5 files changed, 271 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 exporter.go create mode 100644 go.mod create mode 100644 go.sum diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b66cec6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Created by .ignore support plugin (hsz.mobi) +### Go template +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + diff --git a/README.md b/README.md new file mode 100644 index 0000000..bbb96d2 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Prometheus Groupcache exporter \ No newline at end of file diff --git a/exporter.go b/exporter.go new file mode 100644 index 0000000..0c5f13e --- /dev/null +++ b/exporter.go @@ -0,0 +1,176 @@ +package gpexporter + +import ( + "github.com/golang/groupcache" + "github.com/prometheus/client_golang/prometheus" +) + +const subsystem = "groupcache" + +type Exporter struct { + groups []*groupcache.Group + groupGets *prometheus.Desc + groupCacheHits *prometheus.Desc + groupPeerLoads *prometheus.Desc + groupPeerErrors *prometheus.Desc + groupLoads *prometheus.Desc + groupLoadsDeduped *prometheus.Desc + groupLocalLoads *prometheus.Desc + groupLocalLoadErrs *prometheus.Desc + groupServerRequests *prometheus.Desc + cacheBytes *prometheus.Desc + cacheItems *prometheus.Desc + cacheGets *prometheus.Desc + cacheHits *prometheus.Desc + cacheEvictions *prometheus.Desc +} + +func NewExporter(namespace string, groups ...*groupcache.Group) *Exporter { + return &Exporter{ + groups: groups, + groupGets: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "gets_total"), + "todo", + []string{"group"}, + nil, + ), + groupCacheHits: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "hits_total"), + "todo", + []string{"group"}, + nil, + ), + groupPeerLoads: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "peer_loads_total"), + "todo", + []string{"group"}, + nil, + ), + groupPeerErrors: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "peer_errors_total"), + "todo", + []string{"group"}, + nil, + ), + groupLoads: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "loads_total"), + "todo", + []string{"group"}, + nil, + ), + groupLoadsDeduped: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "loads_deduped_total"), + "todo", + []string{"group"}, + nil, + ), + groupLocalLoads: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "local_load_total"), + "todo", + []string{"group"}, + nil, + ), + groupLocalLoadErrs: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "local_load_errs_total"), + "todo", + []string{"group"}, + nil, + ), + groupServerRequests: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "server_requests_total"), + "todo", + []string{"group"}, + nil, + ), + cacheBytes: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "cache_bytes"), + "todo", + []string{"group", "type"}, + nil, + ), + cacheItems: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "cache_items"), + "todo", + []string{"group", "type"}, + nil, + ), + cacheGets: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "cache_gets_total"), + "todo", + []string{"group", "type"}, + nil, + ), + cacheHits: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "cache_hits_total"), + "todo", + []string{"group", "type"}, + nil, + ), + cacheEvictions: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "cache_evictions_total"), + "todo", + []string{"group", "type"}, + nil, + ), + } +} + +func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { + ch <- e.groupGets + ch <- e.groupCacheHits + ch <- e.groupPeerLoads + ch <- e.groupPeerErrors + ch <- e.groupLoads + ch <- e.groupLoadsDeduped + ch <- e.groupLocalLoads + ch <- e.groupLocalLoadErrs + ch <- e.groupServerRequests + ch <- e.cacheBytes + ch <- e.cacheItems + ch <- e.cacheGets + ch <- e.cacheHits + ch <- e.cacheEvictions +} + +func (e *Exporter) Collect(ch chan<- prometheus.Metric) { + for _, group := range e.groups { + e.collectFromGroup(ch, group) + } +} + +func (e *Exporter) collectFromGroup(ch chan<- prometheus.Metric, g *groupcache.Group) { + e.collectStats(ch, g) + e.collectCacheStats(ch, groupcache.HotCache, g) + e.collectCacheStats(ch, groupcache.MainCache, g) +} + +func (e *Exporter) collectStats(ch chan<- prometheus.Metric, g *groupcache.Group) { + ch <- prometheus.MustNewConstMetric(e.groupGets, prometheus.CounterValue, float64(g.Stats.Gets.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupCacheHits, prometheus.CounterValue, float64(g.Stats.CacheHits.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupPeerLoads, prometheus.CounterValue, float64(g.Stats.PeerLoads.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupPeerErrors, prometheus.CounterValue, float64(g.Stats.PeerErrors.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLoads, prometheus.CounterValue, float64(g.Stats.Loads.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLoadsDeduped, prometheus.CounterValue, float64(g.Stats.LoadsDeduped.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLocalLoads, prometheus.CounterValue, float64(g.Stats.LocalLoads.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLocalLoadErrs, prometheus.CounterValue, float64(g.Stats.LocalLoadErrs.Get()), g.Name()) + ch <- prometheus.MustNewConstMetric(e.groupServerRequests, prometheus.CounterValue, float64(g.Stats.ServerRequests.Get()), g.Name()) +} + +func (e *Exporter) collectCacheStats(ch chan<- prometheus.Metric, t groupcache.CacheType, g *groupcache.Group) { + s := g.CacheStats(t) + n := g.Name() + tn := cacheTypeToLabel(t) + + ch <- prometheus.MustNewConstMetric(e.cacheItems, prometheus.GaugeValue, float64(s.Items), n, tn) + ch <- prometheus.MustNewConstMetric(e.cacheBytes, prometheus.GaugeValue, float64(s.Bytes), n, tn) + ch <- prometheus.MustNewConstMetric(e.cacheGets, prometheus.CounterValue, float64(s.Gets), n, tn) + ch <- prometheus.MustNewConstMetric(e.cacheHits, prometheus.CounterValue, float64(s.Hits), n, tn) + ch <- prometheus.MustNewConstMetric(e.cacheEvictions, prometheus.CounterValue, float64(s.Evictions), n, tn) +} + +func cacheTypeToLabel(cacheType groupcache.CacheType) string { + if cacheType == groupcache.MainCache { + return "main" + } + return "hot" +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2d108cf --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/oleh-ozimok/groupcache-exporter + +go 1.12 + +require ( + github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/prometheus/client_golang v1.1.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..c713b1d --- /dev/null +++ b/go.sum @@ -0,0 +1,69 @@ +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From b3bb0f2790d7aea98da5b42844b9dd11c2eb3b78 Mon Sep 17 00:00:00 2001 From: Oleh Ozimok Date: Sat, 14 Sep 2019 17:24:26 +0300 Subject: [PATCH 02/44] rename to gcexporter --- exporter.go | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exporter.go b/exporter.go index 0c5f13e..93428c2 100644 --- a/exporter.go +++ b/exporter.go @@ -1,4 +1,4 @@ -package gpexporter +package gcexporter import ( "github.com/golang/groupcache" diff --git a/go.mod b/go.mod index 2d108cf..c6cff75 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/oleh-ozimok/groupcache-exporter +module github.com/oleh-ozimok/gcexporter go 1.12 From 57df934476ce91f47663613b3a88d1c964707c4b Mon Sep 17 00:00:00 2001 From: Oleh Ozimok Date: Wed, 18 Dec 2019 22:33:36 +0200 Subject: [PATCH 03/44] #1 Create LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f29399b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Oleh Ozimok + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 4fa5c75dd782e17596aa5065e9cec5e9787ed0ec Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Wed, 29 Jun 2022 10:57:26 +0200 Subject: [PATCH 04/44] Updating dependencies & fork details Signed-off-by: Danny Kopping --- LICENSE | 2 +- go.mod | 22 ++- go.sum | 433 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 438 insertions(+), 19 deletions(-) diff --git a/LICENSE b/LICENSE index f29399b..e2d2644 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Oleh Ozimok +Copyright (c) 2022 Grafana Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/go.mod b/go.mod index c6cff75..055b08e 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,20 @@ -module github.com/oleh-ozimok/gcexporter +module github.com/grafana/groupcache_exporter -go 1.12 +go 1.17 require ( - github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/prometheus/client_golang v1.1.0 + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da + github.com/prometheus/client_golang v1.12.2 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.35.0 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect + google.golang.org/protobuf v1.28.0 // indirect ) diff --git a/go.sum b/go.sum index c713b1d..08019f1 100644 --- a/go.sum +++ b/go.sum @@ -1,69 +1,478 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.35.0 h1:Eyr+Pw2VymWejHqCugNaQXkAi6KayVNxaHeu6khmFBE= +github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/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-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8= +golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/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-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +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.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From 35d33a3c4d909f6704649cb1ef2ea4be3f2312b5 Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Wed, 29 Jun 2022 11:35:50 +0200 Subject: [PATCH 05/44] Remove groupcache as a dependency There are a few forks of groupcache now, so instead use an interface for the stats Signed-off-by: Danny Kopping --- exporter.go | 98 +++++++++++++++++++++++++++++++++++------------------ go.mod | 5 +-- go.sum | 2 -- 3 files changed, 66 insertions(+), 39 deletions(-) diff --git a/exporter.go b/exporter.go index 93428c2..94e3256 100644 --- a/exporter.go +++ b/exporter.go @@ -1,14 +1,14 @@ package gcexporter import ( - "github.com/golang/groupcache" "github.com/prometheus/client_golang/prometheus" ) const subsystem = "groupcache" type Exporter struct { - groups []*groupcache.Group + groups []GroupStatistics + groupGets *prometheus.Desc groupCacheHits *prometheus.Desc groupPeerLoads *prometheus.Desc @@ -25,7 +25,45 @@ type Exporter struct { cacheEvictions *prometheus.Desc } -func NewExporter(namespace string, groups ...*groupcache.Group) *Exporter { +type GroupStatistics interface { + // Name returns the group's name + Name() string + + // Gets represents any Get request, including from peers + Gets() int64 + // CacheHits represents either cache was good + CacheHits() int64 + // GetFromPeersLatencyLower represents slowest duration to request value from peers + GetFromPeersLatencyLower() int64 + // PeerLoads represents either remote load or remote cache hit (not an error) + PeerLoads() int64 + // PeerErrors represents a count of errors from peers + PeerErrors() int64 + // Loads represents (gets - cacheHits) + Loads() int64 + // LoadsDeduped represents after singleflight + LoadsDeduped() int64 + // LocalLoads represents total good local loads + LocalLoads() int64 + // LocalLoadErrs represents total bad local loads + LocalLoadErrs() int64 + // ServerRequests represents gets that came over the network from peers + ServerRequests() int64 + + MainCacheItems() int64 + MainCacheBytes() int64 + MainCacheGets() int64 + MainCacheHits() int64 + MainCacheEvictions() int64 + + HotCacheItems() int64 + HotCacheBytes() int64 + HotCacheGets() int64 + HotCacheHits() int64 + HotCacheEvictions() int64 +} + +func NewExporter(namespace string, groups ...GroupStatistics) *Exporter { return &Exporter{ groups: groups, groupGets: prometheus.NewDesc( @@ -138,39 +176,33 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { } } -func (e *Exporter) collectFromGroup(ch chan<- prometheus.Metric, g *groupcache.Group) { - e.collectStats(ch, g) - e.collectCacheStats(ch, groupcache.HotCache, g) - e.collectCacheStats(ch, groupcache.MainCache, g) +func (e *Exporter) collectFromGroup(ch chan<- prometheus.Metric, stats GroupStatistics) { + e.collectStats(ch, stats) + e.collectCacheStats(ch, stats) } -func (e *Exporter) collectStats(ch chan<- prometheus.Metric, g *groupcache.Group) { - ch <- prometheus.MustNewConstMetric(e.groupGets, prometheus.CounterValue, float64(g.Stats.Gets.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupCacheHits, prometheus.CounterValue, float64(g.Stats.CacheHits.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupPeerLoads, prometheus.CounterValue, float64(g.Stats.PeerLoads.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupPeerErrors, prometheus.CounterValue, float64(g.Stats.PeerErrors.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupLoads, prometheus.CounterValue, float64(g.Stats.Loads.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupLoadsDeduped, prometheus.CounterValue, float64(g.Stats.LoadsDeduped.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupLocalLoads, prometheus.CounterValue, float64(g.Stats.LocalLoads.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupLocalLoadErrs, prometheus.CounterValue, float64(g.Stats.LocalLoadErrs.Get()), g.Name()) - ch <- prometheus.MustNewConstMetric(e.groupServerRequests, prometheus.CounterValue, float64(g.Stats.ServerRequests.Get()), g.Name()) +func (e *Exporter) collectStats(ch chan<- prometheus.Metric, stats GroupStatistics) { + ch <- prometheus.MustNewConstMetric(e.groupGets, prometheus.CounterValue, float64(stats.Gets()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupCacheHits, prometheus.CounterValue, float64(stats.CacheHits()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupPeerLoads, prometheus.CounterValue, float64(stats.PeerLoads()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupPeerErrors, prometheus.CounterValue, float64(stats.PeerErrors()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLoads, prometheus.CounterValue, float64(stats.Loads()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLoadsDeduped, prometheus.CounterValue, float64(stats.LoadsDeduped()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLocalLoads, prometheus.CounterValue, float64(stats.LocalLoads()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupLocalLoadErrs, prometheus.CounterValue, float64(stats.LocalLoadErrs()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupServerRequests, prometheus.CounterValue, float64(stats.ServerRequests()), stats.Name()) } -func (e *Exporter) collectCacheStats(ch chan<- prometheus.Metric, t groupcache.CacheType, g *groupcache.Group) { - s := g.CacheStats(t) - n := g.Name() - tn := cacheTypeToLabel(t) - - ch <- prometheus.MustNewConstMetric(e.cacheItems, prometheus.GaugeValue, float64(s.Items), n, tn) - ch <- prometheus.MustNewConstMetric(e.cacheBytes, prometheus.GaugeValue, float64(s.Bytes), n, tn) - ch <- prometheus.MustNewConstMetric(e.cacheGets, prometheus.CounterValue, float64(s.Gets), n, tn) - ch <- prometheus.MustNewConstMetric(e.cacheHits, prometheus.CounterValue, float64(s.Hits), n, tn) - ch <- prometheus.MustNewConstMetric(e.cacheEvictions, prometheus.CounterValue, float64(s.Evictions), n, tn) -} +func (e *Exporter) collectCacheStats(ch chan<- prometheus.Metric, stats GroupStatistics) { + ch <- prometheus.MustNewConstMetric(e.cacheItems, prometheus.GaugeValue, float64(stats.MainCacheItems()), stats.Name(), "main") + ch <- prometheus.MustNewConstMetric(e.cacheBytes, prometheus.GaugeValue, float64(stats.MainCacheBytes()), stats.Name(), "main") + ch <- prometheus.MustNewConstMetric(e.cacheGets, prometheus.CounterValue, float64(stats.MainCacheGets()), stats.Name(), "main") + ch <- prometheus.MustNewConstMetric(e.cacheHits, prometheus.CounterValue, float64(stats.MainCacheHits()), stats.Name(), "main") + ch <- prometheus.MustNewConstMetric(e.cacheEvictions, prometheus.CounterValue, float64(stats.MainCacheEvictions()), stats.Name(), "main") -func cacheTypeToLabel(cacheType groupcache.CacheType) string { - if cacheType == groupcache.MainCache { - return "main" - } - return "hot" + ch <- prometheus.MustNewConstMetric(e.cacheItems, prometheus.GaugeValue, float64(stats.HotCacheItems()), stats.Name(), "hot") + ch <- prometheus.MustNewConstMetric(e.cacheBytes, prometheus.GaugeValue, float64(stats.HotCacheBytes()), stats.Name(), "hot") + ch <- prometheus.MustNewConstMetric(e.cacheGets, prometheus.CounterValue, float64(stats.HotCacheGets()), stats.Name(), "hot") + ch <- prometheus.MustNewConstMetric(e.cacheHits, prometheus.CounterValue, float64(stats.HotCacheHits()), stats.Name(), "hot") + ch <- prometheus.MustNewConstMetric(e.cacheEvictions, prometheus.CounterValue, float64(stats.HotCacheEvictions()), stats.Name(), "hot") } diff --git a/go.mod b/go.mod index 055b08e..4992c0a 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,7 @@ module github.com/grafana/groupcache_exporter go 1.17 -require ( - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da - github.com/prometheus/client_golang v1.12.2 -) +require github.com/prometheus/client_golang v1.12.2 require ( github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index 08019f1..dac3ecd 100644 --- a/go.sum +++ b/go.sum @@ -74,8 +74,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= From d8e9182bd576144061f2f05e21971d139c523852 Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Wed, 29 Jun 2022 11:40:35 +0200 Subject: [PATCH 06/44] Fixing package name Signed-off-by: Danny Kopping --- exporter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter.go b/exporter.go index 94e3256..afbd1ab 100644 --- a/exporter.go +++ b/exporter.go @@ -1,4 +1,4 @@ -package gcexporter +package groupcache_exporter import ( "github.com/prometheus/client_golang/prometheus" From 59a8c6428a43b83f608d05ccb7a93b8969a13f3f Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Wed, 29 Jun 2022 11:54:32 +0200 Subject: [PATCH 07/44] Allowing labels to be passed in rather than metric name prefixes - these can be configured on the registerer Signed-off-by: Danny Kopping --- exporter.go | 60 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/exporter.go b/exporter.go index afbd1ab..30184e1 100644 --- a/exporter.go +++ b/exporter.go @@ -4,8 +4,6 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -const subsystem = "groupcache" - type Exporter struct { groups []GroupStatistics @@ -63,92 +61,92 @@ type GroupStatistics interface { HotCacheEvictions() int64 } -func NewExporter(namespace string, groups ...GroupStatistics) *Exporter { +func NewExporter(labels map[string]string, groups ...GroupStatistics) *Exporter { return &Exporter{ groups: groups, groupGets: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "gets_total"), + "gets_total", "todo", []string{"group"}, - nil, + labels, ), groupCacheHits: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "hits_total"), + "hits_total", "todo", []string{"group"}, - nil, + labels, ), groupPeerLoads: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "peer_loads_total"), + "peer_loads_total", "todo", []string{"group"}, - nil, + labels, ), groupPeerErrors: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "peer_errors_total"), + "peer_errors_total", "todo", []string{"group"}, - nil, + labels, ), groupLoads: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "loads_total"), + "loads_total", "todo", []string{"group"}, - nil, + labels, ), groupLoadsDeduped: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "loads_deduped_total"), + "loads_deduped_total", "todo", []string{"group"}, - nil, + labels, ), groupLocalLoads: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "local_load_total"), + "local_load_total", "todo", []string{"group"}, - nil, + labels, ), groupLocalLoadErrs: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "local_load_errs_total"), + "local_load_errs_total", "todo", []string{"group"}, - nil, + labels, ), groupServerRequests: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "server_requests_total"), + "server_requests_total", "todo", []string{"group"}, - nil, + labels, ), cacheBytes: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_bytes"), + "cache_bytes", "todo", []string{"group", "type"}, - nil, + labels, ), cacheItems: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_items"), + "cache_items", "todo", []string{"group", "type"}, - nil, + labels, ), cacheGets: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_gets_total"), + "cache_gets_total", "todo", []string{"group", "type"}, - nil, + labels, ), cacheHits: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_hits_total"), + "cache_hits_total", "todo", []string{"group", "type"}, - nil, + labels, ), cacheEvictions: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_evictions_total"), + "cache_evictions_total", "todo", []string{"group", "type"}, - nil, + labels, ), } } From 27e24c1f77657333c7b657c3de3098d723706a03 Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Thu, 30 Jun 2022 12:23:56 +0200 Subject: [PATCH 08/44] Adding metric descriptions Signed-off-by: Danny Kopping --- exporter.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/exporter.go b/exporter.go index 30184e1..a8b96ce 100644 --- a/exporter.go +++ b/exporter.go @@ -66,85 +66,85 @@ func NewExporter(labels map[string]string, groups ...GroupStatistics) *Exporter groups: groups, groupGets: prometheus.NewDesc( "gets_total", - "todo", + "Counter of cache gets (including from peers)", []string{"group"}, labels, ), groupCacheHits: prometheus.NewDesc( "hits_total", - "todo", + "Count of cache hits (from either main or hot cache)", []string{"group"}, labels, ), groupPeerLoads: prometheus.NewDesc( "peer_loads_total", - "todo", + "Count of non-error loads or cache hits from peers", []string{"group"}, labels, ), groupPeerErrors: prometheus.NewDesc( "peer_errors_total", - "todo", + "Count of errors from peers", []string{"group"}, labels, ), groupLoads: prometheus.NewDesc( "loads_total", - "todo", + "Count of (gets - hits)", []string{"group"}, labels, ), groupLoadsDeduped: prometheus.NewDesc( "loads_deduped_total", - "todo", + "Count of loads after singleflight", []string{"group"}, labels, ), groupLocalLoads: prometheus.NewDesc( "local_load_total", - "todo", + "Count of loads from local cache", []string{"group"}, labels, ), groupLocalLoadErrs: prometheus.NewDesc( "local_load_errs_total", - "todo", + "Count of loads from local cache that failed", []string{"group"}, labels, ), groupServerRequests: prometheus.NewDesc( "server_requests_total", - "todo", + "Count of gets that came over the network from peers", []string{"group"}, labels, ), cacheBytes: prometheus.NewDesc( "cache_bytes", - "todo", + "Gauge of current bytes in use", []string{"group", "type"}, labels, ), cacheItems: prometheus.NewDesc( "cache_items", - "todo", + "Gauge of current items in use", []string{"group", "type"}, labels, ), cacheGets: prometheus.NewDesc( "cache_gets_total", - "todo", + "Count of cache gets", []string{"group", "type"}, labels, ), cacheHits: prometheus.NewDesc( "cache_hits_total", - "todo", + "Count of cache hits", []string{"group", "type"}, labels, ), cacheEvictions: prometheus.NewDesc( "cache_evictions_total", - "todo", + "Count of cache evictions", []string{"group", "type"}, labels, ), From 8ea81932ef3f25835aa4dd0af4c3766f3ed845b0 Mon Sep 17 00:00:00 2001 From: udhos Date: Mon, 15 Jan 2024 17:24:41 -0300 Subject: [PATCH 09/44] Provide adapters for mailgun and modernprogram. --- README.md | 119 ++++++++++++++++- build.sh | 23 ++++ .../groupcache-exporter-mailgun/groupcache.go | 71 ++++++++++ examples/groupcache-exporter-mailgun/main.go | 62 +++++++++ .../groupcache.go | 71 ++++++++++ .../groupcache-exporter-modernprogram/main.go | 62 +++++++++ exporter.go | 54 +++++--- go.mod | 18 ++- go.sum | 32 ++++- groupcache/mailgun/adapter.go | 121 ++++++++++++++++++ groupcache/modernprogram/adapter.go | 121 ++++++++++++++++++ 11 files changed, 725 insertions(+), 29 deletions(-) create mode 100755 build.sh create mode 100644 examples/groupcache-exporter-mailgun/groupcache.go create mode 100644 examples/groupcache-exporter-mailgun/main.go create mode 100644 examples/groupcache-exporter-modernprogram/groupcache.go create mode 100644 examples/groupcache-exporter-modernprogram/main.go create mode 100644 groupcache/mailgun/adapter.go create mode 100644 groupcache/modernprogram/adapter.go diff --git a/README.md b/README.md index bbb96d2..8946188 100644 --- a/README.md +++ b/README.md @@ -1 +1,118 @@ -# Prometheus Groupcache exporter \ No newline at end of file +[![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/udhos/groupcache_exporter/blob/main/LICENSE) +[![Go Report Card](https://goreportcard.com/badge/github.com/udhos/groupcache_exporter)](https://goreportcard.com/report/github.com/udhos/groupcache_exporter) +[![Go Reference](https://pkg.go.dev/badge/github.com/udhos/groupcache_exporter.svg)](https://pkg.go.dev/github.com/udhos/groupcache_exporter) + +# Prometheus Groupcache exporter + +This exporter implements the prometheus.Collector interface in order to expose Prometheus metrics for [groupcache](https://github.com/golang/groupcache). + +# Example for mailgun groupcache + +```golang +import "github.com/grafana/groupcache_exporter/groupcache/mailgun" + +// ... + +appName := filepath.Base(os.Args[0]) + +cache := startGroupcache() + +// +// expose prometheus metrics +// +{ + metricsRoute := "/metrics" + metricsPort := ":3000" + + log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) + + mailgun := mailgun.New(cache) + labels := map[string]string{ + "app": appName, + } + namespace := "" + collector := groupcache_exporter.NewExporter(namespace, labels, mailgun) + + prometheus.MustRegister(collector) + + go func() { + http.Handle(metricsRoute, promhttp.Handler()) + log.Fatal(http.ListenAndServe(metricsPort, nil)) + }() +} +``` + +Full example: [./examples/groupcache/mailgun](./examples/groupcache/mailgun) + +# Example for modernprogram groupcache + +```golang +import "github.com/grafana/groupcache_exporter/groupcache/modernprogram" + +// ... + +appName := filepath.Base(os.Args[0]) + +cache := startGroupcache() + +// +// expose prometheus metrics +// +{ + metricsRoute := "/metrics" + metricsPort := ":3000" + + log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) + + modernprogram := modernprogram.New(cache) + labels := map[string]string{ + "app": appName, + } + namespace := "" + collector := groupcache_exporter.NewExporter(namespace, labels, modernprogram) + + prometheus.MustRegister(collector) + + go func() { + http.Handle(metricsRoute, promhttp.Handler()) + log.Fatal(http.ListenAndServe(metricsPort, nil)) + }() +} +``` + +Full example: [./examples/groupcache/modernprogram](./examples/groupcache/modernprogram) + +# Testing + +## Build + + go install ./... + +## Run example application + + groupcache-exporter-mailgun + +## Query the metrics endpoint + +```bash +curl -s localhost:3000/metrics | grep -E ^groupcache +groupcache_cache_bytes{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 +groupcache_cache_bytes{app="groupcache-exporter-mailgun",group="files",type="main"} 2954 +groupcache_cache_evictions_total{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 +groupcache_cache_evictions_total{app="groupcache-exporter-mailgun",group="files",type="main"} 1 +groupcache_cache_gets_total{app="groupcache-exporter-mailgun",group="files",type="hot"} 4 +groupcache_cache_gets_total{app="groupcache-exporter-mailgun",group="files",type="main"} 16 +groupcache_cache_hits_total{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 +groupcache_cache_hits_total{app="groupcache-exporter-mailgun",group="files",type="main"} 12 +groupcache_cache_items{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 +groupcache_cache_items{app="groupcache-exporter-mailgun",group="files",type="main"} 1 +groupcache_gets_total{app="groupcache-exporter-mailgun",group="files"} 14 +groupcache_hits_total{app="groupcache-exporter-mailgun",group="files"} 12 +groupcache_loads_deduped_total{app="groupcache-exporter-mailgun",group="files"} 2 +groupcache_loads_total{app="groupcache-exporter-mailgun",group="files"} 2 +groupcache_local_load_errs_total{app="groupcache-exporter-mailgun",group="files"} 0 +groupcache_local_load_total{app="groupcache-exporter-mailgun",group="files"} 2 +groupcache_peer_errors_total{app="groupcache-exporter-mailgun",group="files"} 0 +groupcache_peer_loads_total{app="groupcache-exporter-mailgun",group="files"} 0 +groupcache_server_requests_total{app="groupcache-exporter-mailgun",group="files"} 0 +``` diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..3754a20 --- /dev/null +++ b/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +go install golang.org/x/vuln/cmd/govulncheck@latest + +gofmt -s -w . + +revive ./... + +gocyclo -over 15 . + +go mod tidy + +govulncheck ./... + +go env -w CGO_ENABLED=1 + +go test -race ./... + +go env -w CGO_ENABLED=0 + +go install ./... + +go env -u CGO_ENABLED diff --git a/examples/groupcache-exporter-mailgun/groupcache.go b/examples/groupcache-exporter-mailgun/groupcache.go new file mode 100644 index 0000000..ff88fb4 --- /dev/null +++ b/examples/groupcache-exporter-mailgun/groupcache.go @@ -0,0 +1,71 @@ +package main + +import ( + "context" + "log" + "net/http" + "os" + "time" + + "github.com/mailgun/groupcache/v2" +) + +func startGroupcache() *groupcache.Group { + + ttl := time.Minute + + log.Printf("groupcache ttl: %v", ttl) + + // + // create groupcache pool + // + + groupcachePort := ":5000" + + myURL := "http://127.0.0.1" + groupcachePort + + log.Printf("groupcache my URL: %s", myURL) + + pool := groupcache.NewHTTPPoolOpts(myURL, &groupcache.HTTPPoolOptions{}) + + // + // start groupcache server + // + + serverGroupCache := &http.Server{Addr: groupcachePort, Handler: pool} + + go func() { + log.Printf("groupcache server: listening on %s", groupcachePort) + err := serverGroupCache.ListenAndServe() + log.Printf("groupcache server: exited: %v", err) + }() + + pool.Set(myURL) + + // + // create cache + // + + var groupcacheSizeBytes int64 = 1_000_000 + + // https://talks.golang.org/2013/oscon-dl.slide#46 + // + // 64 MB max per-node memory usage + cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( + func(ctx context.Context, key string, dest groupcache.Sink) error { + + log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) + + data, errFile := os.ReadFile(key) + if errFile != nil { + return errFile + } + + expire := time.Now().Add(ttl) + dest.SetBytes(data, expire) + + return nil + })) + + return cache +} diff --git a/examples/groupcache-exporter-mailgun/main.go b/examples/groupcache-exporter-mailgun/main.go new file mode 100644 index 0000000..7c840fa --- /dev/null +++ b/examples/groupcache-exporter-mailgun/main.go @@ -0,0 +1,62 @@ +// Package main implements the example. +package main + +import ( + "context" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/grafana/groupcache_exporter" + "github.com/grafana/groupcache_exporter/groupcache/mailgun" + "github.com/mailgun/groupcache/v2" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +func main() { + + appName := filepath.Base(os.Args[0]) + + cache := startGroupcache() + + // + // expose prometheus metrics + // + { + metricsRoute := "/metrics" + metricsPort := ":3000" + + log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) + + mailgun := mailgun.New(cache) + labels := map[string]string{ + "app": appName, + } + namespace := "" + collector := groupcache_exporter.NewExporter(namespace, labels, mailgun) + + prometheus.MustRegister(collector) + + go func() { + http.Handle(metricsRoute, promhttp.Handler()) + log.Fatal(http.ListenAndServe(metricsPort, nil)) + }() + } + + // + // query cache periodically + // + + const interval = 5 * time.Second + + for { + var dst []byte + cache.Get(context.TODO(), "/etc/passwd", groupcache.AllocatingByteSliceSink(&dst)) + log.Printf("cache answer: %d bytes, sleeping %v", len(dst), interval) + time.Sleep(interval) + } + +} diff --git a/examples/groupcache-exporter-modernprogram/groupcache.go b/examples/groupcache-exporter-modernprogram/groupcache.go new file mode 100644 index 0000000..f1477a6 --- /dev/null +++ b/examples/groupcache-exporter-modernprogram/groupcache.go @@ -0,0 +1,71 @@ +package main + +import ( + "context" + "log" + "net/http" + "os" + "time" + + "github.com/modernprogram/groupcache/v2" +) + +func startGroupcache() *groupcache.Group { + + ttl := time.Minute + + log.Printf("groupcache ttl: %v", ttl) + + // + // create groupcache pool + // + + groupcachePort := ":5000" + + myURL := "http://127.0.0.1" + groupcachePort + + log.Printf("groupcache my URL: %s", myURL) + + pool := groupcache.NewHTTPPoolOpts(myURL, &groupcache.HTTPPoolOptions{}) + + // + // start groupcache server + // + + serverGroupCache := &http.Server{Addr: groupcachePort, Handler: pool} + + go func() { + log.Printf("groupcache server: listening on %s", groupcachePort) + err := serverGroupCache.ListenAndServe() + log.Printf("groupcache server: exited: %v", err) + }() + + pool.Set(myURL) + + // + // create cache + // + + var groupcacheSizeBytes int64 = 1_000_000 + + // https://talks.golang.org/2013/oscon-dl.slide#46 + // + // 64 MB max per-node memory usage + cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( + func(ctx context.Context, key string, dest groupcache.Sink) error { + + log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) + + data, errFile := os.ReadFile(key) + if errFile != nil { + return errFile + } + + expire := time.Now().Add(ttl) + dest.SetBytes(data, expire) + + return nil + })) + + return cache +} diff --git a/examples/groupcache-exporter-modernprogram/main.go b/examples/groupcache-exporter-modernprogram/main.go new file mode 100644 index 0000000..afb91a8 --- /dev/null +++ b/examples/groupcache-exporter-modernprogram/main.go @@ -0,0 +1,62 @@ +// Package main implements the example. +package main + +import ( + "context" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/grafana/groupcache_exporter" + "github.com/grafana/groupcache_exporter/groupcache/modernprogram" + "github.com/modernprogram/groupcache/v2" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +func main() { + + appName := filepath.Base(os.Args[0]) + + cache := startGroupcache() + + // + // expose prometheus metrics + // + { + metricsRoute := "/metrics" + metricsPort := ":3000" + + log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) + + modernprogram := modernprogram.New(cache) + labels := map[string]string{ + "app": appName, + } + namespace := "" + collector := groupcache_exporter.NewExporter(namespace, labels, modernprogram) + + prometheus.MustRegister(collector) + + go func() { + http.Handle(metricsRoute, promhttp.Handler()) + log.Fatal(http.ListenAndServe(metricsPort, nil)) + }() + } + + // + // query cache periodically + // + + const interval = 5 * time.Second + + for { + var dst []byte + cache.Get(context.TODO(), "/etc/passwd", groupcache.AllocatingByteSliceSink(&dst)) + log.Printf("cache answer: %d bytes, sleeping %v", len(dst), interval) + time.Sleep(interval) + } + +} diff --git a/exporter.go b/exporter.go index a8b96ce..e7b15af 100644 --- a/exporter.go +++ b/exporter.go @@ -1,9 +1,11 @@ +// Package groupcache_exporter exports prometheus metrics for groupcache. package groupcache_exporter import ( "github.com/prometheus/client_golang/prometheus" ) +// Exporter implements interface prometheus.Collector to extract metrics from groupcache. type Exporter struct { groups []GroupStatistics @@ -23,28 +25,41 @@ type Exporter struct { cacheEvictions *prometheus.Desc } +// GroupStatistics is a plugable interface to extract metrics from a groupcache implementation. +// GroupStatistics is used by Exporter to collect the group statistics. +// The user must provide a concrete implementation of this interface that knows how to +// extract group statistics from the actual groupcache implementation. type GroupStatistics interface { // Name returns the group's name Name() string // Gets represents any Get request, including from peers Gets() int64 + // CacheHits represents either cache was good CacheHits() int64 + // GetFromPeersLatencyLower represents slowest duration to request value from peers GetFromPeersLatencyLower() int64 + // PeerLoads represents either remote load or remote cache hit (not an error) PeerLoads() int64 + // PeerErrors represents a count of errors from peers PeerErrors() int64 + // Loads represents (gets - cacheHits) Loads() int64 + // LoadsDeduped represents after singleflight LoadsDeduped() int64 + // LocalLoads represents total good local loads LocalLoads() int64 + // LocalLoadErrs represents total bad local loads LocalLoadErrs() int64 + // ServerRequests represents gets that came over the network from peers ServerRequests() int64 @@ -61,89 +76,94 @@ type GroupStatistics interface { HotCacheEvictions() int64 } -func NewExporter(labels map[string]string, groups ...GroupStatistics) *Exporter { +// NewExporter creates Exporter. +// namespace is usually the empty string. +func NewExporter(namespace string, labels map[string]string, groups ...GroupStatistics) *Exporter { + + const subsystem = "groupcache" + return &Exporter{ groups: groups, groupGets: prometheus.NewDesc( - "gets_total", - "Counter of cache gets (including from peers)", + prometheus.BuildFQName(namespace, subsystem, "gets_total"), + "Count of cache gets (including from peers)", []string{"group"}, labels, ), groupCacheHits: prometheus.NewDesc( - "hits_total", + prometheus.BuildFQName(namespace, subsystem, "hits_total"), "Count of cache hits (from either main or hot cache)", []string{"group"}, labels, ), groupPeerLoads: prometheus.NewDesc( - "peer_loads_total", + prometheus.BuildFQName(namespace, subsystem, "peer_loads_total"), "Count of non-error loads or cache hits from peers", []string{"group"}, labels, ), groupPeerErrors: prometheus.NewDesc( - "peer_errors_total", + prometheus.BuildFQName(namespace, subsystem, "peer_errors_total"), "Count of errors from peers", []string{"group"}, labels, ), groupLoads: prometheus.NewDesc( - "loads_total", + prometheus.BuildFQName(namespace, subsystem, "loads_total"), "Count of (gets - hits)", []string{"group"}, labels, ), groupLoadsDeduped: prometheus.NewDesc( - "loads_deduped_total", + prometheus.BuildFQName(namespace, subsystem, "loads_deduped_total"), "Count of loads after singleflight", []string{"group"}, labels, ), groupLocalLoads: prometheus.NewDesc( - "local_load_total", + prometheus.BuildFQName(namespace, subsystem, "local_load_total"), "Count of loads from local cache", []string{"group"}, labels, ), groupLocalLoadErrs: prometheus.NewDesc( - "local_load_errs_total", + prometheus.BuildFQName(namespace, subsystem, "local_load_errs_total"), "Count of loads from local cache that failed", []string{"group"}, labels, ), groupServerRequests: prometheus.NewDesc( - "server_requests_total", + prometheus.BuildFQName(namespace, subsystem, "server_requests_total"), "Count of gets that came over the network from peers", []string{"group"}, labels, ), cacheBytes: prometheus.NewDesc( - "cache_bytes", + prometheus.BuildFQName(namespace, subsystem, "cache_bytes"), "Gauge of current bytes in use", []string{"group", "type"}, labels, ), cacheItems: prometheus.NewDesc( - "cache_items", + prometheus.BuildFQName(namespace, subsystem, "cache_items"), "Gauge of current items in use", []string{"group", "type"}, labels, ), cacheGets: prometheus.NewDesc( - "cache_gets_total", + prometheus.BuildFQName(namespace, subsystem, "cache_gets_total"), "Count of cache gets", []string{"group", "type"}, labels, ), cacheHits: prometheus.NewDesc( - "cache_hits_total", + prometheus.BuildFQName(namespace, subsystem, "cache_hits_total"), "Count of cache hits", []string{"group", "type"}, labels, ), cacheEvictions: prometheus.NewDesc( - "cache_evictions_total", + prometheus.BuildFQName(namespace, subsystem, "cache_evictions_total"), "Count of cache evictions", []string{"group", "type"}, labels, @@ -151,6 +171,7 @@ func NewExporter(labels map[string]string, groups ...GroupStatistics) *Exporter } } +// Describe sends metrics descriptors. func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.groupGets ch <- e.groupCacheHits @@ -168,6 +189,7 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.cacheEvictions } +// Collect is called by the Prometheus registry when collecting metrics. func (e *Exporter) Collect(ch chan<- prometheus.Metric) { for _, group := range e.groups { e.collectFromGroup(ch, group) diff --git a/go.mod b/go.mod index 4992c0a..ff87851 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,25 @@ module github.com/grafana/groupcache_exporter -go 1.17 +go 1.21.5 -require github.com/prometheus/client_golang v1.12.2 +toolchain go1.21.6 + +require ( + github.com/mailgun/groupcache/v2 v2.5.0 + github.com/modernprogram/groupcache/v2 v2.5.5 + github.com/prometheus/client_golang v1.12.2 +) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.35.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect - golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect - google.golang.org/protobuf v1.28.0 // indirect + github.com/segmentio/fasthash v1.0.3 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + golang.org/x/sys v0.14.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/go.sum b/go.sum index dac3ecd..f420bb6 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -96,8 +97,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -108,8 +110,9 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -142,6 +145,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= +github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -149,11 +154,14 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modernprogram/groupcache/v2 v2.5.5 h1:DfKTmO+9I6TmbelZEUEAUW6XBENrO1LAUV5SOw2b5SM= +github.com/modernprogram/groupcache/v2 v2.5.5/go.mod h1:lW+JZYFFe7HBd+9DH+hwEJyJEr6fiUfBbLmg/qQjS7A= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -180,14 +188,21 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -317,8 +332,9 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8= -golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -374,7 +390,6 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -451,8 +466,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -464,6 +479,9 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/groupcache/mailgun/adapter.go b/groupcache/mailgun/adapter.go new file mode 100644 index 0000000..7bcafb9 --- /dev/null +++ b/groupcache/mailgun/adapter.go @@ -0,0 +1,121 @@ +// Package mailgun implements an adapter to extract metrics from mailgun groupcache. +package mailgun + +import ( + "github.com/mailgun/groupcache/v2" +) + +// GroupMailgun implements interface GroupStatistics to extract metrics from mailgun groupcache group. +type GroupMailgun struct { + group *groupcache.Group +} + +// New creates a new GroupMailgun. +func New(group *groupcache.Group) *GroupMailgun { + return &GroupMailgun{group: group} +} + +// Name returns the group's name +func (g *GroupMailgun) Name() string { + return g.group.Name() +} + +// Gets represents any Get request, including from peers +func (g *GroupMailgun) Gets() int64 { + return g.group.Stats.Gets.Get() +} + +// CacheHits represents either cache was good +func (g *GroupMailgun) CacheHits() int64 { + return g.group.Stats.CacheHits.Get() +} + +// GetFromPeersLatencyLower represents slowest duration to request value from peers +func (g *GroupMailgun) GetFromPeersLatencyLower() int64 { + return g.group.Stats.GetFromPeersLatencyLower.Get() +} + +// PeerLoads represents either remote load or remote cache hit (not an error) +func (g *GroupMailgun) PeerLoads() int64 { + return g.group.Stats.PeerLoads.Get() +} + +// PeerErrors represents a count of errors from peers +func (g *GroupMailgun) PeerErrors() int64 { + return g.group.Stats.PeerErrors.Get() +} + +// Loads represents (gets - cacheHits) +func (g *GroupMailgun) Loads() int64 { + return g.group.Stats.Loads.Get() +} + +// LoadsDeduped represents after singleflight +func (g *GroupMailgun) LoadsDeduped() int64 { + return g.group.Stats.LoadsDeduped.Get() +} + +// LocalLoads represents total good local loads +func (g *GroupMailgun) LocalLoads() int64 { + return g.group.Stats.LocalLoads.Get() +} + +// LocalLoadErrs represents total bad local loads +func (g *GroupMailgun) LocalLoadErrs() int64 { + return g.group.Stats.LocalLoadErrs.Get() +} + +// ServerRequests represents gets that came over the network from peers +func (g *GroupMailgun) ServerRequests() int64 { + return g.group.Stats.ServerRequests.Get() +} + +// MainCacheItems represents number of items in the main cache +func (g *GroupMailgun) MainCacheItems() int64 { + return g.group.CacheStats(groupcache.MainCache).Items +} + +// MainCacheBytes represents number of bytes in the main cache +func (g *GroupMailgun) MainCacheBytes() int64 { + return g.group.CacheStats(groupcache.MainCache).Bytes +} + +// MainCacheGets represents number of get requests in the main cache +func (g *GroupMailgun) MainCacheGets() int64 { + return g.group.CacheStats(groupcache.MainCache).Gets +} + +// MainCacheHits represents number of hit in the main cache +func (g *GroupMailgun) MainCacheHits() int64 { + return g.group.CacheStats(groupcache.MainCache).Hits +} + +// MainCacheEvictions represents number of evictions in the main cache +func (g *GroupMailgun) MainCacheEvictions() int64 { + return g.group.CacheStats(groupcache.MainCache).Evictions +} + +// HotCacheItems represents number of items in the main cache +func (g *GroupMailgun) HotCacheItems() int64 { + return g.group.CacheStats(groupcache.HotCache).Items +} + +// HotCacheBytes represents number of bytes in the hot cache +func (g *GroupMailgun) HotCacheBytes() int64 { + return g.group.CacheStats(groupcache.HotCache).Bytes +} + +// HotCacheGets represents number of get requests in the hot cache +func (g *GroupMailgun) HotCacheGets() int64 { + return g.group.CacheStats(groupcache.HotCache).Gets +} + +// HotCacheHits represents number of hit in the hot cache +func (g *GroupMailgun) HotCacheHits() int64 { + return g.group.CacheStats(groupcache.HotCache).Hits +} + +// HotCacheEvictions represents number of evictions in the hot cache +func (g *GroupMailgun) HotCacheEvictions() int64 { + return g.group.CacheStats(groupcache.HotCache).Evictions +} diff --git a/groupcache/modernprogram/adapter.go b/groupcache/modernprogram/adapter.go new file mode 100644 index 0000000..e8c3c44 --- /dev/null +++ b/groupcache/modernprogram/adapter.go @@ -0,0 +1,121 @@ +// Package modernprogram implements an adapter to extract metrics from modernprogram groupcache. +package modernprogram + +import ( + "github.com/modernprogram/groupcache/v2" +) + +// GroupMailgun implements interface GroupStatistics to extract metrics from mailgun groupcache group. +type GroupMailgun struct { + group *groupcache.Group +} + +// New creates a new GroupMailgun. +func New(group *groupcache.Group) *GroupMailgun { + return &GroupMailgun{group: group} +} + +// Name returns the group's name +func (g *GroupMailgun) Name() string { + return g.group.Name() +} + +// Gets represents any Get request, including from peers +func (g *GroupMailgun) Gets() int64 { + return g.group.Stats.Gets.Get() +} + +// CacheHits represents either cache was good +func (g *GroupMailgun) CacheHits() int64 { + return g.group.Stats.CacheHits.Get() +} + +// GetFromPeersLatencyLower represents slowest duration to request value from peers +func (g *GroupMailgun) GetFromPeersLatencyLower() int64 { + return g.group.Stats.GetFromPeersLatencyLower.Get() +} + +// PeerLoads represents either remote load or remote cache hit (not an error) +func (g *GroupMailgun) PeerLoads() int64 { + return g.group.Stats.PeerLoads.Get() +} + +// PeerErrors represents a count of errors from peers +func (g *GroupMailgun) PeerErrors() int64 { + return g.group.Stats.PeerErrors.Get() +} + +// Loads represents (gets - cacheHits) +func (g *GroupMailgun) Loads() int64 { + return g.group.Stats.Loads.Get() +} + +// LoadsDeduped represents after singleflight +func (g *GroupMailgun) LoadsDeduped() int64 { + return g.group.Stats.LoadsDeduped.Get() +} + +// LocalLoads represents total good local loads +func (g *GroupMailgun) LocalLoads() int64 { + return g.group.Stats.LocalLoads.Get() +} + +// LocalLoadErrs represents total bad local loads +func (g *GroupMailgun) LocalLoadErrs() int64 { + return g.group.Stats.LocalLoadErrs.Get() +} + +// ServerRequests represents gets that came over the network from peers +func (g *GroupMailgun) ServerRequests() int64 { + return g.group.Stats.ServerRequests.Get() +} + +// MainCacheItems represents number of items in the main cache +func (g *GroupMailgun) MainCacheItems() int64 { + return g.group.CacheStats(groupcache.MainCache).Items +} + +// MainCacheBytes represents number of bytes in the main cache +func (g *GroupMailgun) MainCacheBytes() int64 { + return g.group.CacheStats(groupcache.MainCache).Bytes +} + +// MainCacheGets represents number of get requests in the main cache +func (g *GroupMailgun) MainCacheGets() int64 { + return g.group.CacheStats(groupcache.MainCache).Gets +} + +// MainCacheHits represents number of hit in the main cache +func (g *GroupMailgun) MainCacheHits() int64 { + return g.group.CacheStats(groupcache.MainCache).Hits +} + +// MainCacheEvictions represents number of evictions in the main cache +func (g *GroupMailgun) MainCacheEvictions() int64 { + return g.group.CacheStats(groupcache.MainCache).Evictions +} + +// HotCacheItems represents number of items in the main cache +func (g *GroupMailgun) HotCacheItems() int64 { + return g.group.CacheStats(groupcache.HotCache).Items +} + +// HotCacheBytes represents number of bytes in the hot cache +func (g *GroupMailgun) HotCacheBytes() int64 { + return g.group.CacheStats(groupcache.HotCache).Bytes +} + +// HotCacheGets represents number of get requests in the hot cache +func (g *GroupMailgun) HotCacheGets() int64 { + return g.group.CacheStats(groupcache.HotCache).Gets +} + +// HotCacheHits represents number of hit in the hot cache +func (g *GroupMailgun) HotCacheHits() int64 { + return g.group.CacheStats(groupcache.HotCache).Hits +} + +// HotCacheEvictions represents number of evictions in the hot cache +func (g *GroupMailgun) HotCacheEvictions() int64 { + return g.group.CacheStats(groupcache.HotCache).Evictions +} From 0cd32d7e07e041ff8d7c426d9affd30c2f9aff88 Mon Sep 17 00:00:00 2001 From: udhos Date: Mon, 15 Jan 2024 17:32:21 -0300 Subject: [PATCH 10/44] Fix imports. --- README.md | 4 ++-- examples/groupcache-exporter-mailgun/main.go | 4 ++-- examples/groupcache-exporter-modernprogram/main.go | 4 ++-- go.mod | 6 ++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8946188..4a28dd0 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This exporter implements the prometheus.Collector interface in order to expose P # Example for mailgun groupcache ```golang -import "github.com/grafana/groupcache_exporter/groupcache/mailgun" +import "github.com/udhos/groupcache_exporter/groupcache/mailgun" // ... @@ -47,7 +47,7 @@ Full example: [./examples/groupcache/mailgun](./examples/groupcache/mailgun) # Example for modernprogram groupcache ```golang -import "github.com/grafana/groupcache_exporter/groupcache/modernprogram" +import "github.com/udhos/groupcache_exporter/groupcache/modernprogram" // ... diff --git a/examples/groupcache-exporter-mailgun/main.go b/examples/groupcache-exporter-mailgun/main.go index 7c840fa..3e6dc98 100644 --- a/examples/groupcache-exporter-mailgun/main.go +++ b/examples/groupcache-exporter-mailgun/main.go @@ -9,11 +9,11 @@ import ( "path/filepath" "time" - "github.com/grafana/groupcache_exporter" - "github.com/grafana/groupcache_exporter/groupcache/mailgun" "github.com/mailgun/groupcache/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/udhos/groupcache_exporter" + "github.com/udhos/groupcache_exporter/groupcache/mailgun" ) func main() { diff --git a/examples/groupcache-exporter-modernprogram/main.go b/examples/groupcache-exporter-modernprogram/main.go index afb91a8..40e9446 100644 --- a/examples/groupcache-exporter-modernprogram/main.go +++ b/examples/groupcache-exporter-modernprogram/main.go @@ -9,11 +9,11 @@ import ( "path/filepath" "time" - "github.com/grafana/groupcache_exporter" - "github.com/grafana/groupcache_exporter/groupcache/modernprogram" "github.com/modernprogram/groupcache/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/udhos/groupcache_exporter" + "github.com/udhos/groupcache_exporter/groupcache/modernprogram" ) func main() { diff --git a/go.mod b/go.mod index ff87851..5fd8d8e 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ -module github.com/grafana/groupcache_exporter +module github.com/udhos/groupcache_exporter -go 1.21.5 - -toolchain go1.21.6 +go 1.21.6 require ( github.com/mailgun/groupcache/v2 v2.5.0 From 084a85a8d7eab7e0418ad304a0a6359234ea0365 Mon Sep 17 00:00:00 2001 From: udhos Date: Mon, 15 Jan 2024 19:43:02 -0300 Subject: [PATCH 11/44] Clean-up. --- groupcache/mailgun/adapter.go | 50 ++++++++++++++--------------- groupcache/modernprogram/adapter.go | 50 ++++++++++++++--------------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/groupcache/mailgun/adapter.go b/groupcache/mailgun/adapter.go index 7bcafb9..65949cb 100644 --- a/groupcache/mailgun/adapter.go +++ b/groupcache/mailgun/adapter.go @@ -5,117 +5,117 @@ import ( "github.com/mailgun/groupcache/v2" ) -// GroupMailgun implements interface GroupStatistics to extract metrics from mailgun groupcache group. -type GroupMailgun struct { +// Group implements interface GroupStatistics to extract metrics from mailgun groupcache group. +type Group struct { group *groupcache.Group } // New creates a new GroupMailgun. -func New(group *groupcache.Group) *GroupMailgun { - return &GroupMailgun{group: group} +func New(group *groupcache.Group) *Group { + return &Group{group: group} } // Name returns the group's name -func (g *GroupMailgun) Name() string { +func (g *Group) Name() string { return g.group.Name() } // Gets represents any Get request, including from peers -func (g *GroupMailgun) Gets() int64 { +func (g *Group) Gets() int64 { return g.group.Stats.Gets.Get() } // CacheHits represents either cache was good -func (g *GroupMailgun) CacheHits() int64 { +func (g *Group) CacheHits() int64 { return g.group.Stats.CacheHits.Get() } // GetFromPeersLatencyLower represents slowest duration to request value from peers -func (g *GroupMailgun) GetFromPeersLatencyLower() int64 { +func (g *Group) GetFromPeersLatencyLower() int64 { return g.group.Stats.GetFromPeersLatencyLower.Get() } // PeerLoads represents either remote load or remote cache hit (not an error) -func (g *GroupMailgun) PeerLoads() int64 { +func (g *Group) PeerLoads() int64 { return g.group.Stats.PeerLoads.Get() } // PeerErrors represents a count of errors from peers -func (g *GroupMailgun) PeerErrors() int64 { +func (g *Group) PeerErrors() int64 { return g.group.Stats.PeerErrors.Get() } // Loads represents (gets - cacheHits) -func (g *GroupMailgun) Loads() int64 { +func (g *Group) Loads() int64 { return g.group.Stats.Loads.Get() } // LoadsDeduped represents after singleflight -func (g *GroupMailgun) LoadsDeduped() int64 { +func (g *Group) LoadsDeduped() int64 { return g.group.Stats.LoadsDeduped.Get() } // LocalLoads represents total good local loads -func (g *GroupMailgun) LocalLoads() int64 { +func (g *Group) LocalLoads() int64 { return g.group.Stats.LocalLoads.Get() } // LocalLoadErrs represents total bad local loads -func (g *GroupMailgun) LocalLoadErrs() int64 { +func (g *Group) LocalLoadErrs() int64 { return g.group.Stats.LocalLoadErrs.Get() } // ServerRequests represents gets that came over the network from peers -func (g *GroupMailgun) ServerRequests() int64 { +func (g *Group) ServerRequests() int64 { return g.group.Stats.ServerRequests.Get() } // MainCacheItems represents number of items in the main cache -func (g *GroupMailgun) MainCacheItems() int64 { +func (g *Group) MainCacheItems() int64 { return g.group.CacheStats(groupcache.MainCache).Items } // MainCacheBytes represents number of bytes in the main cache -func (g *GroupMailgun) MainCacheBytes() int64 { +func (g *Group) MainCacheBytes() int64 { return g.group.CacheStats(groupcache.MainCache).Bytes } // MainCacheGets represents number of get requests in the main cache -func (g *GroupMailgun) MainCacheGets() int64 { +func (g *Group) MainCacheGets() int64 { return g.group.CacheStats(groupcache.MainCache).Gets } // MainCacheHits represents number of hit in the main cache -func (g *GroupMailgun) MainCacheHits() int64 { +func (g *Group) MainCacheHits() int64 { return g.group.CacheStats(groupcache.MainCache).Hits } // MainCacheEvictions represents number of evictions in the main cache -func (g *GroupMailgun) MainCacheEvictions() int64 { +func (g *Group) MainCacheEvictions() int64 { return g.group.CacheStats(groupcache.MainCache).Evictions } // HotCacheItems represents number of items in the main cache -func (g *GroupMailgun) HotCacheItems() int64 { +func (g *Group) HotCacheItems() int64 { return g.group.CacheStats(groupcache.HotCache).Items } // HotCacheBytes represents number of bytes in the hot cache -func (g *GroupMailgun) HotCacheBytes() int64 { +func (g *Group) HotCacheBytes() int64 { return g.group.CacheStats(groupcache.HotCache).Bytes } // HotCacheGets represents number of get requests in the hot cache -func (g *GroupMailgun) HotCacheGets() int64 { +func (g *Group) HotCacheGets() int64 { return g.group.CacheStats(groupcache.HotCache).Gets } // HotCacheHits represents number of hit in the hot cache -func (g *GroupMailgun) HotCacheHits() int64 { +func (g *Group) HotCacheHits() int64 { return g.group.CacheStats(groupcache.HotCache).Hits } // HotCacheEvictions represents number of evictions in the hot cache -func (g *GroupMailgun) HotCacheEvictions() int64 { +func (g *Group) HotCacheEvictions() int64 { return g.group.CacheStats(groupcache.HotCache).Evictions } diff --git a/groupcache/modernprogram/adapter.go b/groupcache/modernprogram/adapter.go index e8c3c44..db27f0f 100644 --- a/groupcache/modernprogram/adapter.go +++ b/groupcache/modernprogram/adapter.go @@ -5,117 +5,117 @@ import ( "github.com/modernprogram/groupcache/v2" ) -// GroupMailgun implements interface GroupStatistics to extract metrics from mailgun groupcache group. -type GroupMailgun struct { +// Group implements interface GroupStatistics to extract metrics from mailgun groupcache group. +type Group struct { group *groupcache.Group } // New creates a new GroupMailgun. -func New(group *groupcache.Group) *GroupMailgun { - return &GroupMailgun{group: group} +func New(group *groupcache.Group) *Group { + return &Group{group: group} } // Name returns the group's name -func (g *GroupMailgun) Name() string { +func (g *Group) Name() string { return g.group.Name() } // Gets represents any Get request, including from peers -func (g *GroupMailgun) Gets() int64 { +func (g *Group) Gets() int64 { return g.group.Stats.Gets.Get() } // CacheHits represents either cache was good -func (g *GroupMailgun) CacheHits() int64 { +func (g *Group) CacheHits() int64 { return g.group.Stats.CacheHits.Get() } // GetFromPeersLatencyLower represents slowest duration to request value from peers -func (g *GroupMailgun) GetFromPeersLatencyLower() int64 { +func (g *Group) GetFromPeersLatencyLower() int64 { return g.group.Stats.GetFromPeersLatencyLower.Get() } // PeerLoads represents either remote load or remote cache hit (not an error) -func (g *GroupMailgun) PeerLoads() int64 { +func (g *Group) PeerLoads() int64 { return g.group.Stats.PeerLoads.Get() } // PeerErrors represents a count of errors from peers -func (g *GroupMailgun) PeerErrors() int64 { +func (g *Group) PeerErrors() int64 { return g.group.Stats.PeerErrors.Get() } // Loads represents (gets - cacheHits) -func (g *GroupMailgun) Loads() int64 { +func (g *Group) Loads() int64 { return g.group.Stats.Loads.Get() } // LoadsDeduped represents after singleflight -func (g *GroupMailgun) LoadsDeduped() int64 { +func (g *Group) LoadsDeduped() int64 { return g.group.Stats.LoadsDeduped.Get() } // LocalLoads represents total good local loads -func (g *GroupMailgun) LocalLoads() int64 { +func (g *Group) LocalLoads() int64 { return g.group.Stats.LocalLoads.Get() } // LocalLoadErrs represents total bad local loads -func (g *GroupMailgun) LocalLoadErrs() int64 { +func (g *Group) LocalLoadErrs() int64 { return g.group.Stats.LocalLoadErrs.Get() } // ServerRequests represents gets that came over the network from peers -func (g *GroupMailgun) ServerRequests() int64 { +func (g *Group) ServerRequests() int64 { return g.group.Stats.ServerRequests.Get() } // MainCacheItems represents number of items in the main cache -func (g *GroupMailgun) MainCacheItems() int64 { +func (g *Group) MainCacheItems() int64 { return g.group.CacheStats(groupcache.MainCache).Items } // MainCacheBytes represents number of bytes in the main cache -func (g *GroupMailgun) MainCacheBytes() int64 { +func (g *Group) MainCacheBytes() int64 { return g.group.CacheStats(groupcache.MainCache).Bytes } // MainCacheGets represents number of get requests in the main cache -func (g *GroupMailgun) MainCacheGets() int64 { +func (g *Group) MainCacheGets() int64 { return g.group.CacheStats(groupcache.MainCache).Gets } // MainCacheHits represents number of hit in the main cache -func (g *GroupMailgun) MainCacheHits() int64 { +func (g *Group) MainCacheHits() int64 { return g.group.CacheStats(groupcache.MainCache).Hits } // MainCacheEvictions represents number of evictions in the main cache -func (g *GroupMailgun) MainCacheEvictions() int64 { +func (g *Group) MainCacheEvictions() int64 { return g.group.CacheStats(groupcache.MainCache).Evictions } // HotCacheItems represents number of items in the main cache -func (g *GroupMailgun) HotCacheItems() int64 { +func (g *Group) HotCacheItems() int64 { return g.group.CacheStats(groupcache.HotCache).Items } // HotCacheBytes represents number of bytes in the hot cache -func (g *GroupMailgun) HotCacheBytes() int64 { +func (g *Group) HotCacheBytes() int64 { return g.group.CacheStats(groupcache.HotCache).Bytes } // HotCacheGets represents number of get requests in the hot cache -func (g *GroupMailgun) HotCacheGets() int64 { +func (g *Group) HotCacheGets() int64 { return g.group.CacheStats(groupcache.HotCache).Gets } // HotCacheHits represents number of hit in the hot cache -func (g *GroupMailgun) HotCacheHits() int64 { +func (g *Group) HotCacheHits() int64 { return g.group.CacheStats(groupcache.HotCache).Hits } // HotCacheEvictions represents number of evictions in the hot cache -func (g *GroupMailgun) HotCacheEvictions() int64 { +func (g *Group) HotCacheEvictions() int64 { return g.group.CacheStats(groupcache.HotCache).Evictions } From 949acaecbbf623005f1f7d8569c941d5e32c2da3 Mon Sep 17 00:00:00 2001 From: udhos Date: Mon, 15 Jan 2024 20:20:22 -0300 Subject: [PATCH 12/44] Fix example links. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a28dd0..dc826a3 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ cache := startGroupcache() } ``` -Full example: [./examples/groupcache/mailgun](./examples/groupcache/mailgun) +Full example: [examples/groupcache-exporter-mailgun](examples/groupcache-exporter-mailgun) # Example for modernprogram groupcache @@ -80,7 +80,7 @@ cache := startGroupcache() } ``` -Full example: [./examples/groupcache/modernprogram](./examples/groupcache/modernprogram) +Full example: [examples/groupcache-exporter-modernprogram](examples/groupcache-exporter-modernprogram) # Testing From ffe4c8986ea71b1e3cdf3a45fd8697be60a8c793 Mon Sep 17 00:00:00 2001 From: udhos Date: Mon, 22 Jan 2024 02:20:31 -0300 Subject: [PATCH 13/44] Fix comments. --- go.mod | 17 +- go.sum | 485 ++-------------------------- groupcache/mailgun/adapter.go | 2 +- groupcache/modernprogram/adapter.go | 4 +- 4 files changed, 41 insertions(+), 467 deletions(-) diff --git a/go.mod b/go.mod index 5fd8d8e..3c6c919 100644 --- a/go.mod +++ b/go.mod @@ -5,19 +5,18 @@ go 1.21.6 require ( github.com/mailgun/groupcache/v2 v2.5.0 github.com/modernprogram/groupcache/v2 v2.5.5 - github.com/prometheus/client_golang v1.12.2 + github.com/prometheus/client_golang v1.18.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.35.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.46.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/segmentio/fasthash v1.0.3 // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - golang.org/x/sys v0.14.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + golang.org/x/sys v0.16.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect ) diff --git a/go.sum b/go.sum index f420bb6..5922d6f 100644 --- a/go.sum +++ b/go.sum @@ -1,494 +1,69 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modernprogram/groupcache/v2 v2.5.5 h1:DfKTmO+9I6TmbelZEUEAUW6XBENrO1LAUV5SOw2b5SM= github.com/modernprogram/groupcache/v2 v2.5.5/go.mod h1:lW+JZYFFe7HBd+9DH+hwEJyJEr6fiUfBbLmg/qQjS7A= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0 h1:Eyr+Pw2VymWejHqCugNaQXkAi6KayVNxaHeu6khmFBE= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= +github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/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-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/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-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -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.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/groupcache/mailgun/adapter.go b/groupcache/mailgun/adapter.go index 65949cb..c50306d 100644 --- a/groupcache/mailgun/adapter.go +++ b/groupcache/mailgun/adapter.go @@ -10,7 +10,7 @@ type Group struct { group *groupcache.Group } -// New creates a new GroupMailgun. +// New creates a new Group. func New(group *groupcache.Group) *Group { return &Group{group: group} } diff --git a/groupcache/modernprogram/adapter.go b/groupcache/modernprogram/adapter.go index db27f0f..8919708 100644 --- a/groupcache/modernprogram/adapter.go +++ b/groupcache/modernprogram/adapter.go @@ -5,12 +5,12 @@ import ( "github.com/modernprogram/groupcache/v2" ) -// Group implements interface GroupStatistics to extract metrics from mailgun groupcache group. +// Group implements interface GroupStatistics to extract metrics from modernprogram groupcache group. type Group struct { group *groupcache.Group } -// New creates a new GroupMailgun. +// New creates a new Group. func New(group *groupcache.Group) *Group { return &Group{group: group} } From 85dea63d25bfc448e37305eeb5f514fd78553585 Mon Sep 17 00:00:00 2001 From: udhos Date: Wed, 31 Jan 2024 22:17:31 -0300 Subject: [PATCH 14/44] Support google groupcache. --- build.sh | 2 + .../groupcache-exporter-google/groupcache.go | 63 +++++++++ examples/groupcache-exporter-google/main.go | 62 +++++++++ .../groupcache-exporter-mailgun/groupcache.go | 4 +- .../groupcache.go | 4 +- go.mod | 1 + go.sum | 24 +--- groupcache/google/adapter.go | 121 ++++++++++++++++++ 8 files changed, 253 insertions(+), 28 deletions(-) create mode 100644 examples/groupcache-exporter-google/groupcache.go create mode 100644 examples/groupcache-exporter-google/main.go create mode 100644 groupcache/google/adapter.go diff --git a/build.sh b/build.sh index 3754a20..2ce48af 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,7 @@ #!/bin/bash go install golang.org/x/vuln/cmd/govulncheck@latest +go install golang.org/x/tools/cmd/deadcode@latest gofmt -s -w . @@ -11,6 +12,7 @@ gocyclo -over 15 . go mod tidy govulncheck ./... +deadcode ./examples/* go env -w CGO_ENABLED=1 diff --git a/examples/groupcache-exporter-google/groupcache.go b/examples/groupcache-exporter-google/groupcache.go new file mode 100644 index 0000000..455659e --- /dev/null +++ b/examples/groupcache-exporter-google/groupcache.go @@ -0,0 +1,63 @@ +package main + +import ( + "context" + "log" + "net/http" + "os" + + "github.com/golang/groupcache" +) + +func startGroupcache() *groupcache.Group { + + // + // create groupcache pool + // + + groupcachePort := ":5000" + + myURL := "http://127.0.0.1" + groupcachePort + + log.Printf("groupcache my URL: %s", myURL) + + pool := groupcache.NewHTTPPoolOpts(myURL, &groupcache.HTTPPoolOptions{}) + + // + // start groupcache server + // + + serverGroupCache := &http.Server{Addr: groupcachePort, Handler: pool} + + go func() { + log.Printf("groupcache server: listening on %s", groupcachePort) + err := serverGroupCache.ListenAndServe() + log.Printf("groupcache server: exited: %v", err) + }() + + pool.Set(myURL) + + // + // create cache + // + + var groupcacheSizeBytes int64 = 1_000_000 + + // https://talks.golang.org/2013/oscon-dl.slide#46 + // + // 64 MB max per-node memory usage + cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( + func(ctx context.Context, key string, dest groupcache.Sink) error { + + log.Printf("getter: loading: key:%s", key) + + data, errFile := os.ReadFile(key) + if errFile != nil { + return errFile + } + + return dest.SetBytes(data) + })) + + return cache +} diff --git a/examples/groupcache-exporter-google/main.go b/examples/groupcache-exporter-google/main.go new file mode 100644 index 0000000..f12b77e --- /dev/null +++ b/examples/groupcache-exporter-google/main.go @@ -0,0 +1,62 @@ +// Package main implements the example. +package main + +import ( + "context" + "log" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/golang/groupcache" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/udhos/groupcache_exporter" + "github.com/udhos/groupcache_exporter/groupcache/google" +) + +func main() { + + appName := filepath.Base(os.Args[0]) + + cache := startGroupcache() + + // + // expose prometheus metrics + // + { + metricsRoute := "/metrics" + metricsPort := ":3000" + + log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) + + google := google.New(cache) + labels := map[string]string{ + "app": appName, + } + namespace := "" + collector := groupcache_exporter.NewExporter(namespace, labels, google) + + prometheus.MustRegister(collector) + + go func() { + http.Handle(metricsRoute, promhttp.Handler()) + log.Fatal(http.ListenAndServe(metricsPort, nil)) + }() + } + + // + // query cache periodically + // + + const interval = 5 * time.Second + + for { + var dst []byte + cache.Get(context.TODO(), "/etc/passwd", groupcache.AllocatingByteSliceSink(&dst)) + log.Printf("cache answer: %d bytes, sleeping %v", len(dst), interval) + time.Sleep(interval) + } + +} diff --git a/examples/groupcache-exporter-mailgun/groupcache.go b/examples/groupcache-exporter-mailgun/groupcache.go index ff88fb4..a15838c 100644 --- a/examples/groupcache-exporter-mailgun/groupcache.go +++ b/examples/groupcache-exporter-mailgun/groupcache.go @@ -62,9 +62,7 @@ func startGroupcache() *groupcache.Group { } expire := time.Now().Add(ttl) - dest.SetBytes(data, expire) - - return nil + return dest.SetBytes(data, expire) })) return cache diff --git a/examples/groupcache-exporter-modernprogram/groupcache.go b/examples/groupcache-exporter-modernprogram/groupcache.go index f1477a6..95d3dc0 100644 --- a/examples/groupcache-exporter-modernprogram/groupcache.go +++ b/examples/groupcache-exporter-modernprogram/groupcache.go @@ -62,9 +62,7 @@ func startGroupcache() *groupcache.Group { } expire := time.Now().Add(ttl) - dest.SetBytes(data, expire) - - return nil + return dest.SetBytes(data, expire) })) return cache diff --git a/go.mod b/go.mod index 3c6c919..96eda4d 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/udhos/groupcache_exporter go 1.21.6 require ( + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/mailgun/groupcache/v2 v2.5.0 github.com/modernprogram/groupcache/v2 v2.5.5 github.com/prometheus/client_golang v1.18.0 diff --git a/go.sum b/go.sum index 5922d6f..a564d28 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -7,26 +5,18 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modernprogram/groupcache/v2 v2.5.5 h1:DfKTmO+9I6TmbelZEUEAUW6XBENrO1LAUV5SOw2b5SM= github.com/modernprogram/groupcache/v2 v2.5.5/go.mod h1:lW+JZYFFe7HBd+9DH+hwEJyJEr6fiUfBbLmg/qQjS7A= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= @@ -37,7 +27,6 @@ github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqSc github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -46,24 +35,15 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/groupcache/google/adapter.go b/groupcache/google/adapter.go new file mode 100644 index 0000000..578b989 --- /dev/null +++ b/groupcache/google/adapter.go @@ -0,0 +1,121 @@ +// Package google implements an adapter to extract metrics from google groupcache. +package google + +import ( + "github.com/golang/groupcache" +) + +// Group implements interface GroupStatistics to extract metrics from google groupcache group. +type Group struct { + group *groupcache.Group +} + +// New creates a new Group. +func New(group *groupcache.Group) *Group { + return &Group{group: group} +} + +// Name returns the group's name +func (g *Group) Name() string { + return g.group.Name() +} + +// Gets represents any Get request, including from peers +func (g *Group) Gets() int64 { + return g.group.Stats.Gets.Get() +} + +// CacheHits represents either cache was good +func (g *Group) CacheHits() int64 { + return g.group.Stats.CacheHits.Get() +} + +// GetFromPeersLatencyLower represents slowest duration to request value from peers +func (g *Group) GetFromPeersLatencyLower() int64 { + return 0 +} + +// PeerLoads represents either remote load or remote cache hit (not an error) +func (g *Group) PeerLoads() int64 { + return g.group.Stats.PeerLoads.Get() +} + +// PeerErrors represents a count of errors from peers +func (g *Group) PeerErrors() int64 { + return g.group.Stats.PeerErrors.Get() +} + +// Loads represents (gets - cacheHits) +func (g *Group) Loads() int64 { + return g.group.Stats.Loads.Get() +} + +// LoadsDeduped represents after singleflight +func (g *Group) LoadsDeduped() int64 { + return g.group.Stats.LoadsDeduped.Get() +} + +// LocalLoads represents total good local loads +func (g *Group) LocalLoads() int64 { + return g.group.Stats.LocalLoads.Get() +} + +// LocalLoadErrs represents total bad local loads +func (g *Group) LocalLoadErrs() int64 { + return g.group.Stats.LocalLoadErrs.Get() +} + +// ServerRequests represents gets that came over the network from peers +func (g *Group) ServerRequests() int64 { + return g.group.Stats.ServerRequests.Get() +} + +// MainCacheItems represents number of items in the main cache +func (g *Group) MainCacheItems() int64 { + return g.group.CacheStats(groupcache.MainCache).Items +} + +// MainCacheBytes represents number of bytes in the main cache +func (g *Group) MainCacheBytes() int64 { + return g.group.CacheStats(groupcache.MainCache).Bytes +} + +// MainCacheGets represents number of get requests in the main cache +func (g *Group) MainCacheGets() int64 { + return g.group.CacheStats(groupcache.MainCache).Gets +} + +// MainCacheHits represents number of hit in the main cache +func (g *Group) MainCacheHits() int64 { + return g.group.CacheStats(groupcache.MainCache).Hits +} + +// MainCacheEvictions represents number of evictions in the main cache +func (g *Group) MainCacheEvictions() int64 { + return g.group.CacheStats(groupcache.MainCache).Evictions +} + +// HotCacheItems represents number of items in the main cache +func (g *Group) HotCacheItems() int64 { + return g.group.CacheStats(groupcache.HotCache).Items +} + +// HotCacheBytes represents number of bytes in the hot cache +func (g *Group) HotCacheBytes() int64 { + return g.group.CacheStats(groupcache.HotCache).Bytes +} + +// HotCacheGets represents number of get requests in the hot cache +func (g *Group) HotCacheGets() int64 { + return g.group.CacheStats(groupcache.HotCache).Gets +} + +// HotCacheHits represents number of hit in the hot cache +func (g *Group) HotCacheHits() int64 { + return g.group.CacheStats(groupcache.HotCache).Hits +} + +// HotCacheEvictions represents number of evictions in the hot cache +func (g *Group) HotCacheEvictions() int64 { + return g.group.CacheStats(groupcache.HotCache).Evictions +} From b8775d2742c31f6b765db19a543f523274b70d61 Mon Sep 17 00:00:00 2001 From: udhos Date: Tue, 13 Feb 2024 00:23:57 -0300 Subject: [PATCH 15/44] Upgrade toolchain. --- examples/groupcache-exporter-google/groupcache.go | 2 +- examples/groupcache-exporter-mailgun/groupcache.go | 2 +- examples/groupcache-exporter-modernprogram/groupcache.go | 2 +- go.mod | 6 +++--- go.sum | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/groupcache-exporter-google/groupcache.go b/examples/groupcache-exporter-google/groupcache.go index 455659e..4ec93fd 100644 --- a/examples/groupcache-exporter-google/groupcache.go +++ b/examples/groupcache-exporter-google/groupcache.go @@ -47,7 +47,7 @@ func startGroupcache() *groupcache.Group { // // 64 MB max per-node memory usage cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( - func(ctx context.Context, key string, dest groupcache.Sink) error { + func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { log.Printf("getter: loading: key:%s", key) diff --git a/examples/groupcache-exporter-mailgun/groupcache.go b/examples/groupcache-exporter-mailgun/groupcache.go index a15838c..46121d0 100644 --- a/examples/groupcache-exporter-mailgun/groupcache.go +++ b/examples/groupcache-exporter-mailgun/groupcache.go @@ -52,7 +52,7 @@ func startGroupcache() *groupcache.Group { // // 64 MB max per-node memory usage cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( - func(ctx context.Context, key string, dest groupcache.Sink) error { + func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) diff --git a/examples/groupcache-exporter-modernprogram/groupcache.go b/examples/groupcache-exporter-modernprogram/groupcache.go index 95d3dc0..5018a1e 100644 --- a/examples/groupcache-exporter-modernprogram/groupcache.go +++ b/examples/groupcache-exporter-modernprogram/groupcache.go @@ -52,7 +52,7 @@ func startGroupcache() *groupcache.Group { // // 64 MB max per-node memory usage cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( - func(ctx context.Context, key string, dest groupcache.Sink) error { + func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) diff --git a/go.mod b/go.mod index 96eda4d..59129ff 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/udhos/groupcache_exporter -go 1.21.6 +go 1.22.0 require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/mailgun/groupcache/v2 v2.5.0 - github.com/modernprogram/groupcache/v2 v2.5.5 + github.com/modernprogram/groupcache/v2 v2.5.6 github.com/prometheus/client_golang v1.18.0 ) @@ -18,6 +18,6 @@ require ( github.com/prometheus/procfs v0.12.0 // indirect github.com/segmentio/fasthash v1.0.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/sys v0.17.0 // indirect google.golang.org/protobuf v1.32.0 // indirect ) diff --git a/go.sum b/go.sum index a564d28..99d5b01 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/modernprogram/groupcache/v2 v2.5.5 h1:DfKTmO+9I6TmbelZEUEAUW6XBENrO1LAUV5SOw2b5SM= -github.com/modernprogram/groupcache/v2 v2.5.5/go.mod h1:lW+JZYFFe7HBd+9DH+hwEJyJEr6fiUfBbLmg/qQjS7A= +github.com/modernprogram/groupcache/v2 v2.5.6 h1:G4e9QJEghQRBIO1WyIkSw1S2vyjpY9DlZgMsVuymYHU= +github.com/modernprogram/groupcache/v2 v2.5.6/go.mod h1:it+NoQbGs35RSn/5bdw6b3QEjEw0bLB/lYIywZrxyFY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= @@ -36,8 +36,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= From f7fb794c5191d0f7ec4c42339e18804792168c5e Mon Sep 17 00:00:00 2001 From: udhos Date: Thu, 23 May 2024 23:34:47 -0300 Subject: [PATCH 16/44] Upgrade dependency. --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 59129ff..42eef20 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/udhos/groupcache_exporter -go 1.22.0 +go 1.22.3 require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da @@ -19,5 +19,5 @@ require ( github.com/segmentio/fasthash v1.0.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect golang.org/x/sys v0.17.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect ) diff --git a/go.sum b/go.sum index 99d5b01..28928cf 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 89a39eaf2bfd10a4d82402372ada0b194a8295c3 Mon Sep 17 00:00:00 2001 From: udhos Date: Wed, 23 Oct 2024 21:49:40 -0300 Subject: [PATCH 17/44] Upgrade dependencies. --- go.mod | 22 ++++++++++++---------- go.sum | 55 ++++++++++++++++++++++++++++--------------------------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index 42eef20..764c584 100644 --- a/go.mod +++ b/go.mod @@ -1,23 +1,25 @@ module github.com/udhos/groupcache_exporter -go 1.22.3 +go 1.23.2 require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/mailgun/groupcache/v2 v2.5.0 - github.com/modernprogram/groupcache/v2 v2.5.6 - github.com/prometheus/client_golang v1.18.0 + github.com/modernprogram/groupcache/v2 v2.6.0 + github.com/prometheus/client_golang v1.20.5 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.46.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/segmentio/fasthash v1.0.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - golang.org/x/sys v0.17.0 // indirect - google.golang.org/protobuf v1.34.1 // indirect + golang.org/x/sys v0.26.0 // indirect + google.golang.org/protobuf v1.35.1 // indirect ) diff --git a/go.sum b/go.sum index 28928cf..f383bb0 100644 --- a/go.sum +++ b/go.sum @@ -1,48 +1,49 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/modernprogram/groupcache/v2 v2.5.6 h1:G4e9QJEghQRBIO1WyIkSw1S2vyjpY9DlZgMsVuymYHU= -github.com/modernprogram/groupcache/v2 v2.5.6/go.mod h1:it+NoQbGs35RSn/5bdw6b3QEjEw0bLB/lYIywZrxyFY= +github.com/modernprogram/groupcache/v2 v2.6.0 h1:I+JWwYUg+8W0+IxkpBIHSBd8TKl9kbHL6HKDZ4iF7e0= +github.com/modernprogram/groupcache/v2 v2.6.0/go.mod h1:it+NoQbGs35RSn/5bdw6b3QEjEw0bLB/lYIywZrxyFY= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= -github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 5311f255cd23538b5ec6cffc4660d9294538cdff Mon Sep 17 00:00:00 2001 From: udhos Date: Wed, 20 Nov 2024 18:05:24 -0300 Subject: [PATCH 18/44] Export number of evictions for non-expired keys. --- .../groupcache.go | 6 ++- exporter.go | 40 ++++++++++++------- go.mod | 10 ++--- go.sum | 16 ++++---- groupcache/google/adapter.go | 10 +++++ groupcache/mailgun/adapter.go | 10 +++++ groupcache/modernprogram/adapter.go | 10 +++++ 7 files changed, 73 insertions(+), 29 deletions(-) diff --git a/examples/groupcache-exporter-modernprogram/groupcache.go b/examples/groupcache-exporter-modernprogram/groupcache.go index 5018a1e..3ac6038 100644 --- a/examples/groupcache-exporter-modernprogram/groupcache.go +++ b/examples/groupcache-exporter-modernprogram/groupcache.go @@ -20,13 +20,15 @@ func startGroupcache() *groupcache.Group { // create groupcache pool // + workspace := groupcache.NewWorkspace() + groupcachePort := ":5000" myURL := "http://127.0.0.1" + groupcachePort log.Printf("groupcache my URL: %s", myURL) - pool := groupcache.NewHTTPPoolOpts(myURL, &groupcache.HTTPPoolOptions{}) + pool := groupcache.NewHTTPPoolOptsWithWorkspace(workspace, myURL, &groupcache.HTTPPoolOptions{}) // // start groupcache server @@ -51,7 +53,7 @@ func startGroupcache() *groupcache.Group { // https://talks.golang.org/2013/oscon-dl.slide#46 // // 64 MB max per-node memory usage - cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( + cache := groupcache.NewGroupWithWorkspace(workspace, "files", groupcacheSizeBytes, groupcache.GetterFunc( func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) diff --git a/exporter.go b/exporter.go index e7b15af..872f8ea 100644 --- a/exporter.go +++ b/exporter.go @@ -9,20 +9,21 @@ import ( type Exporter struct { groups []GroupStatistics - groupGets *prometheus.Desc - groupCacheHits *prometheus.Desc - groupPeerLoads *prometheus.Desc - groupPeerErrors *prometheus.Desc - groupLoads *prometheus.Desc - groupLoadsDeduped *prometheus.Desc - groupLocalLoads *prometheus.Desc - groupLocalLoadErrs *prometheus.Desc - groupServerRequests *prometheus.Desc - cacheBytes *prometheus.Desc - cacheItems *prometheus.Desc - cacheGets *prometheus.Desc - cacheHits *prometheus.Desc - cacheEvictions *prometheus.Desc + groupGets *prometheus.Desc + groupCacheHits *prometheus.Desc + groupPeerLoads *prometheus.Desc + groupPeerErrors *prometheus.Desc + groupLoads *prometheus.Desc + groupLoadsDeduped *prometheus.Desc + groupLocalLoads *prometheus.Desc + groupLocalLoadErrs *prometheus.Desc + groupServerRequests *prometheus.Desc + cacheBytes *prometheus.Desc + cacheItems *prometheus.Desc + cacheGets *prometheus.Desc + cacheHits *prometheus.Desc + cacheEvictions *prometheus.Desc + cacheEvictionsNonExpired *prometheus.Desc } // GroupStatistics is a plugable interface to extract metrics from a groupcache implementation. @@ -68,12 +69,14 @@ type GroupStatistics interface { MainCacheGets() int64 MainCacheHits() int64 MainCacheEvictions() int64 + MainCacheEvictionsNonExpired() int64 HotCacheItems() int64 HotCacheBytes() int64 HotCacheGets() int64 HotCacheHits() int64 HotCacheEvictions() int64 + HotCacheEvictionsNonExpired() int64 } // NewExporter creates Exporter. @@ -168,6 +171,12 @@ func NewExporter(namespace string, labels map[string]string, groups ...GroupStat []string{"group", "type"}, labels, ), + cacheEvictionsNonExpired: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "cache_evictions_nonexpired_total"), + "Count of cache evictions for non-expired keys", + []string{"group", "type"}, + labels, + ), } } @@ -187,6 +196,7 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.cacheGets ch <- e.cacheHits ch <- e.cacheEvictions + ch <- e.cacheEvictionsNonExpired } // Collect is called by the Prometheus registry when collecting metrics. @@ -219,10 +229,12 @@ func (e *Exporter) collectCacheStats(ch chan<- prometheus.Metric, stats GroupSta ch <- prometheus.MustNewConstMetric(e.cacheGets, prometheus.CounterValue, float64(stats.MainCacheGets()), stats.Name(), "main") ch <- prometheus.MustNewConstMetric(e.cacheHits, prometheus.CounterValue, float64(stats.MainCacheHits()), stats.Name(), "main") ch <- prometheus.MustNewConstMetric(e.cacheEvictions, prometheus.CounterValue, float64(stats.MainCacheEvictions()), stats.Name(), "main") + ch <- prometheus.MustNewConstMetric(e.cacheEvictionsNonExpired, prometheus.CounterValue, float64(stats.MainCacheEvictionsNonExpired()), stats.Name(), "main") ch <- prometheus.MustNewConstMetric(e.cacheItems, prometheus.GaugeValue, float64(stats.HotCacheItems()), stats.Name(), "hot") ch <- prometheus.MustNewConstMetric(e.cacheBytes, prometheus.GaugeValue, float64(stats.HotCacheBytes()), stats.Name(), "hot") ch <- prometheus.MustNewConstMetric(e.cacheGets, prometheus.CounterValue, float64(stats.HotCacheGets()), stats.Name(), "hot") ch <- prometheus.MustNewConstMetric(e.cacheHits, prometheus.CounterValue, float64(stats.HotCacheHits()), stats.Name(), "hot") ch <- prometheus.MustNewConstMetric(e.cacheEvictions, prometheus.CounterValue, float64(stats.HotCacheEvictions()), stats.Name(), "hot") + ch <- prometheus.MustNewConstMetric(e.cacheEvictionsNonExpired, prometheus.CounterValue, float64(stats.HotCacheEvictionsNonExpired()), stats.Name(), "hot") } diff --git a/go.mod b/go.mod index 764c584..8a7aff1 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/udhos/groupcache_exporter -go 1.23.2 +go 1.23.3 require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/mailgun/groupcache/v2 v2.5.0 - github.com/modernprogram/groupcache/v2 v2.6.0 + github.com/modernprogram/groupcache/v2 v2.6.1 github.com/prometheus/client_golang v1.20.5 ) @@ -16,10 +16,10 @@ require ( github.com/klauspost/compress v1.17.11 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/segmentio/fasthash v1.0.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - golang.org/x/sys v0.26.0 // indirect - google.golang.org/protobuf v1.35.1 // indirect + golang.org/x/sys v0.27.0 // indirect + google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/go.sum b/go.sum index f383bb0..12c5c44 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/modernprogram/groupcache/v2 v2.6.0 h1:I+JWwYUg+8W0+IxkpBIHSBd8TKl9kbHL6HKDZ4iF7e0= -github.com/modernprogram/groupcache/v2 v2.6.0/go.mod h1:it+NoQbGs35RSn/5bdw6b3QEjEw0bLB/lYIywZrxyFY= +github.com/modernprogram/groupcache/v2 v2.6.1 h1:6mLYSQcHYUntlvZO2Y4cPHHCRw81hQ6eueiB21Ia9g8= +github.com/modernprogram/groupcache/v2 v2.6.1/go.mod h1:fR6q6Ud5gTrAlh8dXOyJulyl4EnbihlEEfNN8KupkFU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -27,8 +27,8 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= @@ -40,10 +40,10 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/groupcache/google/adapter.go b/groupcache/google/adapter.go index 578b989..5e74bb3 100644 --- a/groupcache/google/adapter.go +++ b/groupcache/google/adapter.go @@ -95,6 +95,11 @@ func (g *Group) MainCacheEvictions() int64 { return g.group.CacheStats(groupcache.MainCache).Evictions } +// MainCacheEvictionsNonExpired represents number of evictions for non-expired keys in the main cache +func (g *Group) MainCacheEvictionsNonExpired() int64 { + return 0 +} + // HotCacheItems represents number of items in the main cache func (g *Group) HotCacheItems() int64 { return g.group.CacheStats(groupcache.HotCache).Items @@ -119,3 +124,8 @@ func (g *Group) HotCacheHits() int64 { func (g *Group) HotCacheEvictions() int64 { return g.group.CacheStats(groupcache.HotCache).Evictions } + +// HotCacheEvictionsNonExpired represents number of evictions for non-expired keys in the hot cache +func (g *Group) HotCacheEvictionsNonExpired() int64 { + return 0 +} diff --git a/groupcache/mailgun/adapter.go b/groupcache/mailgun/adapter.go index c50306d..0dff1fd 100644 --- a/groupcache/mailgun/adapter.go +++ b/groupcache/mailgun/adapter.go @@ -95,6 +95,11 @@ func (g *Group) MainCacheEvictions() int64 { return g.group.CacheStats(groupcache.MainCache).Evictions } +// MainCacheEvictionsNonExpired represents number of evictions for non-expired keys in the main cache +func (g *Group) MainCacheEvictionsNonExpired() int64 { + return 0 +} + // HotCacheItems represents number of items in the main cache func (g *Group) HotCacheItems() int64 { return g.group.CacheStats(groupcache.HotCache).Items @@ -119,3 +124,8 @@ func (g *Group) HotCacheHits() int64 { func (g *Group) HotCacheEvictions() int64 { return g.group.CacheStats(groupcache.HotCache).Evictions } + +// HotCacheEvictionsNonExpired represents number of evictions for non-expired keys in the hot cache +func (g *Group) HotCacheEvictionsNonExpired() int64 { + return 0 +} diff --git a/groupcache/modernprogram/adapter.go b/groupcache/modernprogram/adapter.go index 8919708..3cc2da9 100644 --- a/groupcache/modernprogram/adapter.go +++ b/groupcache/modernprogram/adapter.go @@ -95,6 +95,11 @@ func (g *Group) MainCacheEvictions() int64 { return g.group.CacheStats(groupcache.MainCache).Evictions } +// MainCacheEvictionsNonExpired represents number of evictions for non-expired keys in the main cache +func (g *Group) MainCacheEvictionsNonExpired() int64 { + return g.group.CacheStats(groupcache.MainCache).EvictionsNonExpired +} + // HotCacheItems represents number of items in the main cache func (g *Group) HotCacheItems() int64 { return g.group.CacheStats(groupcache.HotCache).Items @@ -119,3 +124,8 @@ func (g *Group) HotCacheHits() int64 { func (g *Group) HotCacheEvictions() int64 { return g.group.CacheStats(groupcache.HotCache).Evictions } + +// HotCacheEvictionsNonExpired represents number of evictions for non-expired keys in the hot cache +func (g *Group) HotCacheEvictionsNonExpired() int64 { + return g.group.CacheStats(groupcache.HotCache).EvictionsNonExpired +} From 346d8d2635dddaa2c337d13fd05e546b3aa59d7c Mon Sep 17 00:00:00 2001 From: udhos Date: Wed, 20 Nov 2024 23:25:40 -0300 Subject: [PATCH 19/44] Upgrade dependency. --- examples/groupcache-exporter-modernprogram/groupcache.go | 5 +++-- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/groupcache-exporter-modernprogram/groupcache.go b/examples/groupcache-exporter-modernprogram/groupcache.go index 3ac6038..f13fc66 100644 --- a/examples/groupcache-exporter-modernprogram/groupcache.go +++ b/examples/groupcache-exporter-modernprogram/groupcache.go @@ -48,12 +48,13 @@ func startGroupcache() *groupcache.Group { // create cache // - var groupcacheSizeBytes int64 = 1_000_000 + const purgeExpired = true + const groupcacheSizeBytes = 1_000_000 // https://talks.golang.org/2013/oscon-dl.slide#46 // // 64 MB max per-node memory usage - cache := groupcache.NewGroupWithWorkspace(workspace, "files", groupcacheSizeBytes, groupcache.GetterFunc( + cache := groupcache.NewGroupWithWorkspace(workspace, "files", purgeExpired, groupcacheSizeBytes, groupcache.GetterFunc( func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) diff --git a/go.mod b/go.mod index 8a7aff1..bc61412 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.3 require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/mailgun/groupcache/v2 v2.5.0 - github.com/modernprogram/groupcache/v2 v2.6.1 + github.com/modernprogram/groupcache/v2 v2.6.2 github.com/prometheus/client_golang v1.20.5 ) diff --git a/go.sum b/go.sum index 12c5c44..4a602b4 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/modernprogram/groupcache/v2 v2.6.1 h1:6mLYSQcHYUntlvZO2Y4cPHHCRw81hQ6eueiB21Ia9g8= -github.com/modernprogram/groupcache/v2 v2.6.1/go.mod h1:fR6q6Ud5gTrAlh8dXOyJulyl4EnbihlEEfNN8KupkFU= +github.com/modernprogram/groupcache/v2 v2.6.2 h1:R/vOLKU5sXb5GZoUfQ9KJuSYc3LTK2hkpETD131NktQ= +github.com/modernprogram/groupcache/v2 v2.6.2/go.mod h1:fR6q6Ud5gTrAlh8dXOyJulyl4EnbihlEEfNN8KupkFU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= From f5714f0349f1b91a4bc7f5aeadc504fc2024b5bd Mon Sep 17 00:00:00 2001 From: udhos Date: Sat, 23 Nov 2024 18:27:20 -0300 Subject: [PATCH 20/44] Upgrade dependency. --- go.mod | 2 +- go.sum | 4 ++-- groupcache/modernprogram/adapter.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index bc61412..9b7cc10 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.3 require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/mailgun/groupcache/v2 v2.5.0 - github.com/modernprogram/groupcache/v2 v2.6.2 + github.com/modernprogram/groupcache/v2 v2.6.3 github.com/prometheus/client_golang v1.20.5 ) diff --git a/go.sum b/go.sum index 4a602b4..00d83e6 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/modernprogram/groupcache/v2 v2.6.2 h1:R/vOLKU5sXb5GZoUfQ9KJuSYc3LTK2hkpETD131NktQ= -github.com/modernprogram/groupcache/v2 v2.6.2/go.mod h1:fR6q6Ud5gTrAlh8dXOyJulyl4EnbihlEEfNN8KupkFU= +github.com/modernprogram/groupcache/v2 v2.6.3 h1:UXED5takUY36n9gKHGMfDZyCH+ho0yGcI/t0pbx8TmY= +github.com/modernprogram/groupcache/v2 v2.6.3/go.mod h1:fR6q6Ud5gTrAlh8dXOyJulyl4EnbihlEEfNN8KupkFU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/groupcache/modernprogram/adapter.go b/groupcache/modernprogram/adapter.go index 3cc2da9..3feee97 100644 --- a/groupcache/modernprogram/adapter.go +++ b/groupcache/modernprogram/adapter.go @@ -97,7 +97,7 @@ func (g *Group) MainCacheEvictions() int64 { // MainCacheEvictionsNonExpired represents number of evictions for non-expired keys in the main cache func (g *Group) MainCacheEvictionsNonExpired() int64 { - return g.group.CacheStats(groupcache.MainCache).EvictionsNonExpired + return g.group.CacheStats(groupcache.MainCache).EvictionsNonExpiredOnMemFull } // HotCacheItems represents number of items in the main cache @@ -127,5 +127,5 @@ func (g *Group) HotCacheEvictions() int64 { // HotCacheEvictionsNonExpired represents number of evictions for non-expired keys in the hot cache func (g *Group) HotCacheEvictionsNonExpired() int64 { - return g.group.CacheStats(groupcache.HotCache).EvictionsNonExpired + return g.group.CacheStats(groupcache.HotCache).EvictionsNonExpiredOnMemFull } From 5a39b89d65bb316a1cdfc87f76576f3170975354 Mon Sep 17 00:00:00 2001 From: udhos Date: Sat, 23 Nov 2024 18:31:31 -0300 Subject: [PATCH 21/44] Improve stat description. --- exporter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter.go b/exporter.go index 872f8ea..285a9e1 100644 --- a/exporter.go +++ b/exporter.go @@ -173,7 +173,7 @@ func NewExporter(namespace string, labels map[string]string, groups ...GroupStat ), cacheEvictionsNonExpired: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "cache_evictions_nonexpired_total"), - "Count of cache evictions for non-expired keys", + "Count of cache evictions for non-expired keys due to memory full.", []string{"group", "type"}, labels, ), From 9b4ce81c3e8fe3e043d747060d099579d1bf4294 Mon Sep 17 00:00:00 2001 From: udhos Date: Thu, 5 Dec 2024 02:56:21 -0300 Subject: [PATCH 22/44] Expose latency metric for slowest get from peers. --- exporter.go | 40 +++++++++++++++++++++++++--------------- go.mod | 2 +- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/exporter.go b/exporter.go index 285a9e1..d111082 100644 --- a/exporter.go +++ b/exporter.go @@ -9,21 +9,22 @@ import ( type Exporter struct { groups []GroupStatistics - groupGets *prometheus.Desc - groupCacheHits *prometheus.Desc - groupPeerLoads *prometheus.Desc - groupPeerErrors *prometheus.Desc - groupLoads *prometheus.Desc - groupLoadsDeduped *prometheus.Desc - groupLocalLoads *prometheus.Desc - groupLocalLoadErrs *prometheus.Desc - groupServerRequests *prometheus.Desc - cacheBytes *prometheus.Desc - cacheItems *prometheus.Desc - cacheGets *prometheus.Desc - cacheHits *prometheus.Desc - cacheEvictions *prometheus.Desc - cacheEvictionsNonExpired *prometheus.Desc + groupGets *prometheus.Desc + groupCacheHits *prometheus.Desc + groupGetFromPeersLatencyLower *prometheus.Desc + groupPeerLoads *prometheus.Desc + groupPeerErrors *prometheus.Desc + groupLoads *prometheus.Desc + groupLoadsDeduped *prometheus.Desc + groupLocalLoads *prometheus.Desc + groupLocalLoadErrs *prometheus.Desc + groupServerRequests *prometheus.Desc + cacheBytes *prometheus.Desc + cacheItems *prometheus.Desc + cacheGets *prometheus.Desc + cacheHits *prometheus.Desc + cacheEvictions *prometheus.Desc + cacheEvictionsNonExpired *prometheus.Desc } // GroupStatistics is a plugable interface to extract metrics from a groupcache implementation. @@ -87,6 +88,7 @@ func NewExporter(namespace string, labels map[string]string, groups ...GroupStat return &Exporter{ groups: groups, + groupGets: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "gets_total"), "Count of cache gets (including from peers)", @@ -99,6 +101,12 @@ func NewExporter(namespace string, labels map[string]string, groups ...GroupStat []string{"group"}, labels, ), + groupGetFromPeersLatencyLower: prometheus.NewDesc( + prometheus.BuildFQName(namespace, subsystem, "get_from_peers_latency_slowest_milliseconds"), + "Represent slowest duration to request value from peers.", + []string{"group"}, + labels, + ), groupPeerLoads: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "peer_loads_total"), "Count of non-error loads or cache hits from peers", @@ -184,6 +192,7 @@ func NewExporter(namespace string, labels map[string]string, groups ...GroupStat func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.groupGets ch <- e.groupCacheHits + ch <- e.groupGetFromPeersLatencyLower ch <- e.groupPeerLoads ch <- e.groupPeerErrors ch <- e.groupLoads @@ -214,6 +223,7 @@ func (e *Exporter) collectFromGroup(ch chan<- prometheus.Metric, stats GroupStat func (e *Exporter) collectStats(ch chan<- prometheus.Metric, stats GroupStatistics) { ch <- prometheus.MustNewConstMetric(e.groupGets, prometheus.CounterValue, float64(stats.Gets()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupCacheHits, prometheus.CounterValue, float64(stats.CacheHits()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupGetFromPeersLatencyLower, prometheus.GaugeValue, float64(stats.GetFromPeersLatencyLower()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupPeerLoads, prometheus.CounterValue, float64(stats.PeerLoads()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupPeerErrors, prometheus.CounterValue, float64(stats.PeerErrors()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupLoads, prometheus.CounterValue, float64(stats.Loads()), stats.Name()) diff --git a/go.mod b/go.mod index 9b7cc10..168e12d 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/udhos/groupcache_exporter -go 1.23.3 +go 1.23.4 require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da From 2565f5bf97e866c3443b63f3d2199a54c4b54bc8 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Sat, 21 Dec 2024 14:48:14 -0500 Subject: [PATCH 23/44] Set Golang 1.22 and remove non-Mailgun groupcache references. --- .../groupcache-exporter-google/groupcache.go | 63 --------- examples/groupcache-exporter-google/main.go | 62 --------- examples/groupcache-exporter-mailgun/main.go | 4 +- .../groupcache.go | 72 ---------- .../groupcache-exporter-modernprogram/main.go | 62 --------- go.mod | 6 +- go.sum | 4 - groupcache/google/adapter.go | 131 ------------------ groupcache/modernprogram/adapter.go | 131 ------------------ 9 files changed, 4 insertions(+), 531 deletions(-) delete mode 100644 examples/groupcache-exporter-google/groupcache.go delete mode 100644 examples/groupcache-exporter-google/main.go delete mode 100644 examples/groupcache-exporter-modernprogram/groupcache.go delete mode 100644 examples/groupcache-exporter-modernprogram/main.go delete mode 100644 groupcache/google/adapter.go delete mode 100644 groupcache/modernprogram/adapter.go diff --git a/examples/groupcache-exporter-google/groupcache.go b/examples/groupcache-exporter-google/groupcache.go deleted file mode 100644 index 4ec93fd..0000000 --- a/examples/groupcache-exporter-google/groupcache.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "context" - "log" - "net/http" - "os" - - "github.com/golang/groupcache" -) - -func startGroupcache() *groupcache.Group { - - // - // create groupcache pool - // - - groupcachePort := ":5000" - - myURL := "http://127.0.0.1" + groupcachePort - - log.Printf("groupcache my URL: %s", myURL) - - pool := groupcache.NewHTTPPoolOpts(myURL, &groupcache.HTTPPoolOptions{}) - - // - // start groupcache server - // - - serverGroupCache := &http.Server{Addr: groupcachePort, Handler: pool} - - go func() { - log.Printf("groupcache server: listening on %s", groupcachePort) - err := serverGroupCache.ListenAndServe() - log.Printf("groupcache server: exited: %v", err) - }() - - pool.Set(myURL) - - // - // create cache - // - - var groupcacheSizeBytes int64 = 1_000_000 - - // https://talks.golang.org/2013/oscon-dl.slide#46 - // - // 64 MB max per-node memory usage - cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( - func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { - - log.Printf("getter: loading: key:%s", key) - - data, errFile := os.ReadFile(key) - if errFile != nil { - return errFile - } - - return dest.SetBytes(data) - })) - - return cache -} diff --git a/examples/groupcache-exporter-google/main.go b/examples/groupcache-exporter-google/main.go deleted file mode 100644 index f12b77e..0000000 --- a/examples/groupcache-exporter-google/main.go +++ /dev/null @@ -1,62 +0,0 @@ -// Package main implements the example. -package main - -import ( - "context" - "log" - "net/http" - "os" - "path/filepath" - "time" - - "github.com/golang/groupcache" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/udhos/groupcache_exporter" - "github.com/udhos/groupcache_exporter/groupcache/google" -) - -func main() { - - appName := filepath.Base(os.Args[0]) - - cache := startGroupcache() - - // - // expose prometheus metrics - // - { - metricsRoute := "/metrics" - metricsPort := ":3000" - - log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) - - google := google.New(cache) - labels := map[string]string{ - "app": appName, - } - namespace := "" - collector := groupcache_exporter.NewExporter(namespace, labels, google) - - prometheus.MustRegister(collector) - - go func() { - http.Handle(metricsRoute, promhttp.Handler()) - log.Fatal(http.ListenAndServe(metricsPort, nil)) - }() - } - - // - // query cache periodically - // - - const interval = 5 * time.Second - - for { - var dst []byte - cache.Get(context.TODO(), "/etc/passwd", groupcache.AllocatingByteSliceSink(&dst)) - log.Printf("cache answer: %d bytes, sleeping %v", len(dst), interval) - time.Sleep(interval) - } - -} diff --git a/examples/groupcache-exporter-mailgun/main.go b/examples/groupcache-exporter-mailgun/main.go index 3e6dc98..cda8b3e 100644 --- a/examples/groupcache-exporter-mailgun/main.go +++ b/examples/groupcache-exporter-mailgun/main.go @@ -9,11 +9,11 @@ import ( "path/filepath" "time" + "github.com/Baliedge/groupcache_exporter" + "github.com/Baliedge/groupcache_exporter/groupcache/mailgun" "github.com/mailgun/groupcache/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/udhos/groupcache_exporter" - "github.com/udhos/groupcache_exporter/groupcache/mailgun" ) func main() { diff --git a/examples/groupcache-exporter-modernprogram/groupcache.go b/examples/groupcache-exporter-modernprogram/groupcache.go deleted file mode 100644 index f13fc66..0000000 --- a/examples/groupcache-exporter-modernprogram/groupcache.go +++ /dev/null @@ -1,72 +0,0 @@ -package main - -import ( - "context" - "log" - "net/http" - "os" - "time" - - "github.com/modernprogram/groupcache/v2" -) - -func startGroupcache() *groupcache.Group { - - ttl := time.Minute - - log.Printf("groupcache ttl: %v", ttl) - - // - // create groupcache pool - // - - workspace := groupcache.NewWorkspace() - - groupcachePort := ":5000" - - myURL := "http://127.0.0.1" + groupcachePort - - log.Printf("groupcache my URL: %s", myURL) - - pool := groupcache.NewHTTPPoolOptsWithWorkspace(workspace, myURL, &groupcache.HTTPPoolOptions{}) - - // - // start groupcache server - // - - serverGroupCache := &http.Server{Addr: groupcachePort, Handler: pool} - - go func() { - log.Printf("groupcache server: listening on %s", groupcachePort) - err := serverGroupCache.ListenAndServe() - log.Printf("groupcache server: exited: %v", err) - }() - - pool.Set(myURL) - - // - // create cache - // - - const purgeExpired = true - const groupcacheSizeBytes = 1_000_000 - - // https://talks.golang.org/2013/oscon-dl.slide#46 - // - // 64 MB max per-node memory usage - cache := groupcache.NewGroupWithWorkspace(workspace, "files", purgeExpired, groupcacheSizeBytes, groupcache.GetterFunc( - func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { - - log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) - - data, errFile := os.ReadFile(key) - if errFile != nil { - return errFile - } - - expire := time.Now().Add(ttl) - return dest.SetBytes(data, expire) - })) - - return cache -} diff --git a/examples/groupcache-exporter-modernprogram/main.go b/examples/groupcache-exporter-modernprogram/main.go deleted file mode 100644 index 40e9446..0000000 --- a/examples/groupcache-exporter-modernprogram/main.go +++ /dev/null @@ -1,62 +0,0 @@ -// Package main implements the example. -package main - -import ( - "context" - "log" - "net/http" - "os" - "path/filepath" - "time" - - "github.com/modernprogram/groupcache/v2" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/udhos/groupcache_exporter" - "github.com/udhos/groupcache_exporter/groupcache/modernprogram" -) - -func main() { - - appName := filepath.Base(os.Args[0]) - - cache := startGroupcache() - - // - // expose prometheus metrics - // - { - metricsRoute := "/metrics" - metricsPort := ":3000" - - log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) - - modernprogram := modernprogram.New(cache) - labels := map[string]string{ - "app": appName, - } - namespace := "" - collector := groupcache_exporter.NewExporter(namespace, labels, modernprogram) - - prometheus.MustRegister(collector) - - go func() { - http.Handle(metricsRoute, promhttp.Handler()) - log.Fatal(http.ListenAndServe(metricsPort, nil)) - }() - } - - // - // query cache periodically - // - - const interval = 5 * time.Second - - for { - var dst []byte - cache.Get(context.TODO(), "/etc/passwd", groupcache.AllocatingByteSliceSink(&dst)) - log.Printf("cache answer: %d bytes, sleeping %v", len(dst), interval) - time.Sleep(interval) - } - -} diff --git a/go.mod b/go.mod index 168e12d..c8dffaf 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,9 @@ -module github.com/udhos/groupcache_exporter +module github.com/Baliedge/groupcache_exporter -go 1.23.4 +go 1.22 require ( - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/mailgun/groupcache/v2 v2.5.0 - github.com/modernprogram/groupcache/v2 v2.6.3 github.com/prometheus/client_golang v1.20.5 ) diff --git a/go.sum b/go.sum index 00d83e6..862d348 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,6 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -17,8 +15,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/modernprogram/groupcache/v2 v2.6.3 h1:UXED5takUY36n9gKHGMfDZyCH+ho0yGcI/t0pbx8TmY= -github.com/modernprogram/groupcache/v2 v2.6.3/go.mod h1:fR6q6Ud5gTrAlh8dXOyJulyl4EnbihlEEfNN8KupkFU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/groupcache/google/adapter.go b/groupcache/google/adapter.go deleted file mode 100644 index 5e74bb3..0000000 --- a/groupcache/google/adapter.go +++ /dev/null @@ -1,131 +0,0 @@ -// Package google implements an adapter to extract metrics from google groupcache. -package google - -import ( - "github.com/golang/groupcache" -) - -// Group implements interface GroupStatistics to extract metrics from google groupcache group. -type Group struct { - group *groupcache.Group -} - -// New creates a new Group. -func New(group *groupcache.Group) *Group { - return &Group{group: group} -} - -// Name returns the group's name -func (g *Group) Name() string { - return g.group.Name() -} - -// Gets represents any Get request, including from peers -func (g *Group) Gets() int64 { - return g.group.Stats.Gets.Get() -} - -// CacheHits represents either cache was good -func (g *Group) CacheHits() int64 { - return g.group.Stats.CacheHits.Get() -} - -// GetFromPeersLatencyLower represents slowest duration to request value from peers -func (g *Group) GetFromPeersLatencyLower() int64 { - return 0 -} - -// PeerLoads represents either remote load or remote cache hit (not an error) -func (g *Group) PeerLoads() int64 { - return g.group.Stats.PeerLoads.Get() -} - -// PeerErrors represents a count of errors from peers -func (g *Group) PeerErrors() int64 { - return g.group.Stats.PeerErrors.Get() -} - -// Loads represents (gets - cacheHits) -func (g *Group) Loads() int64 { - return g.group.Stats.Loads.Get() -} - -// LoadsDeduped represents after singleflight -func (g *Group) LoadsDeduped() int64 { - return g.group.Stats.LoadsDeduped.Get() -} - -// LocalLoads represents total good local loads -func (g *Group) LocalLoads() int64 { - return g.group.Stats.LocalLoads.Get() -} - -// LocalLoadErrs represents total bad local loads -func (g *Group) LocalLoadErrs() int64 { - return g.group.Stats.LocalLoadErrs.Get() -} - -// ServerRequests represents gets that came over the network from peers -func (g *Group) ServerRequests() int64 { - return g.group.Stats.ServerRequests.Get() -} - -// MainCacheItems represents number of items in the main cache -func (g *Group) MainCacheItems() int64 { - return g.group.CacheStats(groupcache.MainCache).Items -} - -// MainCacheBytes represents number of bytes in the main cache -func (g *Group) MainCacheBytes() int64 { - return g.group.CacheStats(groupcache.MainCache).Bytes -} - -// MainCacheGets represents number of get requests in the main cache -func (g *Group) MainCacheGets() int64 { - return g.group.CacheStats(groupcache.MainCache).Gets -} - -// MainCacheHits represents number of hit in the main cache -func (g *Group) MainCacheHits() int64 { - return g.group.CacheStats(groupcache.MainCache).Hits -} - -// MainCacheEvictions represents number of evictions in the main cache -func (g *Group) MainCacheEvictions() int64 { - return g.group.CacheStats(groupcache.MainCache).Evictions -} - -// MainCacheEvictionsNonExpired represents number of evictions for non-expired keys in the main cache -func (g *Group) MainCacheEvictionsNonExpired() int64 { - return 0 -} - -// HotCacheItems represents number of items in the main cache -func (g *Group) HotCacheItems() int64 { - return g.group.CacheStats(groupcache.HotCache).Items -} - -// HotCacheBytes represents number of bytes in the hot cache -func (g *Group) HotCacheBytes() int64 { - return g.group.CacheStats(groupcache.HotCache).Bytes -} - -// HotCacheGets represents number of get requests in the hot cache -func (g *Group) HotCacheGets() int64 { - return g.group.CacheStats(groupcache.HotCache).Gets -} - -// HotCacheHits represents number of hit in the hot cache -func (g *Group) HotCacheHits() int64 { - return g.group.CacheStats(groupcache.HotCache).Hits -} - -// HotCacheEvictions represents number of evictions in the hot cache -func (g *Group) HotCacheEvictions() int64 { - return g.group.CacheStats(groupcache.HotCache).Evictions -} - -// HotCacheEvictionsNonExpired represents number of evictions for non-expired keys in the hot cache -func (g *Group) HotCacheEvictionsNonExpired() int64 { - return 0 -} diff --git a/groupcache/modernprogram/adapter.go b/groupcache/modernprogram/adapter.go deleted file mode 100644 index 3feee97..0000000 --- a/groupcache/modernprogram/adapter.go +++ /dev/null @@ -1,131 +0,0 @@ -// Package modernprogram implements an adapter to extract metrics from modernprogram groupcache. -package modernprogram - -import ( - "github.com/modernprogram/groupcache/v2" -) - -// Group implements interface GroupStatistics to extract metrics from modernprogram groupcache group. -type Group struct { - group *groupcache.Group -} - -// New creates a new Group. -func New(group *groupcache.Group) *Group { - return &Group{group: group} -} - -// Name returns the group's name -func (g *Group) Name() string { - return g.group.Name() -} - -// Gets represents any Get request, including from peers -func (g *Group) Gets() int64 { - return g.group.Stats.Gets.Get() -} - -// CacheHits represents either cache was good -func (g *Group) CacheHits() int64 { - return g.group.Stats.CacheHits.Get() -} - -// GetFromPeersLatencyLower represents slowest duration to request value from peers -func (g *Group) GetFromPeersLatencyLower() int64 { - return g.group.Stats.GetFromPeersLatencyLower.Get() -} - -// PeerLoads represents either remote load or remote cache hit (not an error) -func (g *Group) PeerLoads() int64 { - return g.group.Stats.PeerLoads.Get() -} - -// PeerErrors represents a count of errors from peers -func (g *Group) PeerErrors() int64 { - return g.group.Stats.PeerErrors.Get() -} - -// Loads represents (gets - cacheHits) -func (g *Group) Loads() int64 { - return g.group.Stats.Loads.Get() -} - -// LoadsDeduped represents after singleflight -func (g *Group) LoadsDeduped() int64 { - return g.group.Stats.LoadsDeduped.Get() -} - -// LocalLoads represents total good local loads -func (g *Group) LocalLoads() int64 { - return g.group.Stats.LocalLoads.Get() -} - -// LocalLoadErrs represents total bad local loads -func (g *Group) LocalLoadErrs() int64 { - return g.group.Stats.LocalLoadErrs.Get() -} - -// ServerRequests represents gets that came over the network from peers -func (g *Group) ServerRequests() int64 { - return g.group.Stats.ServerRequests.Get() -} - -// MainCacheItems represents number of items in the main cache -func (g *Group) MainCacheItems() int64 { - return g.group.CacheStats(groupcache.MainCache).Items -} - -// MainCacheBytes represents number of bytes in the main cache -func (g *Group) MainCacheBytes() int64 { - return g.group.CacheStats(groupcache.MainCache).Bytes -} - -// MainCacheGets represents number of get requests in the main cache -func (g *Group) MainCacheGets() int64 { - return g.group.CacheStats(groupcache.MainCache).Gets -} - -// MainCacheHits represents number of hit in the main cache -func (g *Group) MainCacheHits() int64 { - return g.group.CacheStats(groupcache.MainCache).Hits -} - -// MainCacheEvictions represents number of evictions in the main cache -func (g *Group) MainCacheEvictions() int64 { - return g.group.CacheStats(groupcache.MainCache).Evictions -} - -// MainCacheEvictionsNonExpired represents number of evictions for non-expired keys in the main cache -func (g *Group) MainCacheEvictionsNonExpired() int64 { - return g.group.CacheStats(groupcache.MainCache).EvictionsNonExpiredOnMemFull -} - -// HotCacheItems represents number of items in the main cache -func (g *Group) HotCacheItems() int64 { - return g.group.CacheStats(groupcache.HotCache).Items -} - -// HotCacheBytes represents number of bytes in the hot cache -func (g *Group) HotCacheBytes() int64 { - return g.group.CacheStats(groupcache.HotCache).Bytes -} - -// HotCacheGets represents number of get requests in the hot cache -func (g *Group) HotCacheGets() int64 { - return g.group.CacheStats(groupcache.HotCache).Gets -} - -// HotCacheHits represents number of hit in the hot cache -func (g *Group) HotCacheHits() int64 { - return g.group.CacheStats(groupcache.HotCache).Hits -} - -// HotCacheEvictions represents number of evictions in the hot cache -func (g *Group) HotCacheEvictions() int64 { - return g.group.CacheStats(groupcache.HotCache).Evictions -} - -// HotCacheEvictionsNonExpired represents number of evictions for non-expired keys in the hot cache -func (g *Group) HotCacheEvictionsNonExpired() int64 { - return g.group.CacheStats(groupcache.HotCache).EvictionsNonExpiredOnMemFull -} From ba58e01aaf3fb19b0e830be494f12a4baf2b0ae1 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Sat, 21 Dec 2024 15:00:27 -0500 Subject: [PATCH 24/44] Add golangci-lint GHA. --- .github/workflow/lint.yaml | 31 +++++++++++ .golangci.yml | 102 +++++++++++++++++++++++++++++++++++++ Makefile | 9 ++++ 3 files changed, 142 insertions(+) create mode 100644 .github/workflow/lint.yaml create mode 100644 .golangci.yml create mode 100644 Makefile diff --git a/.github/workflow/lint.yaml b/.github/workflow/lint.yaml new file mode 100644 index 0000000..41324c6 --- /dev/null +++ b/.github/workflow/lint.yaml @@ -0,0 +1,31 @@ +name: Lint + +on: + push: + branches: [ main ] + +env: + GOLANGCI_LINT_VERSION: v1.62.2 + +jobs: + lint: + name: lint + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version-file: ./go.mod + + - name: Check that 'go mod tidy' was called before commit + run: go mod tidy && git diff --exit-code + + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: ${{ env.GOLANGCI_LINT_VERSION }} + skip-cache: true # cache/restore is done by actions/setup-go step + args: -v diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..080f761 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,102 @@ +linters: + # Please, do not use `enable-all`: it's deprecated and will be removed soon. + # Inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint. + # Full list of linters - https://golangci-lint.run/usage/linters + disable-all: true + enable: + # - bodyclose # https://github.com/timakin/bodyclose + # - gomodguard + # - errcheck # Mandatory. Do not disable. + # - gocritic + - goimports + # - gosec + # - gosimple + - govet + # - noctx + # - nolintlint + # - ineffassign # Mandatory. Do not disable. + # - staticcheck # Mandatory. Do not disable. + # - stylecheck + # - typecheck + # - unused + +# Other linters: +# - dogsled +# - dupl +# - exportloopref +# - exhaustive # e.g. missing cases in switch of type +# - funlen +# - gochecknoinits +# - gocognit +# - goconst +# - gocyclo +# - goerr113 +# - gofmt +# - goprintffuncname +# - lll +# - misspell +# - nakedret +# - nlreturn +# - prealloc +# - revive +# - rowserrcheck +# - stylecheck +# - unconvert +# - unparam + +linters-settings: + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + disabled-checks: + - dupImport # https://github.com/go-critic/go-critic/issues/845 + - whyNoLint # checked by nolintlint linter + - hugeParam # TODO(vtopc): configure(80 bytes is probably not so much) and enable. + - rangeValCopy # TODO(vtopc): configure(disable for tests) and enable. + + errcheck: + # List of functions to exclude from checking, where each entry is a single function to exclude. + # See https://github.com/kisielk/errcheck#excluding-functions for details. + exclude-functions: + - (io.Closer).Close + - (io.ReadCloser).Close + + govet: + enable-all: true + disable: + - shadow + - fieldalignment + + gomodguard: + blocked: + # List of blocked modules. + # Default: [] + modules: + - github.com/golang/protobuf: + recommendations: + - google.golang.org/protobuf + reason: "see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules" + - github.com/pkg/errors: + recommendations: + - errors + - github.com/mailgun/errors + reason: "Deprecated" + +issues: + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same-issues: 50 + +run: + # include test files or not, default is true + tests: true + + # Timeout for analysis, e.g. 30s, 5m. + # Default: 1m + timeout: 5m diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c0bb133 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +GOLANGCI_LINT = $(GOPATH)/bin/golangci-lint +GOLANGCI_LINT_VERSION = v1.62.2 + +$(GOLANGCI_LINT): + curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION) + +.PHONY: lint +lint: $(GOLANGCI_LINT) + $(GOLANGCI_LINT) run From 4c506d9dc993b6782fdcc2e07a998a16a40411e0 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Sat, 21 Dec 2024 21:51:55 -0500 Subject: [PATCH 25/44] Remove abstraction layer for multiple groupcache implementations. --- .../groupcache.go | 0 .../{groupcache-exporter-mailgun => }/main.go | 4 +- exporter.go | 11 +++- .../mailgun/adapter.go => statsadapter.go | 57 +++++++++---------- 4 files changed, 37 insertions(+), 35 deletions(-) rename examples/{groupcache-exporter-mailgun => }/groupcache.go (100%) rename examples/{groupcache-exporter-mailgun => }/main.go (91%) rename groupcache/mailgun/adapter.go => statsadapter.go (67%) diff --git a/examples/groupcache-exporter-mailgun/groupcache.go b/examples/groupcache.go similarity index 100% rename from examples/groupcache-exporter-mailgun/groupcache.go rename to examples/groupcache.go diff --git a/examples/groupcache-exporter-mailgun/main.go b/examples/main.go similarity index 91% rename from examples/groupcache-exporter-mailgun/main.go rename to examples/main.go index cda8b3e..ea3c08b 100644 --- a/examples/groupcache-exporter-mailgun/main.go +++ b/examples/main.go @@ -10,7 +10,6 @@ import ( "time" "github.com/Baliedge/groupcache_exporter" - "github.com/Baliedge/groupcache_exporter/groupcache/mailgun" "github.com/mailgun/groupcache/v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -31,12 +30,11 @@ func main() { log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) - mailgun := mailgun.New(cache) labels := map[string]string{ "app": appName, } namespace := "" - collector := groupcache_exporter.NewExporter(namespace, labels, mailgun) + collector := groupcache_exporter.NewExporter(namespace, labels, cache) prometheus.MustRegister(collector) diff --git a/exporter.go b/exporter.go index d111082..65dacea 100644 --- a/exporter.go +++ b/exporter.go @@ -2,6 +2,7 @@ package groupcache_exporter import ( + "github.com/mailgun/groupcache/v2" "github.com/prometheus/client_golang/prometheus" ) @@ -82,12 +83,16 @@ type GroupStatistics interface { // NewExporter creates Exporter. // namespace is usually the empty string. -func NewExporter(namespace string, labels map[string]string, groups ...GroupStatistics) *Exporter { - +func NewExporter(namespace string, labels map[string]string, groups ...*groupcache.Group) *Exporter { const subsystem = "groupcache" + statgroups := make([]GroupStatistics, 0, len(groups)) + for _, g := range groups { + statgroups = append(statgroups, newStatsAdapter(g)) + } + return &Exporter{ - groups: groups, + groups: statgroups, groupGets: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "gets_total"), diff --git a/groupcache/mailgun/adapter.go b/statsadapter.go similarity index 67% rename from groupcache/mailgun/adapter.go rename to statsadapter.go index 0dff1fd..c065f41 100644 --- a/groupcache/mailgun/adapter.go +++ b/statsadapter.go @@ -1,131 +1,130 @@ -// Package mailgun implements an adapter to extract metrics from mailgun groupcache. -package mailgun +package groupcache_exporter import ( "github.com/mailgun/groupcache/v2" ) -// Group implements interface GroupStatistics to extract metrics from mailgun groupcache group. -type Group struct { +// Group implements interface GroupStatistics to extract metrics from groupcache group. +type statsAdapter struct { group *groupcache.Group } // New creates a new Group. -func New(group *groupcache.Group) *Group { - return &Group{group: group} +func newStatsAdapter(group *groupcache.Group) *statsAdapter { + return &statsAdapter{group: group} } // Name returns the group's name -func (g *Group) Name() string { +func (g *statsAdapter) Name() string { return g.group.Name() } // Gets represents any Get request, including from peers -func (g *Group) Gets() int64 { +func (g *statsAdapter) Gets() int64 { return g.group.Stats.Gets.Get() } // CacheHits represents either cache was good -func (g *Group) CacheHits() int64 { +func (g *statsAdapter) CacheHits() int64 { return g.group.Stats.CacheHits.Get() } // GetFromPeersLatencyLower represents slowest duration to request value from peers -func (g *Group) GetFromPeersLatencyLower() int64 { +func (g *statsAdapter) GetFromPeersLatencyLower() int64 { return g.group.Stats.GetFromPeersLatencyLower.Get() } // PeerLoads represents either remote load or remote cache hit (not an error) -func (g *Group) PeerLoads() int64 { +func (g *statsAdapter) PeerLoads() int64 { return g.group.Stats.PeerLoads.Get() } // PeerErrors represents a count of errors from peers -func (g *Group) PeerErrors() int64 { +func (g *statsAdapter) PeerErrors() int64 { return g.group.Stats.PeerErrors.Get() } // Loads represents (gets - cacheHits) -func (g *Group) Loads() int64 { +func (g *statsAdapter) Loads() int64 { return g.group.Stats.Loads.Get() } // LoadsDeduped represents after singleflight -func (g *Group) LoadsDeduped() int64 { +func (g *statsAdapter) LoadsDeduped() int64 { return g.group.Stats.LoadsDeduped.Get() } // LocalLoads represents total good local loads -func (g *Group) LocalLoads() int64 { +func (g *statsAdapter) LocalLoads() int64 { return g.group.Stats.LocalLoads.Get() } // LocalLoadErrs represents total bad local loads -func (g *Group) LocalLoadErrs() int64 { +func (g *statsAdapter) LocalLoadErrs() int64 { return g.group.Stats.LocalLoadErrs.Get() } // ServerRequests represents gets that came over the network from peers -func (g *Group) ServerRequests() int64 { +func (g *statsAdapter) ServerRequests() int64 { return g.group.Stats.ServerRequests.Get() } // MainCacheItems represents number of items in the main cache -func (g *Group) MainCacheItems() int64 { +func (g *statsAdapter) MainCacheItems() int64 { return g.group.CacheStats(groupcache.MainCache).Items } // MainCacheBytes represents number of bytes in the main cache -func (g *Group) MainCacheBytes() int64 { +func (g *statsAdapter) MainCacheBytes() int64 { return g.group.CacheStats(groupcache.MainCache).Bytes } // MainCacheGets represents number of get requests in the main cache -func (g *Group) MainCacheGets() int64 { +func (g *statsAdapter) MainCacheGets() int64 { return g.group.CacheStats(groupcache.MainCache).Gets } // MainCacheHits represents number of hit in the main cache -func (g *Group) MainCacheHits() int64 { +func (g *statsAdapter) MainCacheHits() int64 { return g.group.CacheStats(groupcache.MainCache).Hits } // MainCacheEvictions represents number of evictions in the main cache -func (g *Group) MainCacheEvictions() int64 { +func (g *statsAdapter) MainCacheEvictions() int64 { return g.group.CacheStats(groupcache.MainCache).Evictions } // MainCacheEvictionsNonExpired represents number of evictions for non-expired keys in the main cache -func (g *Group) MainCacheEvictionsNonExpired() int64 { +func (g *statsAdapter) MainCacheEvictionsNonExpired() int64 { return 0 } // HotCacheItems represents number of items in the main cache -func (g *Group) HotCacheItems() int64 { +func (g *statsAdapter) HotCacheItems() int64 { return g.group.CacheStats(groupcache.HotCache).Items } // HotCacheBytes represents number of bytes in the hot cache -func (g *Group) HotCacheBytes() int64 { +func (g *statsAdapter) HotCacheBytes() int64 { return g.group.CacheStats(groupcache.HotCache).Bytes } // HotCacheGets represents number of get requests in the hot cache -func (g *Group) HotCacheGets() int64 { +func (g *statsAdapter) HotCacheGets() int64 { return g.group.CacheStats(groupcache.HotCache).Gets } // HotCacheHits represents number of hit in the hot cache -func (g *Group) HotCacheHits() int64 { +func (g *statsAdapter) HotCacheHits() int64 { return g.group.CacheStats(groupcache.HotCache).Hits } // HotCacheEvictions represents number of evictions in the hot cache -func (g *Group) HotCacheEvictions() int64 { +func (g *statsAdapter) HotCacheEvictions() int64 { return g.group.CacheStats(groupcache.HotCache).Evictions } // HotCacheEvictionsNonExpired represents number of evictions for non-expired keys in the hot cache -func (g *Group) HotCacheEvictionsNonExpired() int64 { +func (g *statsAdapter) HotCacheEvictionsNonExpired() int64 { return 0 } From b08abe9e573c5216c8a6195d9eac812cb9e9be84 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Sat, 21 Dec 2024 21:57:48 -0500 Subject: [PATCH 26/44] Update README.md. --- README.md | 94 +++---------------------------------------------------- 1 file changed, 5 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index dc826a3..3c49678 100644 --- a/README.md +++ b/README.md @@ -1,98 +1,14 @@ -[![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/udhos/groupcache_exporter/blob/main/LICENSE) -[![Go Report Card](https://goreportcard.com/badge/github.com/udhos/groupcache_exporter)](https://goreportcard.com/report/github.com/udhos/groupcache_exporter) -[![Go Reference](https://pkg.go.dev/badge/github.com/udhos/groupcache_exporter.svg)](https://pkg.go.dev/github.com/udhos/groupcache_exporter) +[![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Baliedge/groupcache_exporter/blob/main/LICENSE) -# Prometheus Groupcache exporter +# Prometheus Groupcache Exporter -This exporter implements the prometheus.Collector interface in order to expose Prometheus metrics for [groupcache](https://github.com/golang/groupcache). +This exporter extracts statistics from [groupcache](https://github.com/golang/groupcache) instances and converts to Prometheus metrics. -# Example for mailgun groupcache - -```golang -import "github.com/udhos/groupcache_exporter/groupcache/mailgun" - -// ... - -appName := filepath.Base(os.Args[0]) - -cache := startGroupcache() - -// -// expose prometheus metrics -// -{ - metricsRoute := "/metrics" - metricsPort := ":3000" - - log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) - - mailgun := mailgun.New(cache) - labels := map[string]string{ - "app": appName, - } - namespace := "" - collector := groupcache_exporter.NewExporter(namespace, labels, mailgun) - - prometheus.MustRegister(collector) - - go func() { - http.Handle(metricsRoute, promhttp.Handler()) - log.Fatal(http.ListenAndServe(metricsPort, nil)) - }() -} -``` +# Example Full example: [examples/groupcache-exporter-mailgun](examples/groupcache-exporter-mailgun) -# Example for modernprogram groupcache - -```golang -import "github.com/udhos/groupcache_exporter/groupcache/modernprogram" - -// ... - -appName := filepath.Base(os.Args[0]) - -cache := startGroupcache() - -// -// expose prometheus metrics -// -{ - metricsRoute := "/metrics" - metricsPort := ":3000" - - log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) - - modernprogram := modernprogram.New(cache) - labels := map[string]string{ - "app": appName, - } - namespace := "" - collector := groupcache_exporter.NewExporter(namespace, labels, modernprogram) - - prometheus.MustRegister(collector) - - go func() { - http.Handle(metricsRoute, promhttp.Handler()) - log.Fatal(http.ListenAndServe(metricsPort, nil)) - }() -} -``` - -Full example: [examples/groupcache-exporter-modernprogram](examples/groupcache-exporter-modernprogram) - -# Testing - -## Build - - go install ./... - -## Run example application - - groupcache-exporter-mailgun - -## Query the metrics endpoint +## Exported Metrics ```bash curl -s localhost:3000/metrics | grep -E ^groupcache From c2d5ccbe0874ffb5ebe0e4e8210c443fa5d2dfd4 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Sat, 21 Dec 2024 21:58:35 -0500 Subject: [PATCH 27/44] Remove unnecessary stuff. --- build.sh | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100755 build.sh diff --git a/build.sh b/build.sh deleted file mode 100755 index 2ce48af..0000000 --- a/build.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -go install golang.org/x/vuln/cmd/govulncheck@latest -go install golang.org/x/tools/cmd/deadcode@latest - -gofmt -s -w . - -revive ./... - -gocyclo -over 15 . - -go mod tidy - -govulncheck ./... -deadcode ./examples/* - -go env -w CGO_ENABLED=1 - -go test -race ./... - -go env -w CGO_ENABLED=0 - -go install ./... - -go env -u CGO_ENABLED From 8264fc5d5a6491179dea026617eb87be23ea7826 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Sat, 21 Dec 2024 22:08:35 -0500 Subject: [PATCH 28/44] Update linter config. --- .golangci.yml | 76 ++++++++------------------------------------------- 1 file changed, 12 insertions(+), 64 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 080f761..3662b21 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -4,45 +4,21 @@ linters: # Full list of linters - https://golangci-lint.run/usage/linters disable-all: true enable: - # - bodyclose # https://github.com/timakin/bodyclose - # - gomodguard - # - errcheck # Mandatory. Do not disable. - # - gocritic + - gomodguard + - errcheck + - gocritic - goimports - # - gosec - # - gosimple + - gosec + - gosimple - govet - # - noctx - # - nolintlint - # - ineffassign # Mandatory. Do not disable. - # - staticcheck # Mandatory. Do not disable. + - noctx + - nolintlint + - ineffassign + - staticcheck # - stylecheck - # - typecheck - # - unused - -# Other linters: -# - dogsled -# - dupl -# - exportloopref -# - exhaustive # e.g. missing cases in switch of type -# - funlen -# - gochecknoinits -# - gocognit -# - goconst -# - gocyclo -# - goerr113 -# - gofmt -# - goprintffuncname -# - lll -# - misspell -# - nakedret -# - nlreturn -# - prealloc -# - revive -# - rowserrcheck -# - stylecheck -# - unconvert -# - unparam + - typecheck + - unused + - gocyclo linters-settings: gocritic: @@ -52,40 +28,12 @@ linters-settings: - opinionated - performance - style - disabled-checks: - - dupImport # https://github.com/go-critic/go-critic/issues/845 - - whyNoLint # checked by nolintlint linter - - hugeParam # TODO(vtopc): configure(80 bytes is probably not so much) and enable. - - rangeValCopy # TODO(vtopc): configure(disable for tests) and enable. - - errcheck: - # List of functions to exclude from checking, where each entry is a single function to exclude. - # See https://github.com/kisielk/errcheck#excluding-functions for details. - exclude-functions: - - (io.Closer).Close - - (io.ReadCloser).Close govet: enable-all: true disable: - - shadow - fieldalignment - gomodguard: - blocked: - # List of blocked modules. - # Default: [] - modules: - - github.com/golang/protobuf: - recommendations: - - google.golang.org/protobuf - reason: "see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules" - - github.com/pkg/errors: - recommendations: - - errors - - github.com/mailgun/errors - reason: "Deprecated" - issues: # Maximum issues count per one linter. Set to 0 to disable. Default is 50. max-issues-per-linter: 0 From fe50da5fddf736630e240ebb8ec55b1eb6b5efad Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Sun, 22 Dec 2024 21:41:11 -0500 Subject: [PATCH 29/44] Tests for exporter. --- examples/groupcache.go | 2 +- exporter_test.go | 228 +++++++++++++++++++++++++++++++++++++++++ go.mod | 9 +- go.sum | 9 ++ 4 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 exporter_test.go diff --git a/examples/groupcache.go b/examples/groupcache.go index 46121d0..2ff5dd6 100644 --- a/examples/groupcache.go +++ b/examples/groupcache.go @@ -52,7 +52,7 @@ func startGroupcache() *groupcache.Group { // // 64 MB max per-node memory usage cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( - func(_ /*ctx*/ context.Context, key string, dest groupcache.Sink) error { + func(_ context.Context, key string, dest groupcache.Sink) error { log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) diff --git a/exporter_test.go b/exporter_test.go new file mode 100644 index 0000000..575cb94 --- /dev/null +++ b/exporter_test.go @@ -0,0 +1,228 @@ +package groupcache_exporter_test + +import ( + "bytes" + "context" + "fmt" + "io" + "net/http" + "sort" + "sync" + "testing" + "time" + + "github.com/Baliedge/groupcache_exporter" + "github.com/mailgun/groupcache/v2" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/client_golang/prometheus/testutil/promlint" + promdto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/expfmt" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type MetricInfo struct { + Name string + Labels prometheus.Labels +} + +func TestExporter(t *testing.T) { + // Given + const metricsRoute = "/metrics" + const httpPort = 9080 + const ttl = time.Minute + var wg sync.WaitGroup + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + // Setup groupcache. + getter := func(_ context.Context, key string, dest groupcache.Sink) error { + err := dest.SetString("foobar", time.Now().Add(ttl)) + require.NoError(t, err) + return nil + } + group := groupcache.NewGroup("test", 10_000, groupcache.GetterFunc(getter)) + gcexporter := groupcache_exporter.NewExporter("", nil, group) + prometheus.MustRegister(gcexporter) + + // Setup HTTP server. + mux := http.NewServeMux() + mux.Handle(metricsRoute, promhttp.Handler()) + httpSrv := &http.Server{ + Addr: fmt.Sprintf("127.0.0.1:%d", httpPort), + Handler: mux, + ReadHeaderTimeout: time.Minute, + } + wg.Add(1) + go func() { + _ = httpSrv.ListenAndServe() + wg.Done() + }() + defer func() { + // Tear down. + err := httpSrv.Shutdown(ctx) + require.NoError(t, err) + wg.Wait() + }() + + // When + // Add cache activity. + for i := 0; i < 10; i++ { + var value string + err := group.Get(ctx, fmt.Sprintf("key%d", i), groupcache.StringSink(&value)) + require.NoError(t, err) + } + + // Then + // Get metrics from endpoint. + httpClt := http.DefaultClient + metricsURL := fmt.Sprintf("http://127.0.0.1:%d%s", httpPort, metricsRoute) + rq, err := http.NewRequestWithContext(ctx, http.MethodGet, metricsURL, http.NoBody) + require.NoError(t, err) + rs, err := httpClt.Do(rq) + require.NoError(t, err) + content, err := io.ReadAll(rs.Body) + defer rs.Body.Close() + require.NoError(t, err) + + // Parse metrics and assert expected values are found. + expectedMetrics := []struct { + Name string + Labels prometheus.Labels + }{ + { + Name: "groupcache_cache_bytes", + Labels: prometheus.Labels{"type": "main"}, + }, + { + Name: "groupcache_cache_bytes", + Labels: prometheus.Labels{"type": "hot"}, + }, + { + Name: "groupcache_cache_evictions_total", + Labels: prometheus.Labels{"type": "main"}, + }, + { + Name: "groupcache_cache_evictions_total", + Labels: prometheus.Labels{"type": "hot"}, + }, + { + Name: "groupcache_cache_gets_total", + Labels: prometheus.Labels{"type": "main"}, + }, + { + Name: "groupcache_cache_gets_total", + Labels: prometheus.Labels{"type": "hot"}, + }, + { + Name: "groupcache_cache_hits_total", + Labels: prometheus.Labels{"type": "main"}, + }, + { + Name: "groupcache_cache_hits_total", + Labels: prometheus.Labels{"type": "hot"}, + }, + { + Name: "groupcache_cache_items", + Labels: prometheus.Labels{"type": "main"}, + }, + { + Name: "groupcache_cache_items", + Labels: prometheus.Labels{"type": "hot"}, + }, + { + Name: "groupcache_gets_total", + }, + { + Name: "groupcache_hits_total", + }, + { + Name: "groupcache_loads_deduped_total", + }, + { + Name: "groupcache_loads_total", + }, + { + Name: "groupcache_local_load_errs_total", + }, + { + Name: "groupcache_local_load_total", + }, + { + Name: "groupcache_peer_errors_total", + }, + { + Name: "groupcache_peer_loads_total", + }, + { + Name: "groupcache_server_requests_total", + }, + } + tp := new(expfmt.TextParser) + mfs, err := tp.TextToMetricFamilies(bytes.NewReader(content)) + require.NoError(t, err) + + for _, expectedMetric := range expectedMetrics { + testName := fmt.Sprintf("Metric %s{%s}", expectedMetric.Name, labelsToString(expectedMetric.Labels)) + t.Run(testName, func(t *testing.T) { + assertMetricPresent(t, expectedMetric, mfs) + }) + } + + t.Run("Lint", func(t *testing.T) { + // FIXME: Fix lint errors + t.Skip() + linter := promlint.New(bytes.NewReader(content)) + problems, err := linter.Lint() + require.NoError(t, err) + for _, problem := range problems { + assert.Fail(t, fmt.Sprintf("%#v", problem)) + } + }) +} + +// Assert expected metric name and labels are present. +func assertMetricPresent(t *testing.T, expected MetricInfo, mfs map[string]*promdto.MetricFamily) { + mf, ok := mfs[expected.Name] + if !assert.True(t, ok, "Metric not found") { + return + } + + matchFlag := false + for _, metric := range mf.Metric { + LM1: + for key, value := range expected.Labels { + for _, label := range metric.Label { + if label.Name == nil || label.Value == nil { + continue + } + if *label.Name == key && *label.Value == value { + // Label match, go to next expected label. + continue LM1 + } + } + break LM1 + } + // All labels match. + matchFlag = true + break + } + assert.True(t, matchFlag, "Labels mismatch") +} + +func labelsToString(labels prometheus.Labels) string { + keys := make([]string, 0, len(labels)) + for key := range labels { + keys = append(keys, key) + } + sort.Strings(keys) + var buf bytes.Buffer + for i, key := range keys { + if i > 0 { + buf.WriteString(",") + } + buf.WriteString(fmt.Sprintf("%s=%q", key, labels[key])) + } + return buf.String() +} diff --git a/go.mod b/go.mod index c8dffaf..b460302 100644 --- a/go.mod +++ b/go.mod @@ -5,19 +5,24 @@ go 1.22 require ( github.com/mailgun/groupcache/v2 v2.5.0 github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.60.1 + github.com/stretchr/testify v1.9.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/klauspost/compress v1.17.11 // indirect + github.com/kr/text v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/segmentio/fasthash v1.0.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect golang.org/x/sys v0.27.0 // indirect google.golang.org/protobuf v1.35.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 862d348..cfeb3aa 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -11,6 +12,10 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= @@ -27,6 +32,8 @@ github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPA github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -41,6 +48,8 @@ golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 0557d6cc8bcba8170d8a55c072d508e376f68451 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Mon, 23 Dec 2024 09:10:09 -0500 Subject: [PATCH 30/44] Tidy code. --- exporter_test.go | 87 +++++++++++++++++++++++++++++++++++++----------- go.mod | 2 ++ go.sum | 6 ++++ 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/exporter_test.go b/exporter_test.go index 575cb94..92caea4 100644 --- a/exporter_test.go +++ b/exporter_test.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "io" + "net" "net/http" "sort" "sync" @@ -13,6 +14,7 @@ import ( "github.com/Baliedge/groupcache_exporter" "github.com/mailgun/groupcache/v2" + "github.com/mailgun/holster/v4/retry" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/testutil/promlint" @@ -27,11 +29,14 @@ type MetricInfo struct { Labels prometheus.Labels } +const ( + pingRoute = "/ping" + metricsRoute = "/metrics" + ttl = time.Minute +) + func TestExporter(t *testing.T) { // Given - const metricsRoute = "/metrics" - const httpPort = 9080 - const ttl = time.Minute var wg sync.WaitGroup ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -48,20 +53,15 @@ func TestExporter(t *testing.T) { // Setup HTTP server. mux := http.NewServeMux() + mux.HandleFunc(pingRoute, pingHandler) mux.Handle(metricsRoute, promhttp.Handler()) - httpSrv := &http.Server{ - Addr: fmt.Sprintf("127.0.0.1:%d", httpPort), - Handler: mux, - ReadHeaderTimeout: time.Minute, - } - wg.Add(1) - go func() { - _ = httpSrv.ListenAndServe() - wg.Done() - }() + httpSrv, err := startHTTPServer(ctx, mux, &wg) + require.NoError(t, err) + t.Logf("HTTP server ready at %s", httpSrv.Addr) defer func() { // Tear down. - err := httpSrv.Shutdown(ctx) + t.Log("HTTP server shutting down...") + err = httpSrv.Shutdown(ctx) require.NoError(t, err) wg.Wait() }() @@ -70,17 +70,13 @@ func TestExporter(t *testing.T) { // Add cache activity. for i := 0; i < 10; i++ { var value string - err := group.Get(ctx, fmt.Sprintf("key%d", i), groupcache.StringSink(&value)) + err = group.Get(ctx, fmt.Sprintf("key%d", i), groupcache.StringSink(&value)) require.NoError(t, err) } // Then // Get metrics from endpoint. - httpClt := http.DefaultClient - metricsURL := fmt.Sprintf("http://127.0.0.1:%d%s", httpPort, metricsRoute) - rq, err := http.NewRequestWithContext(ctx, http.MethodGet, metricsURL, http.NoBody) - require.NoError(t, err) - rs, err := httpClt.Do(rq) + rs, err := getURL(ctx, fmt.Sprintf("http://%s%s", httpSrv.Addr, metricsRoute)) require.NoError(t, err) content, err := io.ReadAll(rs.Body) defer rs.Body.Close() @@ -182,6 +178,53 @@ func TestExporter(t *testing.T) { }) } +// Start an HTTP server on a dynamic port. +func startHTTPServer(ctx context.Context, mux *http.ServeMux, wg *sync.WaitGroup) (*http.Server, error) { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return nil, err + } + httpSrv := &http.Server{ + Addr: listener.Addr().(*net.TCPAddr).AddrPort().String(), + Handler: mux, + ReadHeaderTimeout: time.Minute, + } + wg.Add(1) + go func() { + _ = httpSrv.Serve(listener) + wg.Done() + }() + err = waitForReady(ctx, httpSrv) + return httpSrv, err +} + +func waitForReady(ctx context.Context, httpSrv *http.Server) error { + httpClt := http.DefaultClient + return retry.Until(ctx, retry.Interval(20*time.Millisecond), func(ctx context.Context, _ int) error { + pingURL := fmt.Sprintf("http://%s%s", httpSrv.Addr, pingRoute) + ctx2, cancel2 := context.WithTimeout(ctx, 10*time.Second) + defer cancel2() + rq, err := http.NewRequestWithContext(ctx2, http.MethodGet, pingURL, http.NoBody) + if err != nil { + return err + } + rs, err := httpClt.Do(rq) + if err != nil { + return err + } + rs.Body.Close() + return nil + }) +} + +func getURL(ctx context.Context, u string) (*http.Response, error) { + rq, err := http.NewRequestWithContext(ctx, http.MethodGet, u, http.NoBody) + if err != nil { + return nil, err + } + return http.DefaultClient.Do(rq) +} + // Assert expected metric name and labels are present. func assertMetricPresent(t *testing.T, expected MetricInfo, mfs map[string]*promdto.MetricFamily) { mf, ok := mfs[expected.Name] @@ -211,6 +254,10 @@ func assertMetricPresent(t *testing.T, expected MetricInfo, mfs map[string]*prom assert.True(t, matchFlag, "Labels mismatch") } +func pingHandler(writer http.ResponseWriter, rq *http.Request) { + writer.WriteHeader(http.StatusOK) +} + func labelsToString(labels prometheus.Labels) string { keys := make([]string, 0, len(labels)) for key := range labels { diff --git a/go.mod b/go.mod index b460302..bad6e6b 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22 require ( github.com/mailgun/groupcache/v2 v2.5.0 + github.com/mailgun/holster/v4 v4.20.3 github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 github.com/prometheus/common v0.60.1 @@ -18,6 +19,7 @@ require ( github.com/klauspost/compress v1.17.11 // indirect github.com/kr/text v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/segmentio/fasthash v1.0.3 // indirect diff --git a/go.sum b/go.sum index cfeb3aa..00f89d6 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/ahmetb/go-linq v3.0.0+incompatible h1:qQkjjOXKrKOTy83X8OpRmnKflXKQIL/mC/gMVVDMhOA= +github.com/ahmetb/go-linq v3.0.0+incompatible/go.mod h1:PFffvbdbtw+QTB0WKRP0cNht7vnCfnGlEpak/DVg5cY= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -20,8 +22,12 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= +github.com/mailgun/holster/v4 v4.20.3 h1:FwHxBvuoWEqEpZGeNCLuk/oAHyNs3+ksGoCW0qbiHyo= +github.com/mailgun/holster/v4 v4.20.3/go.mod h1:HuFVoS8qOhceEBL4czXnVzp0bQrrIkLeX30IAll5hQ0= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= From ab82dceb7c7e79e2cb743a50818fc440b5ba6bf1 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Mon, 23 Dec 2024 09:13:11 -0500 Subject: [PATCH 31/44] Update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c49678..1b4e84a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This exporter extracts statistics from [groupcache](https://github.com/golang/gr # Example -Full example: [examples/groupcache-exporter-mailgun](examples/groupcache-exporter-mailgun) +Full example: [examples](examples) ## Exported Metrics From 15dd66425e371a9e6f6e3594bf0d0799c4d497fe Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Mon, 23 Dec 2024 09:19:40 -0500 Subject: [PATCH 32/44] Metric `groupcache_get_from_peers_latency_slowest` returns seconds instead of ms. --- exporter.go | 6 +++--- exporter_test.go | 2 -- statsadapter.go | 8 ++++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/exporter.go b/exporter.go index 65dacea..684658f 100644 --- a/exporter.go +++ b/exporter.go @@ -43,7 +43,7 @@ type GroupStatistics interface { CacheHits() int64 // GetFromPeersLatencyLower represents slowest duration to request value from peers - GetFromPeersLatencyLower() int64 + GetFromPeersLatencyLower() float64 // PeerLoads represents either remote load or remote cache hit (not an error) PeerLoads() int64 @@ -107,7 +107,7 @@ func NewExporter(namespace string, labels map[string]string, groups ...*groupcac labels, ), groupGetFromPeersLatencyLower: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "get_from_peers_latency_slowest_milliseconds"), + prometheus.BuildFQName(namespace, subsystem, "get_from_peers_latency_slowest"), "Represent slowest duration to request value from peers.", []string{"group"}, labels, @@ -228,7 +228,7 @@ func (e *Exporter) collectFromGroup(ch chan<- prometheus.Metric, stats GroupStat func (e *Exporter) collectStats(ch chan<- prometheus.Metric, stats GroupStatistics) { ch <- prometheus.MustNewConstMetric(e.groupGets, prometheus.CounterValue, float64(stats.Gets()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupCacheHits, prometheus.CounterValue, float64(stats.CacheHits()), stats.Name()) - ch <- prometheus.MustNewConstMetric(e.groupGetFromPeersLatencyLower, prometheus.GaugeValue, float64(stats.GetFromPeersLatencyLower()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupGetFromPeersLatencyLower, prometheus.GaugeValue, stats.GetFromPeersLatencyLower(), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupPeerLoads, prometheus.CounterValue, float64(stats.PeerLoads()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupPeerErrors, prometheus.CounterValue, float64(stats.PeerErrors()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupLoads, prometheus.CounterValue, float64(stats.Loads()), stats.Name()) diff --git a/exporter_test.go b/exporter_test.go index 92caea4..ef45944 100644 --- a/exporter_test.go +++ b/exporter_test.go @@ -167,8 +167,6 @@ func TestExporter(t *testing.T) { } t.Run("Lint", func(t *testing.T) { - // FIXME: Fix lint errors - t.Skip() linter := promlint.New(bytes.NewReader(content)) problems, err := linter.Lint() require.NoError(t, err) diff --git a/statsadapter.go b/statsadapter.go index c065f41..0d86619 100644 --- a/statsadapter.go +++ b/statsadapter.go @@ -30,8 +30,12 @@ func (g *statsAdapter) CacheHits() int64 { } // GetFromPeersLatencyLower represents slowest duration to request value from peers -func (g *statsAdapter) GetFromPeersLatencyLower() int64 { - return g.group.Stats.GetFromPeersLatencyLower.Get() +func (g *statsAdapter) GetFromPeersLatencyLower() float64 { + latencyMs := g.group.Stats.GetFromPeersLatencyLower.Get() + if latencyMs == 0 { + return 0 + } + return float64(latencyMs) / 1000 } // PeerLoads represents either remote load or remote cache hit (not an error) From acef83f01be6bd9d7702eb98441f76e43bfe85e5 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Mon, 23 Dec 2024 09:31:16 -0500 Subject: [PATCH 33/44] Update README.md. --- README.md | 44 ++++++++++++++++++++++---------------------- exporter_test.go | 3 +++ 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 1b4e84a..c3cff44 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Prometheus Groupcache Exporter -This exporter extracts statistics from [groupcache](https://github.com/golang/groupcache) instances and converts to Prometheus metrics. +This exporter extracts statistics from [Mailgun groupcache](https://github.com/golang/groupcache) instances and converts to Prometheus metrics. # Example @@ -10,25 +10,25 @@ Full example: [examples](examples) ## Exported Metrics -```bash -curl -s localhost:3000/metrics | grep -E ^groupcache -groupcache_cache_bytes{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 -groupcache_cache_bytes{app="groupcache-exporter-mailgun",group="files",type="main"} 2954 -groupcache_cache_evictions_total{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 -groupcache_cache_evictions_total{app="groupcache-exporter-mailgun",group="files",type="main"} 1 -groupcache_cache_gets_total{app="groupcache-exporter-mailgun",group="files",type="hot"} 4 -groupcache_cache_gets_total{app="groupcache-exporter-mailgun",group="files",type="main"} 16 -groupcache_cache_hits_total{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 -groupcache_cache_hits_total{app="groupcache-exporter-mailgun",group="files",type="main"} 12 -groupcache_cache_items{app="groupcache-exporter-mailgun",group="files",type="hot"} 0 -groupcache_cache_items{app="groupcache-exporter-mailgun",group="files",type="main"} 1 -groupcache_gets_total{app="groupcache-exporter-mailgun",group="files"} 14 -groupcache_hits_total{app="groupcache-exporter-mailgun",group="files"} 12 -groupcache_loads_deduped_total{app="groupcache-exporter-mailgun",group="files"} 2 -groupcache_loads_total{app="groupcache-exporter-mailgun",group="files"} 2 -groupcache_local_load_errs_total{app="groupcache-exporter-mailgun",group="files"} 0 -groupcache_local_load_total{app="groupcache-exporter-mailgun",group="files"} 2 -groupcache_peer_errors_total{app="groupcache-exporter-mailgun",group="files"} 0 -groupcache_peer_loads_total{app="groupcache-exporter-mailgun",group="files"} 0 -groupcache_server_requests_total{app="groupcache-exporter-mailgun",group="files"} 0 +``` +groupcache_cache_bytes{app="groupcache-exporter",group="files",type="hot"} 0 +groupcache_cache_bytes{app="groupcache-exporter",group="files",type="main"} 2954 +groupcache_cache_evictions_total{app="groupcache-exporter",group="files",type="hot"} 0 +groupcache_cache_evictions_total{app="groupcache-exporter",group="files",type="main"} 1 +groupcache_cache_gets_total{app="groupcache-exporter",group="files",type="hot"} 4 +groupcache_cache_gets_total{app="groupcache-exporter",group="files",type="main"} 16 +groupcache_cache_hits_total{app="groupcache-exporter",group="files",type="hot"} 0 +groupcache_cache_hits_total{app="groupcache-exporter",group="files",type="main"} 12 +groupcache_cache_items{app="groupcache-exporter",group="files",type="hot"} 0 +groupcache_cache_items{app="groupcache-exporter",group="files",type="main"} 1 +groupcache_gets_total{app="groupcache-exporter",group="files"} 14 +groupcache_hits_total{app="groupcache-exporter",group="files"} 12 +groupcache_get_from_peers_latency_slowest{app="groupcache-exporter",group="files"} 0.055 +groupcache_loads_deduped_total{app="groupcache-exporter",group="files"} 2 +groupcache_loads_total{app="groupcache-exporter",group="files"} 2 +groupcache_local_load_errs_total{app="groupcache-exporter",group="files"} 0 +groupcache_local_load_total{app="groupcache-exporter",group="files"} 2 +groupcache_peer_errors_total{app="groupcache-exporter",group="files"} 0 +groupcache_peer_loads_total{app="groupcache-exporter",group="files"} 0 +groupcache_server_requests_total{app="groupcache-exporter",group="files"} 0 ``` diff --git a/exporter_test.go b/exporter_test.go index ef45944..69f3288 100644 --- a/exporter_test.go +++ b/exporter_test.go @@ -133,6 +133,9 @@ func TestExporter(t *testing.T) { { Name: "groupcache_hits_total", }, + { + Name: "groupcache_get_from_peers_latency_slowest", + }, { Name: "groupcache_loads_deduped_total", }, From a0e3a65d0828369054bc3cd5afcbcb4e66d8e4f4 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Mon, 23 Dec 2024 14:41:55 -0500 Subject: [PATCH 34/44] Revise metric docs. --- README.md | 38 ++++++++++++++++---------------------- exporter.go | 24 ++++++++++++------------ exporter_test.go | 16 ++++++++++++---- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index c3cff44..8ad0534 100644 --- a/README.md +++ b/README.md @@ -10,25 +10,19 @@ Full example: [examples](examples) ## Exported Metrics -``` -groupcache_cache_bytes{app="groupcache-exporter",group="files",type="hot"} 0 -groupcache_cache_bytes{app="groupcache-exporter",group="files",type="main"} 2954 -groupcache_cache_evictions_total{app="groupcache-exporter",group="files",type="hot"} 0 -groupcache_cache_evictions_total{app="groupcache-exporter",group="files",type="main"} 1 -groupcache_cache_gets_total{app="groupcache-exporter",group="files",type="hot"} 4 -groupcache_cache_gets_total{app="groupcache-exporter",group="files",type="main"} 16 -groupcache_cache_hits_total{app="groupcache-exporter",group="files",type="hot"} 0 -groupcache_cache_hits_total{app="groupcache-exporter",group="files",type="main"} 12 -groupcache_cache_items{app="groupcache-exporter",group="files",type="hot"} 0 -groupcache_cache_items{app="groupcache-exporter",group="files",type="main"} 1 -groupcache_gets_total{app="groupcache-exporter",group="files"} 14 -groupcache_hits_total{app="groupcache-exporter",group="files"} 12 -groupcache_get_from_peers_latency_slowest{app="groupcache-exporter",group="files"} 0.055 -groupcache_loads_deduped_total{app="groupcache-exporter",group="files"} 2 -groupcache_loads_total{app="groupcache-exporter",group="files"} 2 -groupcache_local_load_errs_total{app="groupcache-exporter",group="files"} 0 -groupcache_local_load_total{app="groupcache-exporter",group="files"} 2 -groupcache_peer_errors_total{app="groupcache-exporter",group="files"} 0 -groupcache_peer_loads_total{app="groupcache-exporter",group="files"} 0 -groupcache_server_requests_total{app="groupcache-exporter",group="files"} 0 -``` +- `groupcache_cache_bytes{group,type="main|hot"}`: Gauge of current bytes in use +- `groupcache_cache_evictions_nonexpired_total{group,type="main|hot"}`: Count of cache evictions for non-expired keys due to memory full +- `groupcache_cache_evictions_total{group,type="main|hot"}`: Count of cache evictions +- `groupcache_cache_gets_total{group,type="main|hot"}`: Count of cache gets +- `groupcache_cache_hits_total{group,type="main|hot"}`: Count of cache hits +- `groupcache_cache_items{group,type="main|hot"}`: Gauge of current items in use +- `groupcache_get_from_peers_latency_lower{group}`: Represent slowest duration to request value from peers +- `groupcache_gets_total{group}`: Count of cache gets (including from peers, from either main or hot caches) +- `groupcache_hits_total{group}`: Count of cache hits (from either main or hot caches) +- `groupcache_loads_deduped_total{group}`: Count of loads after singleflight +- `groupcache_loads_total{group}`: Count of (gets - hits) +- `groupcache_local_load_errs_total{group}`: Count of load errors from local cache +- `groupcache_local_loads_total{group}`: Count of loads from local cache +- `groupcache_peer_errors_total{group}`: Count of errors from peers +- `groupcache_peer_loads_total{group}`: Count of loads or cache hits from peers +- `groupcache_server_requests_total{group}`: Count of gets received from peers diff --git a/exporter.go b/exporter.go index 684658f..57f089f 100644 --- a/exporter.go +++ b/exporter.go @@ -11,7 +11,7 @@ type Exporter struct { groups []GroupStatistics groupGets *prometheus.Desc - groupCacheHits *prometheus.Desc + groupHits *prometheus.Desc groupGetFromPeersLatencyLower *prometheus.Desc groupPeerLoads *prometheus.Desc groupPeerErrors *prometheus.Desc @@ -96,25 +96,25 @@ func NewExporter(namespace string, labels map[string]string, groups ...*groupcac groupGets: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "gets_total"), - "Count of cache gets (including from peers)", + "Count of cache gets (including from peers, from either main or hot cache)", []string{"group"}, labels, ), - groupCacheHits: prometheus.NewDesc( + groupHits: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "hits_total"), "Count of cache hits (from either main or hot cache)", []string{"group"}, labels, ), groupGetFromPeersLatencyLower: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "get_from_peers_latency_slowest"), - "Represent slowest duration to request value from peers.", + prometheus.BuildFQName(namespace, subsystem, "get_from_peers_latency_lower"), + "Represent slowest duration to request value from peers", []string{"group"}, labels, ), groupPeerLoads: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "peer_loads_total"), - "Count of non-error loads or cache hits from peers", + "Count of loads or cache hits from peers", []string{"group"}, labels, ), @@ -137,20 +137,20 @@ func NewExporter(namespace string, labels map[string]string, groups ...*groupcac labels, ), groupLocalLoads: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "local_load_total"), + prometheus.BuildFQName(namespace, subsystem, "local_loads_total"), "Count of loads from local cache", []string{"group"}, labels, ), groupLocalLoadErrs: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "local_load_errs_total"), - "Count of loads from local cache that failed", + "Count of load errors from local cache", []string{"group"}, labels, ), groupServerRequests: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "server_requests_total"), - "Count of gets that came over the network from peers", + "Count of gets received from peers", []string{"group"}, labels, ), @@ -186,7 +186,7 @@ func NewExporter(namespace string, labels map[string]string, groups ...*groupcac ), cacheEvictionsNonExpired: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "cache_evictions_nonexpired_total"), - "Count of cache evictions for non-expired keys due to memory full.", + "Count of cache evictions for non-expired keys due to memory full", []string{"group", "type"}, labels, ), @@ -196,7 +196,7 @@ func NewExporter(namespace string, labels map[string]string, groups ...*groupcac // Describe sends metrics descriptors. func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.groupGets - ch <- e.groupCacheHits + ch <- e.groupHits ch <- e.groupGetFromPeersLatencyLower ch <- e.groupPeerLoads ch <- e.groupPeerErrors @@ -227,7 +227,7 @@ func (e *Exporter) collectFromGroup(ch chan<- prometheus.Metric, stats GroupStat func (e *Exporter) collectStats(ch chan<- prometheus.Metric, stats GroupStatistics) { ch <- prometheus.MustNewConstMetric(e.groupGets, prometheus.CounterValue, float64(stats.Gets()), stats.Name()) - ch <- prometheus.MustNewConstMetric(e.groupCacheHits, prometheus.CounterValue, float64(stats.CacheHits()), stats.Name()) + ch <- prometheus.MustNewConstMetric(e.groupHits, prometheus.CounterValue, float64(stats.CacheHits()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupGetFromPeersLatencyLower, prometheus.GaugeValue, stats.GetFromPeersLatencyLower(), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupPeerLoads, prometheus.CounterValue, float64(stats.PeerLoads()), stats.Name()) ch <- prometheus.MustNewConstMetric(e.groupPeerErrors, prometheus.CounterValue, float64(stats.PeerErrors()), stats.Name()) diff --git a/exporter_test.go b/exporter_test.go index 69f3288..f81ab6e 100644 --- a/exporter_test.go +++ b/exporter_test.go @@ -95,6 +95,14 @@ func TestExporter(t *testing.T) { Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"type": "hot"}, }, + { + Name: "groupcache_cache_evictions_nonexpired_total", + Labels: prometheus.Labels{"type": "main"}, + }, + { + Name: "groupcache_cache_evictions_nonexpired_total", + Labels: prometheus.Labels{"type": "hot"}, + }, { Name: "groupcache_cache_evictions_total", Labels: prometheus.Labels{"type": "main"}, @@ -128,13 +136,13 @@ func TestExporter(t *testing.T) { Labels: prometheus.Labels{"type": "hot"}, }, { - Name: "groupcache_gets_total", + Name: "groupcache_get_from_peers_latency_lower", }, { - Name: "groupcache_hits_total", + Name: "groupcache_gets_total", }, { - Name: "groupcache_get_from_peers_latency_slowest", + Name: "groupcache_hits_total", }, { Name: "groupcache_loads_deduped_total", @@ -146,7 +154,7 @@ func TestExporter(t *testing.T) { Name: "groupcache_local_load_errs_total", }, { - Name: "groupcache_local_load_total", + Name: "groupcache_local_loads_total", }, { Name: "groupcache_peer_errors_total", From 52ef3df5471f6c783e9de5267b00f001563b4859 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Tue, 24 Dec 2024 09:48:32 -0500 Subject: [PATCH 35/44] Restructure module as a package to be merged into the groupcache module. --- .github/workflow/lint.yaml | 31 ---------- .gitignore | 15 ----- .golangci.yml | 50 --------------- Makefile | 9 --- go.mod | 30 --------- go.sum | 61 ------------------- LICENSE => promexporter/LICENSE | 0 README.md => promexporter/README.md | 8 ++- .../examples}/groupcache.go | 0 {examples => promexporter/examples}/main.go | 4 +- exporter.go => promexporter/exporter.go | 4 +- .../exporter_test.go | 6 +- .../statsadapter.go | 2 +- 13 files changed, 13 insertions(+), 207 deletions(-) delete mode 100644 .github/workflow/lint.yaml delete mode 100644 .gitignore delete mode 100644 .golangci.yml delete mode 100644 Makefile delete mode 100644 go.mod delete mode 100644 go.sum rename LICENSE => promexporter/LICENSE (100%) rename README.md => promexporter/README.md (79%) rename {examples => promexporter/examples}/groupcache.go (100%) rename {examples => promexporter/examples}/main.go (90%) rename exporter.go => promexporter/exporter.go (98%) rename exporter_test.go => promexporter/exporter_test.go (98%) rename statsadapter.go => promexporter/statsadapter.go (99%) diff --git a/.github/workflow/lint.yaml b/.github/workflow/lint.yaml deleted file mode 100644 index 41324c6..0000000 --- a/.github/workflow/lint.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: Lint - -on: - push: - branches: [ main ] - -env: - GOLANGCI_LINT_VERSION: v1.62.2 - -jobs: - lint: - name: lint - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version-file: ./go.mod - - - name: Check that 'go mod tidy' was called before commit - run: go mod tidy && git diff --exit-code - - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - version: ${{ env.GOLANGCI_LINT_VERSION }} - skip-cache: true # cache/restore is done by actions/setup-go step - args: -v diff --git a/.gitignore b/.gitignore deleted file mode 100644 index b66cec6..0000000 --- a/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# Created by .ignore support plugin (hsz.mobi) -### Go template -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 3662b21..0000000 --- a/.golangci.yml +++ /dev/null @@ -1,50 +0,0 @@ -linters: - # Please, do not use `enable-all`: it's deprecated and will be removed soon. - # Inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint. - # Full list of linters - https://golangci-lint.run/usage/linters - disable-all: true - enable: - - gomodguard - - errcheck - - gocritic - - goimports - - gosec - - gosimple - - govet - - noctx - - nolintlint - - ineffassign - - staticcheck - # - stylecheck - - typecheck - - unused - - gocyclo - -linters-settings: - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - - govet: - enable-all: true - disable: - - fieldalignment - -issues: - # Maximum issues count per one linter. Set to 0 to disable. Default is 50. - max-issues-per-linter: 0 - - # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. - max-same-issues: 50 - -run: - # include test files or not, default is true - tests: true - - # Timeout for analysis, e.g. 30s, 5m. - # Default: 1m - timeout: 5m diff --git a/Makefile b/Makefile deleted file mode 100644 index c0bb133..0000000 --- a/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -GOLANGCI_LINT = $(GOPATH)/bin/golangci-lint -GOLANGCI_LINT_VERSION = v1.62.2 - -$(GOLANGCI_LINT): - curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION) - -.PHONY: lint -lint: $(GOLANGCI_LINT) - $(GOLANGCI_LINT) run diff --git a/go.mod b/go.mod deleted file mode 100644 index bad6e6b..0000000 --- a/go.mod +++ /dev/null @@ -1,30 +0,0 @@ -module github.com/Baliedge/groupcache_exporter - -go 1.22 - -require ( - github.com/mailgun/groupcache/v2 v2.5.0 - github.com/mailgun/holster/v4 v4.20.3 - github.com/prometheus/client_golang v1.20.5 - github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.60.1 - github.com/stretchr/testify v1.9.0 -) - -require ( - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/klauspost/compress v1.17.11 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/segmentio/fasthash v1.0.3 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - golang.org/x/sys v0.27.0 // indirect - google.golang.org/protobuf v1.35.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 00f89d6..0000000 --- a/go.sum +++ /dev/null @@ -1,61 +0,0 @@ -github.com/ahmetb/go-linq v3.0.0+incompatible h1:qQkjjOXKrKOTy83X8OpRmnKflXKQIL/mC/gMVVDMhOA= -github.com/ahmetb/go-linq v3.0.0+incompatible/go.mod h1:PFffvbdbtw+QTB0WKRP0cNht7vnCfnGlEpak/DVg5cY= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= -github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= -github.com/mailgun/holster/v4 v4.20.3 h1:FwHxBvuoWEqEpZGeNCLuk/oAHyNs3+ksGoCW0qbiHyo= -github.com/mailgun/holster/v4 v4.20.3/go.mod h1:HuFVoS8qOhceEBL4czXnVzp0bQrrIkLeX30IAll5hQ0= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= -github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= -github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= -google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/LICENSE b/promexporter/LICENSE similarity index 100% rename from LICENSE rename to promexporter/LICENSE diff --git a/README.md b/promexporter/README.md similarity index 79% rename from README.md rename to promexporter/README.md index 8ad0534..931e083 100644 --- a/README.md +++ b/promexporter/README.md @@ -1,8 +1,6 @@ -[![license](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Baliedge/groupcache_exporter/blob/main/LICENSE) - # Prometheus Groupcache Exporter -This exporter extracts statistics from [Mailgun groupcache](https://github.com/golang/groupcache) instances and converts to Prometheus metrics. +This exporter extracts statistics from groupcache instances and exports Prometheus metrics. # Example @@ -26,3 +24,7 @@ Full example: [examples](examples) - `groupcache_peer_errors_total{group}`: Count of errors from peers - `groupcache_peer_loads_total{group}`: Count of loads or cache hits from peers - `groupcache_server_requests_total{group}`: Count of gets received from peers + +# Attribution + +This package source was copied from https://github.com/udhos/groupcache_exporter. See LICENSE for MIT license details impacting the contents of this package directory in addition to the LICENSE at the root of this repo for co-existing Apache license details. diff --git a/examples/groupcache.go b/promexporter/examples/groupcache.go similarity index 100% rename from examples/groupcache.go rename to promexporter/examples/groupcache.go diff --git a/examples/main.go b/promexporter/examples/main.go similarity index 90% rename from examples/main.go rename to promexporter/examples/main.go index ea3c08b..a245d16 100644 --- a/examples/main.go +++ b/promexporter/examples/main.go @@ -9,8 +9,8 @@ import ( "path/filepath" "time" - "github.com/Baliedge/groupcache_exporter" "github.com/mailgun/groupcache/v2" + "github.com/mailgun/groupcache/v2/promexporter" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) @@ -34,7 +34,7 @@ func main() { "app": appName, } namespace := "" - collector := groupcache_exporter.NewExporter(namespace, labels, cache) + collector := promexporter.NewExporter(namespace, labels, cache) prometheus.MustRegister(collector) diff --git a/exporter.go b/promexporter/exporter.go similarity index 98% rename from exporter.go rename to promexporter/exporter.go index 57f089f..9a5afcb 100644 --- a/exporter.go +++ b/promexporter/exporter.go @@ -1,5 +1,5 @@ -// Package groupcache_exporter exports prometheus metrics for groupcache. -package groupcache_exporter +// Package promexporter exports Prometheus metrics for groupcache. +package promexporter import ( "github.com/mailgun/groupcache/v2" diff --git a/exporter_test.go b/promexporter/exporter_test.go similarity index 98% rename from exporter_test.go rename to promexporter/exporter_test.go index f81ab6e..741f114 100644 --- a/exporter_test.go +++ b/promexporter/exporter_test.go @@ -1,4 +1,4 @@ -package groupcache_exporter_test +package promexporter_test import ( "bytes" @@ -12,8 +12,8 @@ import ( "testing" "time" - "github.com/Baliedge/groupcache_exporter" "github.com/mailgun/groupcache/v2" + "github.com/mailgun/groupcache/v2/promexporter" "github.com/mailgun/holster/v4/retry" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -48,7 +48,7 @@ func TestExporter(t *testing.T) { return nil } group := groupcache.NewGroup("test", 10_000, groupcache.GetterFunc(getter)) - gcexporter := groupcache_exporter.NewExporter("", nil, group) + gcexporter := promexporter.NewExporter("", nil, group) prometheus.MustRegister(gcexporter) // Setup HTTP server. diff --git a/statsadapter.go b/promexporter/statsadapter.go similarity index 99% rename from statsadapter.go rename to promexporter/statsadapter.go index 0d86619..2b0cacf 100644 --- a/statsadapter.go +++ b/promexporter/statsadapter.go @@ -1,4 +1,4 @@ -package groupcache_exporter +package promexporter import ( "github.com/mailgun/groupcache/v2" From c0b74302e5cbd61b320d6c358e777641fa9e9ef9 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Tue, 24 Dec 2024 13:29:36 -0500 Subject: [PATCH 36/44] Set Golang to 1.22 and update go.mod. --- example_test.go | 2 +- go.mod | 24 ++++++++++++----- go.sum | 68 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 63 insertions(+), 31 deletions(-) diff --git a/example_test.go b/example_test.go index 9fd306e..7af08c7 100644 --- a/example_test.go +++ b/example_test.go @@ -9,7 +9,7 @@ import ( "github.com/mailgun/groupcache/v2" ) -func ExampleUsage() { +func ExampleGroup() { /* // Keep track of peers in our cluster and add our instance to the pool `http://localhost:8080` pool := groupcache.NewHTTPPoolOpts("http://localhost:8080", &groupcache.HTTPPoolOptions{}) diff --git a/go.mod b/go.mod index 72812e3..a0da164 100644 --- a/go.mod +++ b/go.mod @@ -1,19 +1,29 @@ module github.com/mailgun/groupcache/v2 -go 1.19 +go 1.22 require ( - github.com/golang/protobuf v1.5.2 + github.com/golang/protobuf v1.5.4 + github.com/mailgun/holster/v4 v4.20.3 + github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.61.0 github.com/segmentio/fasthash v1.0.3 - github.com/sirupsen/logrus v1.9.0 - github.com/stretchr/testify v1.8.1 + github.com/sirupsen/logrus v1.9.2 + github.com/stretchr/testify v1.10.0 ) require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect - golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect - google.golang.org/protobuf v1.28.1 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + golang.org/x/sys v0.28.0 // indirect + google.golang.org/protobuf v1.35.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e1d0665..2d3aa30 100644 --- a/go.sum +++ b/go.sum @@ -1,37 +1,59 @@ +github.com/ahmetb/go-linq v3.0.0+incompatible h1:qQkjjOXKrKOTy83X8OpRmnKflXKQIL/mC/gMVVDMhOA= +github.com/ahmetb/go-linq v3.0.0+incompatible/go.mod h1:PFffvbdbtw+QTB0WKRP0cNht7vnCfnGlEpak/DVg5cY= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mailgun/holster/v4 v4.20.3 h1:FwHxBvuoWEqEpZGeNCLuk/oAHyNs3+ksGoCW0qbiHyo= +github.com/mailgun/holster/v4 v4.20.3/go.mod h1:HuFVoS8qOhceEBL4czXnVzp0bQrrIkLeX30IAll5hQ0= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= +github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= +github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc= -golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 78b42e7d89cac92fb0082e0327d00dcc7f578dd3 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Tue, 24 Dec 2024 13:38:06 -0500 Subject: [PATCH 37/44] Tidy code. --- promexporter/exporter_test.go | 104 ++++++++-------------------------- 1 file changed, 24 insertions(+), 80 deletions(-) diff --git a/promexporter/exporter_test.go b/promexporter/exporter_test.go index 741f114..e134b1c 100644 --- a/promexporter/exporter_test.go +++ b/promexporter/exporter_test.go @@ -87,84 +87,28 @@ func TestExporter(t *testing.T) { Name string Labels prometheus.Labels }{ - { - Name: "groupcache_cache_bytes", - Labels: prometheus.Labels{"type": "main"}, - }, - { - Name: "groupcache_cache_bytes", - Labels: prometheus.Labels{"type": "hot"}, - }, - { - Name: "groupcache_cache_evictions_nonexpired_total", - Labels: prometheus.Labels{"type": "main"}, - }, - { - Name: "groupcache_cache_evictions_nonexpired_total", - Labels: prometheus.Labels{"type": "hot"}, - }, - { - Name: "groupcache_cache_evictions_total", - Labels: prometheus.Labels{"type": "main"}, - }, - { - Name: "groupcache_cache_evictions_total", - Labels: prometheus.Labels{"type": "hot"}, - }, - { - Name: "groupcache_cache_gets_total", - Labels: prometheus.Labels{"type": "main"}, - }, - { - Name: "groupcache_cache_gets_total", - Labels: prometheus.Labels{"type": "hot"}, - }, - { - Name: "groupcache_cache_hits_total", - Labels: prometheus.Labels{"type": "main"}, - }, - { - Name: "groupcache_cache_hits_total", - Labels: prometheus.Labels{"type": "hot"}, - }, - { - Name: "groupcache_cache_items", - Labels: prometheus.Labels{"type": "main"}, - }, - { - Name: "groupcache_cache_items", - Labels: prometheus.Labels{"type": "hot"}, - }, - { - Name: "groupcache_get_from_peers_latency_lower", - }, - { - Name: "groupcache_gets_total", - }, - { - Name: "groupcache_hits_total", - }, - { - Name: "groupcache_loads_deduped_total", - }, - { - Name: "groupcache_loads_total", - }, - { - Name: "groupcache_local_load_errs_total", - }, - { - Name: "groupcache_local_loads_total", - }, - { - Name: "groupcache_peer_errors_total", - }, - { - Name: "groupcache_peer_loads_total", - }, - { - Name: "groupcache_server_requests_total", - }, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"type": "main"}}, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"type": "hot"}}, + {Name: "groupcache_cache_evictions_nonexpired_total", Labels: prometheus.Labels{"type": "main"}}, + {Name: "groupcache_cache_evictions_nonexpired_total", Labels: prometheus.Labels{"type": "hot"}}, + {Name: "groupcache_cache_evictions_total", Labels: prometheus.Labels{"type": "main"}}, + {Name: "groupcache_cache_evictions_total", Labels: prometheus.Labels{"type": "hot"}}, + {Name: "groupcache_cache_gets_total", Labels: prometheus.Labels{"type": "main"}}, + {Name: "groupcache_cache_gets_total", Labels: prometheus.Labels{"type": "hot"}}, + {Name: "groupcache_cache_hits_total", Labels: prometheus.Labels{"type": "main"}}, + {Name: "groupcache_cache_hits_total", Labels: prometheus.Labels{"type": "hot"}}, + {Name: "groupcache_cache_items", Labels: prometheus.Labels{"type": "main"}}, + {Name: "groupcache_cache_items", Labels: prometheus.Labels{"type": "hot"}}, + {Name: "groupcache_get_from_peers_latency_lower"}, + {Name: "groupcache_gets_total"}, + {Name: "groupcache_hits_total"}, + {Name: "groupcache_loads_deduped_total"}, + {Name: "groupcache_loads_total"}, + {Name: "groupcache_local_load_errs_total"}, + {Name: "groupcache_local_loads_total"}, + {Name: "groupcache_peer_errors_total"}, + {Name: "groupcache_peer_loads_total"}, + {Name: "groupcache_server_requests_total"}, } tp := new(expfmt.TextParser) mfs, err := tp.TextToMetricFamilies(bytes.NewReader(content)) @@ -173,7 +117,7 @@ func TestExporter(t *testing.T) { for _, expectedMetric := range expectedMetrics { testName := fmt.Sprintf("Metric %s{%s}", expectedMetric.Name, labelsToString(expectedMetric.Labels)) t.Run(testName, func(t *testing.T) { - assertMetricPresent(t, expectedMetric, mfs) + assertContainsMetric(t, expectedMetric, mfs) }) } @@ -235,7 +179,7 @@ func getURL(ctx context.Context, u string) (*http.Response, error) { } // Assert expected metric name and labels are present. -func assertMetricPresent(t *testing.T, expected MetricInfo, mfs map[string]*promdto.MetricFamily) { +func assertContainsMetric(t *testing.T, expected MetricInfo, mfs map[string]*promdto.MetricFamily) { mf, ok := mfs[expected.Name] if !assert.True(t, ok, "Metric not found") { return From c219d7c0f4db01f88188fc2252c7a6fdfd69c663 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Tue, 24 Dec 2024 13:39:11 -0500 Subject: [PATCH 38/44] Update GHA test Golang targets. --- .github/workflows/on-pull-request.yaml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/on-pull-request.yaml b/.github/workflows/on-pull-request.yaml index 756c893..44f2e58 100644 --- a/.github/workflows/on-pull-request.yaml +++ b/.github/workflows/on-pull-request.yaml @@ -2,13 +2,9 @@ name: CI on: push: - branches: - - master - - main + branches: [ master, main ] pull_request: - branches: - - master - - main + branches: [ master, main ] jobs: on-pull-request: @@ -16,23 +12,23 @@ jobs: strategy: matrix: go-version: - - 1.18.x - - 1.19.x + - 1.22.x + - 1.23.x os: [ ubuntu-latest ] runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@v4 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - run: go env - name: Cache deps - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -43,4 +39,4 @@ jobs: run: go mod download - name: Test - run: go test ./... \ No newline at end of file + run: go test ./... From ea6b598b94e610550d06df66cfe5b3a9c066e088 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Tue, 24 Dec 2024 13:55:04 -0500 Subject: [PATCH 39/44] Simplify example in README. --- promexporter/README.md | 13 +++++- promexporter/examples/groupcache.go | 69 ----------------------------- promexporter/examples/main.go | 60 ------------------------- 3 files changed, 12 insertions(+), 130 deletions(-) delete mode 100644 promexporter/examples/groupcache.go delete mode 100644 promexporter/examples/main.go diff --git a/promexporter/README.md b/promexporter/README.md index 931e083..eee5e64 100644 --- a/promexporter/README.md +++ b/promexporter/README.md @@ -4,7 +4,18 @@ This exporter extracts statistics from groupcache instances and exports Promethe # Example -Full example: [examples](examples) +```go +import ( + "github.com/mailgun/groupcache/v2" + "github.com/mailgun/groupcache/v2/promexporter" +) + +// ... + +group := groupcache.NewGroup("mygroup", cacheSize, getter) +collector := promexporter.NewExporter("", nil, group) +prometheus.MustRegister(collector) +``` ## Exported Metrics diff --git a/promexporter/examples/groupcache.go b/promexporter/examples/groupcache.go deleted file mode 100644 index 2ff5dd6..0000000 --- a/promexporter/examples/groupcache.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - "context" - "log" - "net/http" - "os" - "time" - - "github.com/mailgun/groupcache/v2" -) - -func startGroupcache() *groupcache.Group { - - ttl := time.Minute - - log.Printf("groupcache ttl: %v", ttl) - - // - // create groupcache pool - // - - groupcachePort := ":5000" - - myURL := "http://127.0.0.1" + groupcachePort - - log.Printf("groupcache my URL: %s", myURL) - - pool := groupcache.NewHTTPPoolOpts(myURL, &groupcache.HTTPPoolOptions{}) - - // - // start groupcache server - // - - serverGroupCache := &http.Server{Addr: groupcachePort, Handler: pool} - - go func() { - log.Printf("groupcache server: listening on %s", groupcachePort) - err := serverGroupCache.ListenAndServe() - log.Printf("groupcache server: exited: %v", err) - }() - - pool.Set(myURL) - - // - // create cache - // - - var groupcacheSizeBytes int64 = 1_000_000 - - // https://talks.golang.org/2013/oscon-dl.slide#46 - // - // 64 MB max per-node memory usage - cache := groupcache.NewGroup("files", groupcacheSizeBytes, groupcache.GetterFunc( - func(_ context.Context, key string, dest groupcache.Sink) error { - - log.Printf("getter: loading: key:%s, ttl:%v", key, ttl) - - data, errFile := os.ReadFile(key) - if errFile != nil { - return errFile - } - - expire := time.Now().Add(ttl) - return dest.SetBytes(data, expire) - })) - - return cache -} diff --git a/promexporter/examples/main.go b/promexporter/examples/main.go deleted file mode 100644 index a245d16..0000000 --- a/promexporter/examples/main.go +++ /dev/null @@ -1,60 +0,0 @@ -// Package main implements the example. -package main - -import ( - "context" - "log" - "net/http" - "os" - "path/filepath" - "time" - - "github.com/mailgun/groupcache/v2" - "github.com/mailgun/groupcache/v2/promexporter" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -func main() { - - appName := filepath.Base(os.Args[0]) - - cache := startGroupcache() - - // - // expose prometheus metrics - // - { - metricsRoute := "/metrics" - metricsPort := ":3000" - - log.Printf("starting metrics server at: %s %s", metricsPort, metricsRoute) - - labels := map[string]string{ - "app": appName, - } - namespace := "" - collector := promexporter.NewExporter(namespace, labels, cache) - - prometheus.MustRegister(collector) - - go func() { - http.Handle(metricsRoute, promhttp.Handler()) - log.Fatal(http.ListenAndServe(metricsPort, nil)) - }() - } - - // - // query cache periodically - // - - const interval = 5 * time.Second - - for { - var dst []byte - cache.Get(context.TODO(), "/etc/passwd", groupcache.AllocatingByteSliceSink(&dst)) - log.Printf("cache answer: %d bytes, sleeping %v", len(dst), interval) - time.Sleep(interval) - } - -} From dfb46aea5f08de6a795582feffe7df8f5370af8e Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Tue, 24 Dec 2024 15:03:34 -0500 Subject: [PATCH 40/44] Support groups created after calling `GetMetrics()`. --- groupcache.go | 14 +++++++++++++- promexporter/README.md | 6 ++++-- promexporter/exporter.go | 22 +++++++++++----------- promexporter/exporter_test.go | 2 +- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/groupcache.go b/groupcache.go index 541e89a..787f1dc 100644 --- a/groupcache.go +++ b/groupcache.go @@ -76,7 +76,7 @@ var ( initPeerServer func() ) -// GetGroup returns the named group previously created with NewGroup, or +// GetGroup returns the named group previously created with NewGroup or // nil if there's no such group. func GetGroup(name string) *Group { mu.RLock() @@ -85,6 +85,18 @@ func GetGroup(name string) *Group { return g } +// GetGroups returns all groups previously created with NewGroup or nil if no +// groups. +func GetGroups() []*Group { + list := make([]*Group, 0, len(groups)) + mu.RLock() + for _, group := range groups { + list = append(list, group) + } + mu.RUnlock() + return list +} + // NewGroup creates a coordinated group-aware Getter from a Getter. // // The returned Getter tries (but does not guarantee) to run only one diff --git a/promexporter/README.md b/promexporter/README.md index eee5e64..277f033 100644 --- a/promexporter/README.md +++ b/promexporter/README.md @@ -12,9 +12,11 @@ import ( // ... -group := groupcache.NewGroup("mygroup", cacheSize, getter) -collector := promexporter.NewExporter("", nil, group) +collector := promexporter.NewExporter("", nil) prometheus.MustRegister(collector) + +// Collector will discover newly created group. +group := groupcache.NewGroup("mygroup", cacheSize, getter) ``` ## Exported Metrics diff --git a/promexporter/exporter.go b/promexporter/exporter.go index 9a5afcb..82e3f56 100644 --- a/promexporter/exporter.go +++ b/promexporter/exporter.go @@ -8,8 +8,6 @@ import ( // Exporter implements interface prometheus.Collector to extract metrics from groupcache. type Exporter struct { - groups []GroupStatistics - groupGets *prometheus.Desc groupHits *prometheus.Desc groupGetFromPeersLatencyLower *prometheus.Desc @@ -83,17 +81,10 @@ type GroupStatistics interface { // NewExporter creates Exporter. // namespace is usually the empty string. -func NewExporter(namespace string, labels map[string]string, groups ...*groupcache.Group) *Exporter { +func NewExporter(namespace string, labels map[string]string) *Exporter { const subsystem = "groupcache" - statgroups := make([]GroupStatistics, 0, len(groups)) - for _, g := range groups { - statgroups = append(statgroups, newStatsAdapter(g)) - } - return &Exporter{ - groups: statgroups, - groupGets: prometheus.NewDesc( prometheus.BuildFQName(namespace, subsystem, "gets_total"), "Count of cache gets (including from peers, from either main or hot cache)", @@ -193,6 +184,15 @@ func NewExporter(namespace string, labels map[string]string, groups ...*groupcac } } +func (e *Exporter) getStatGroups() []GroupStatistics { + groups := groupcache.GetGroups() + statgroups := make([]GroupStatistics, 0, len(groups)) + for _, g := range groups { + statgroups = append(statgroups, newStatsAdapter(g)) + } + return statgroups +} + // Describe sends metrics descriptors. func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.groupGets @@ -215,7 +215,7 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { // Collect is called by the Prometheus registry when collecting metrics. func (e *Exporter) Collect(ch chan<- prometheus.Metric) { - for _, group := range e.groups { + for _, group := range e.getStatGroups() { e.collectFromGroup(ch, group) } } diff --git a/promexporter/exporter_test.go b/promexporter/exporter_test.go index e134b1c..4ba38c0 100644 --- a/promexporter/exporter_test.go +++ b/promexporter/exporter_test.go @@ -48,7 +48,7 @@ func TestExporter(t *testing.T) { return nil } group := groupcache.NewGroup("test", 10_000, groupcache.GetterFunc(getter)) - gcexporter := promexporter.NewExporter("", nil, group) + gcexporter := promexporter.NewExporter("", nil) prometheus.MustRegister(gcexporter) // Setup HTTP server. From d5733229090010ea50a51ab81250c1febd97066e Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Tue, 24 Dec 2024 17:22:00 -0500 Subject: [PATCH 41/44] Change `NewExporter()` to option variadic arguments. --- promexporter/exporter.go | 229 +++++++++++++++++++--------------- promexporter/exporter_test.go | 2 +- 2 files changed, 132 insertions(+), 99 deletions(-) diff --git a/promexporter/exporter.go b/promexporter/exporter.go index 82e3f56..e1e7454 100644 --- a/promexporter/exporter.go +++ b/promexporter/exporter.go @@ -8,6 +8,8 @@ import ( // Exporter implements interface prometheus.Collector to extract metrics from groupcache. type Exporter struct { + namespace string + labels map[string]string groupGets *prometheus.Desc groupHits *prometheus.Desc groupGetFromPeersLatencyLower *prometheus.Desc @@ -79,109 +81,124 @@ type GroupStatistics interface { HotCacheEvictionsNonExpired() int64 } +type Option interface { + apply(*Exporter) +} + +type namespaceOption struct { + namespace string +} + +type labelsOption struct { + labels map[string]string +} + // NewExporter creates Exporter. // namespace is usually the empty string. -func NewExporter(namespace string, labels map[string]string) *Exporter { +func NewExporter(opts ...Option) *Exporter { const subsystem = "groupcache" - return &Exporter{ - groupGets: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "gets_total"), - "Count of cache gets (including from peers, from either main or hot cache)", - []string{"group"}, - labels, - ), - groupHits: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "hits_total"), - "Count of cache hits (from either main or hot cache)", - []string{"group"}, - labels, - ), - groupGetFromPeersLatencyLower: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "get_from_peers_latency_lower"), - "Represent slowest duration to request value from peers", - []string{"group"}, - labels, - ), - groupPeerLoads: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "peer_loads_total"), - "Count of loads or cache hits from peers", - []string{"group"}, - labels, - ), - groupPeerErrors: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "peer_errors_total"), - "Count of errors from peers", - []string{"group"}, - labels, - ), - groupLoads: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "loads_total"), - "Count of (gets - hits)", - []string{"group"}, - labels, - ), - groupLoadsDeduped: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "loads_deduped_total"), - "Count of loads after singleflight", - []string{"group"}, - labels, - ), - groupLocalLoads: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "local_loads_total"), - "Count of loads from local cache", - []string{"group"}, - labels, - ), - groupLocalLoadErrs: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "local_load_errs_total"), - "Count of load errors from local cache", - []string{"group"}, - labels, - ), - groupServerRequests: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "server_requests_total"), - "Count of gets received from peers", - []string{"group"}, - labels, - ), - cacheBytes: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_bytes"), - "Gauge of current bytes in use", - []string{"group", "type"}, - labels, - ), - cacheItems: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_items"), - "Gauge of current items in use", - []string{"group", "type"}, - labels, - ), - cacheGets: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_gets_total"), - "Count of cache gets", - []string{"group", "type"}, - labels, - ), - cacheHits: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_hits_total"), - "Count of cache hits", - []string{"group", "type"}, - labels, - ), - cacheEvictions: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_evictions_total"), - "Count of cache evictions", - []string{"group", "type"}, - labels, - ), - cacheEvictionsNonExpired: prometheus.NewDesc( - prometheus.BuildFQName(namespace, subsystem, "cache_evictions_nonexpired_total"), - "Count of cache evictions for non-expired keys due to memory full", - []string{"group", "type"}, - labels, - ), + e := new(Exporter) + for _, opt := range opts { + opt.apply(e) } + e.groupGets = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "gets_total"), + "Count of cache gets (including from peers, from either main or hot cache)", + []string{"group"}, + e.labels, + ) + e.groupHits = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "hits_total"), + "Count of cache hits (from either main or hot cache)", + []string{"group"}, + e.labels, + ) + e.groupGetFromPeersLatencyLower = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "get_from_peers_latency_lower"), + "Represent slowest duration to request value from peers", + []string{"group"}, + e.labels, + ) + e.groupPeerLoads = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "peer_loads_total"), + "Count of loads or cache hits from peers", + []string{"group"}, + e.labels, + ) + e.groupPeerErrors = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "peer_errors_total"), + "Count of errors from peers", + []string{"group"}, + e.labels, + ) + e.groupLoads = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "loads_total"), + "Count of (gets - hits)", + []string{"group"}, + e.labels, + ) + e.groupLoadsDeduped = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "loads_deduped_total"), + "Count of loads after singleflight", + []string{"group"}, + e.labels, + ) + e.groupLocalLoads = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "local_loads_total"), + "Count of loads from local cache", + []string{"group"}, + e.labels, + ) + e.groupLocalLoadErrs = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "local_load_errs_total"), + "Count of load errors from local cache", + []string{"group"}, + e.labels, + ) + e.groupServerRequests = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "server_requests_total"), + "Count of gets received from peers", + []string{"group"}, + e.labels, + ) + e.cacheBytes = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "cache_bytes"), + "Gauge of current bytes in use", + []string{"group", "type"}, + e.labels, + ) + e.cacheItems = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "cache_items"), + "Gauge of current items in use", + []string{"group", "type"}, + e.labels, + ) + e.cacheGets = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "cache_gets_total"), + "Count of cache gets", + []string{"group", "type"}, + e.labels, + ) + e.cacheHits = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "cache_hits_total"), + "Count of cache hits", + []string{"group", "type"}, + e.labels, + ) + e.cacheEvictions = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "cache_evictions_total"), + "Count of cache evictions", + []string{"group", "type"}, + e.labels, + ) + e.cacheEvictionsNonExpired = prometheus.NewDesc( + prometheus.BuildFQName(e.namespace, subsystem, "cache_evictions_nonexpired_total"), + "Count of cache evictions for non-expired keys due to memory full", + []string{"group", "type"}, + e.labels, + ) + return e } func (e *Exporter) getStatGroups() []GroupStatistics { @@ -253,3 +270,19 @@ func (e *Exporter) collectCacheStats(ch chan<- prometheus.Metric, stats GroupSta ch <- prometheus.MustNewConstMetric(e.cacheEvictions, prometheus.CounterValue, float64(stats.HotCacheEvictions()), stats.Name(), "hot") ch <- prometheus.MustNewConstMetric(e.cacheEvictionsNonExpired, prometheus.CounterValue, float64(stats.HotCacheEvictionsNonExpired()), stats.Name(), "hot") } + +func WithNamspace(namespace string) Option { + return &namespaceOption{namespace: namespace} +} + +func (o *namespaceOption) apply(e *Exporter) { + e.namespace = o.namespace +} + +func WithLabels(labels map[string]string) Option { + return &labelsOption{labels: labels} +} + +func (o *labelsOption) apply(e *Exporter) { + e.labels = o.labels +} diff --git a/promexporter/exporter_test.go b/promexporter/exporter_test.go index 4ba38c0..1d0d8b1 100644 --- a/promexporter/exporter_test.go +++ b/promexporter/exporter_test.go @@ -48,7 +48,7 @@ func TestExporter(t *testing.T) { return nil } group := groupcache.NewGroup("test", 10_000, groupcache.GetterFunc(getter)) - gcexporter := promexporter.NewExporter("", nil) + gcexporter := promexporter.NewExporter() prometheus.MustRegister(gcexporter) // Setup HTTP server. From 87d28c043320db1dc57cfec0228cd755fba481c3 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Thu, 26 Dec 2024 10:48:11 -0500 Subject: [PATCH 42/44] Tests. --- promexporter/exporter.go | 24 ++- promexporter/exporter_test.go | 325 ++++++++++++++++++++++++++-------- 2 files changed, 271 insertions(+), 78 deletions(-) diff --git a/promexporter/exporter.go b/promexporter/exporter.go index e1e7454..d6e25e9 100644 --- a/promexporter/exporter.go +++ b/promexporter/exporter.go @@ -10,6 +10,7 @@ import ( type Exporter struct { namespace string labels map[string]string + getGroups func() []*groupcache.Group groupGets *prometheus.Desc groupHits *prometheus.Desc groupGetFromPeersLatencyLower *prometheus.Desc @@ -93,12 +94,18 @@ type labelsOption struct { labels map[string]string } +type groupsOption struct { + groupsFn func() []*groupcache.Group +} + // NewExporter creates Exporter. // namespace is usually the empty string. func NewExporter(opts ...Option) *Exporter { const subsystem = "groupcache" - e := new(Exporter) + e := &Exporter{ + getGroups: groupcache.GetGroups, + } for _, opt := range opts { opt.apply(e) } @@ -202,7 +209,7 @@ func NewExporter(opts ...Option) *Exporter { } func (e *Exporter) getStatGroups() []GroupStatistics { - groups := groupcache.GetGroups() + groups := e.getGroups() statgroups := make([]GroupStatistics, 0, len(groups)) for _, g := range groups { statgroups = append(statgroups, newStatsAdapter(g)) @@ -271,7 +278,8 @@ func (e *Exporter) collectCacheStats(ch chan<- prometheus.Metric, stats GroupSta ch <- prometheus.MustNewConstMetric(e.cacheEvictionsNonExpired, prometheus.CounterValue, float64(stats.HotCacheEvictionsNonExpired()), stats.Name(), "hot") } -func WithNamspace(namespace string) Option { +// Set namespace of exported metrics. Namespace serves as the prefix to metric names, like: `_groupcache_cache_bytes`. +func WithNamespace(namespace string) Option { return &namespaceOption{namespace: namespace} } @@ -279,6 +287,7 @@ func (o *namespaceOption) apply(e *Exporter) { e.namespace = o.namespace } +// Set labels added to exported metrics. func WithLabels(labels map[string]string) Option { return &labelsOption{labels: labels} } @@ -286,3 +295,12 @@ func WithLabels(labels map[string]string) Option { func (o *labelsOption) apply(e *Exporter) { e.labels = o.labels } + +// Set function used to get groups to export. Called on every scrape. +func WithGroups(groupsFn func() []*groupcache.Group) Option { + return &groupsOption{groupsFn: groupsFn} +} + +func (o *groupsOption) apply(e *Exporter) { + e.getGroups = o.groupsFn +} diff --git a/promexporter/exporter_test.go b/promexporter/exporter_test.go index 1d0d8b1..8ed86a7 100644 --- a/promexporter/exporter_test.go +++ b/promexporter/exporter_test.go @@ -42,22 +42,15 @@ func TestExporter(t *testing.T) { defer cancel() // Setup groupcache. - getter := func(_ context.Context, key string, dest groupcache.Sink) error { - err := dest.SetString("foobar", time.Now().Add(ttl)) - require.NoError(t, err) - return nil - } - group := groupcache.NewGroup("test", 10_000, groupcache.GetterFunc(getter)) + group := newGroup(t, t.Name()) + defer groupcache.DeregisterGroup(group.Name()) gcexporter := promexporter.NewExporter() - prometheus.MustRegister(gcexporter) + registry := prometheus.NewRegistry() + registry.MustRegister(gcexporter) - // Setup HTTP server. - mux := http.NewServeMux() - mux.HandleFunc(pingRoute, pingHandler) - mux.Handle(metricsRoute, promhttp.Handler()) - httpSrv, err := startHTTPServer(ctx, mux, &wg) + // Setup metrics HTTP server. + httpSrv, err := startMetricsServer(ctx, t, registry, &wg) require.NoError(t, err) - t.Logf("HTTP server ready at %s", httpSrv.Addr) defer func() { // Tear down. t.Log("HTTP server shutting down...") @@ -67,62 +60,46 @@ func TestExporter(t *testing.T) { }() // When - // Add cache activity. - for i := 0; i < 10; i++ { - var value string - err = group.Get(ctx, fmt.Sprintf("key%d", i), groupcache.StringSink(&value)) - require.NoError(t, err) - } - - // Then - // Get metrics from endpoint. - rs, err := getURL(ctx, fmt.Sprintf("http://%s%s", httpSrv.Addr, metricsRoute)) - require.NoError(t, err) - content, err := io.ReadAll(rs.Body) - defer rs.Body.Close() + metricsContent, err := getMetrics(ctx, httpSrv) require.NoError(t, err) + // Then // Parse metrics and assert expected values are found. - expectedMetrics := []struct { - Name string - Labels prometheus.Labels - }{ - {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"type": "main"}}, - {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"type": "hot"}}, - {Name: "groupcache_cache_evictions_nonexpired_total", Labels: prometheus.Labels{"type": "main"}}, - {Name: "groupcache_cache_evictions_nonexpired_total", Labels: prometheus.Labels{"type": "hot"}}, - {Name: "groupcache_cache_evictions_total", Labels: prometheus.Labels{"type": "main"}}, - {Name: "groupcache_cache_evictions_total", Labels: prometheus.Labels{"type": "hot"}}, - {Name: "groupcache_cache_gets_total", Labels: prometheus.Labels{"type": "main"}}, - {Name: "groupcache_cache_gets_total", Labels: prometheus.Labels{"type": "hot"}}, - {Name: "groupcache_cache_hits_total", Labels: prometheus.Labels{"type": "main"}}, - {Name: "groupcache_cache_hits_total", Labels: prometheus.Labels{"type": "hot"}}, - {Name: "groupcache_cache_items", Labels: prometheus.Labels{"type": "main"}}, - {Name: "groupcache_cache_items", Labels: prometheus.Labels{"type": "hot"}}, - {Name: "groupcache_get_from_peers_latency_lower"}, - {Name: "groupcache_gets_total"}, - {Name: "groupcache_hits_total"}, - {Name: "groupcache_loads_deduped_total"}, - {Name: "groupcache_loads_total"}, - {Name: "groupcache_local_load_errs_total"}, - {Name: "groupcache_local_loads_total"}, - {Name: "groupcache_peer_errors_total"}, - {Name: "groupcache_peer_loads_total"}, - {Name: "groupcache_server_requests_total"}, - } - tp := new(expfmt.TextParser) - mfs, err := tp.TextToMetricFamilies(bytes.NewReader(content)) + mfs, err := parseMetricsContent(metricsContent) require.NoError(t, err) - + expectedMetrics := []MetricInfo{ + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group.Name(), "type": "main"}}, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group.Name(), "type": "hot"}}, + {Name: "groupcache_cache_evictions_nonexpired_total", Labels: prometheus.Labels{"group": group.Name(), "type": "main"}}, + {Name: "groupcache_cache_evictions_nonexpired_total", Labels: prometheus.Labels{"group": group.Name(), "type": "hot"}}, + {Name: "groupcache_cache_evictions_total", Labels: prometheus.Labels{"group": group.Name(), "type": "main"}}, + {Name: "groupcache_cache_evictions_total", Labels: prometheus.Labels{"group": group.Name(), "type": "hot"}}, + {Name: "groupcache_cache_gets_total", Labels: prometheus.Labels{"group": group.Name(), "type": "main"}}, + {Name: "groupcache_cache_gets_total", Labels: prometheus.Labels{"group": group.Name(), "type": "hot"}}, + {Name: "groupcache_cache_hits_total", Labels: prometheus.Labels{"group": group.Name(), "type": "main"}}, + {Name: "groupcache_cache_hits_total", Labels: prometheus.Labels{"group": group.Name(), "type": "hot"}}, + {Name: "groupcache_cache_items", Labels: prometheus.Labels{"group": group.Name(), "type": "main"}}, + {Name: "groupcache_cache_items", Labels: prometheus.Labels{"group": group.Name(), "type": "hot"}}, + {Name: "groupcache_get_from_peers_latency_lower", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_gets_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_hits_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_loads_deduped_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_loads_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_local_load_errs_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_local_loads_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_peer_errors_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_peer_loads_total", Labels: prometheus.Labels{"group": group.Name()}}, + {Name: "groupcache_server_requests_total", Labels: prometheus.Labels{"group": group.Name()}}, + } for _, expectedMetric := range expectedMetrics { - testName := fmt.Sprintf("Metric %s{%s}", expectedMetric.Name, labelsToString(expectedMetric.Labels)) + testName := fmt.Sprintf("Metric exported %s{%s}", expectedMetric.Name, labelsToString(expectedMetric.Labels)) t.Run(testName, func(t *testing.T) { assertContainsMetric(t, expectedMetric, mfs) }) } t.Run("Lint", func(t *testing.T) { - linter := promlint.New(bytes.NewReader(content)) + linter := promlint.New(bytes.NewReader(metricsContent)) problems, err := linter.Lint() require.NoError(t, err) for _, problem := range problems { @@ -131,8 +108,174 @@ func TestExporter(t *testing.T) { }) } +func TestExporterWithNamespace(t *testing.T) { + // Given + var wg sync.WaitGroup + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + // Setup groupcache. + group := newGroup(t, t.Name()) + defer groupcache.DeregisterGroup(group.Name()) + gcexporter := promexporter.NewExporter(promexporter.WithNamespace("mynamespace")) + registry := prometheus.NewRegistry() + registry.MustRegister(gcexporter) + + // Setup metrics HTTP server. + httpSrv, err := startMetricsServer(ctx, t, registry, &wg) + require.NoError(t, err) + defer func() { + // Tear down. + t.Log("HTTP server shutting down...") + err = httpSrv.Shutdown(ctx) + require.NoError(t, err) + wg.Wait() + }() + + // When + metricsContent, err := getMetrics(ctx, httpSrv) + require.NoError(t, err) + + // Then + // Parse metrics and assert expected values are found. + mfs, err := parseMetricsContent(metricsContent) + require.NoError(t, err) + expectedMetrics := []MetricInfo{ + {Name: "mynamespace_groupcache_cache_bytes", Labels: prometheus.Labels{"group": group.Name(), "type": "main"}}, + {Name: "mynamespace_groupcache_cache_bytes", Labels: prometheus.Labels{"group": group.Name(), "type": "hot"}}, + {Name: "mynamespace_groupcache_gets_total", Labels: prometheus.Labels{"group": group.Name()}}, + } + for _, expectedMetric := range expectedMetrics { + testName := fmt.Sprintf("Metric exported %s{%s}", expectedMetric.Name, labelsToString(expectedMetric.Labels)) + t.Run(testName, func(t *testing.T) { + assertContainsMetric(t, expectedMetric, mfs) + }) + } +} + +func TestExporterWithLabels(t *testing.T) { + // Given + var wg sync.WaitGroup + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + // Setup groupcache. + group := newGroup(t, t.Name()) + defer groupcache.DeregisterGroup(group.Name()) + gcexporter := promexporter.NewExporter(promexporter.WithLabels(map[string]string{ + "accountid": "0001", + "dc": "west", + })) + registry := prometheus.NewRegistry() + registry.MustRegister(gcexporter) + + // Setup metrics HTTP server. + httpSrv, err := startMetricsServer(ctx, t, registry, &wg) + require.NoError(t, err) + defer func() { + // Tear down. + t.Log("HTTP server shutting down...") + err = httpSrv.Shutdown(ctx) + require.NoError(t, err) + wg.Wait() + }() + + // When + metricsContent, err := getMetrics(ctx, httpSrv) + require.NoError(t, err) + + // Then + // Parse metrics and assert expected values are found. + mfs, err := parseMetricsContent(metricsContent) + require.NoError(t, err) + expectedMetrics := []MetricInfo{ + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group.Name(), "type": "main", "accountid": "0001", "dc": "west"}}, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group.Name(), "type": "hot", "accountid": "0001", "dc": "west"}}, + {Name: "groupcache_gets_total", Labels: prometheus.Labels{"group": group.Name(), "accountid": "0001", "dc": "west"}}, + } + for _, expectedMetric := range expectedMetrics { + assertContainsMetric(t, expectedMetric, mfs) + } +} + +func TestExporterWithGroups(t *testing.T) { + // Given + var wg sync.WaitGroup + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + // Setup groupcache. + group1 := newGroup(t, t.Name()+"_1") + group2 := newGroup(t, t.Name()+"_2") + group3 := newGroup(t, t.Name()+"_3") + defer func() { + groupcache.DeregisterGroup(group1.Name()) + groupcache.DeregisterGroup(group2.Name()) + groupcache.DeregisterGroup(group3.Name()) + }() + gcexporter := promexporter.NewExporter(promexporter.WithGroups(func() []*groupcache.Group { + return []*groupcache.Group{group1, group2} + })) + registry := prometheus.NewRegistry() + registry.MustRegister(gcexporter) + + // Setup metrics HTTP server. + httpSrv, err := startMetricsServer(ctx, t, registry, &wg) + require.NoError(t, err) + defer func() { + // Tear down. + t.Log("HTTP server shutting down...") + err = httpSrv.Shutdown(ctx) + require.NoError(t, err) + wg.Wait() + }() + + // When + metricsContent, err := getMetrics(ctx, httpSrv) + require.NoError(t, err) + + // Then + // Parse metrics and assert expected values are found. + mfs, err := parseMetricsContent(metricsContent) + require.NoError(t, err) + expectedMetrics := []MetricInfo{ + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group1.Name(), "type": "main"}}, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group1.Name(), "type": "hot"}}, + {Name: "groupcache_gets_total", Labels: prometheus.Labels{"group": group1.Name()}}, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group2.Name(), "type": "main"}}, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group2.Name(), "type": "hot"}}, + {Name: "groupcache_gets_total", Labels: prometheus.Labels{"group": group2.Name()}}, + } + for _, expectedMetric := range expectedMetrics { + assertContainsMetric(t, expectedMetric, mfs) + } + // Assert unexpected values are not found. + unexpectedMetrics := []MetricInfo{ + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group3.Name(), "type": "main"}}, + {Name: "groupcache_cache_bytes", Labels: prometheus.Labels{"group": group3.Name(), "type": "hot"}}, + {Name: "groupcache_gets_total", Labels: prometheus.Labels{"group": group3.Name()}}, + } + for _, unexpectedMetric := range unexpectedMetrics { + assertNotContainsMetric(t, unexpectedMetric, mfs) + } +} + +// Create new test group. +func newGroup(t *testing.T, name string) *groupcache.Group { + getter := func(_ context.Context, key string, dest groupcache.Sink) error { + err := dest.SetString("foobar", time.Now().Add(ttl)) + require.NoError(t, err) + return nil + } + return groupcache.NewGroup(name, 10_000, groupcache.GetterFunc(getter)) +} + // Start an HTTP server on a dynamic port. -func startHTTPServer(ctx context.Context, mux *http.ServeMux, wg *sync.WaitGroup) (*http.Server, error) { +func startMetricsServer(ctx context.Context, t *testing.T, registry *prometheus.Registry, wg *sync.WaitGroup) (*http.Server, error) { + mux := http.NewServeMux() + mux.HandleFunc(pingRoute, pingHandler) + // mux.Handle(metricsRoute, promhttp.Handler()) + mux.Handle(metricsRoute, promhttp.HandlerFor(registry, promhttp.HandlerOpts{})) listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { return nil, err @@ -148,7 +291,8 @@ func startHTTPServer(ctx context.Context, mux *http.ServeMux, wg *sync.WaitGroup wg.Done() }() err = waitForReady(ctx, httpSrv) - return httpSrv, err + t.Logf("HTTP server ready at %s", httpSrv.Addr) + return httpSrv, nil } func waitForReady(ctx context.Context, httpSrv *http.Server) error { @@ -170,6 +314,10 @@ func waitForReady(ctx context.Context, httpSrv *http.Server) error { }) } +func pingHandler(writer http.ResponseWriter, rq *http.Request) { + writer.WriteHeader(http.StatusOK) +} + func getURL(ctx context.Context, u string) (*http.Response, error) { rq, err := http.NewRequestWithContext(ctx, http.MethodGet, u, http.NoBody) if err != nil { @@ -178,37 +326,60 @@ func getURL(ctx context.Context, u string) (*http.Response, error) { return http.DefaultClient.Do(rq) } -// Assert expected metric name and labels are present. -func assertContainsMetric(t *testing.T, expected MetricInfo, mfs map[string]*promdto.MetricFamily) { - mf, ok := mfs[expected.Name] - if !assert.True(t, ok, "Metric not found") { - return +// Request metrics endpoint and return content. +func getMetrics(ctx context.Context, httpSrv *http.Server) ([]byte, error) { + rs, err := getURL(ctx, fmt.Sprintf("http://%s%s", httpSrv.Addr, metricsRoute)) + if err != nil { + return nil, err + } + content, err := io.ReadAll(rs.Body) + rs.Body.Close() + return content, err +} + +// Parse metrics content into Prometheus metric structures. +func parseMetricsContent(content []byte) (map[string]*promdto.MetricFamily, error) { + var tp expfmt.TextParser + return tp.TextToMetricFamilies(bytes.NewReader(content)) +} + +func containsMetric(mi MetricInfo, mfs map[string]*promdto.MetricFamily) bool { + mf, ok := mfs[mi.Name] + if !ok { + return false } - matchFlag := false +LM1: for _, metric := range mf.Metric { - LM1: - for key, value := range expected.Labels { + LM2: + for key, value := range mi.Labels { for _, label := range metric.Label { if label.Name == nil || label.Value == nil { continue } if *label.Name == key && *label.Value == value { // Label match, go to next expected label. - continue LM1 + continue LM2 } } - break LM1 + // Expected label not found. + continue LM1 } // All labels match. - matchFlag = true - break + return true } - assert.True(t, matchFlag, "Labels mismatch") + // No metrics match. + return false } -func pingHandler(writer http.ResponseWriter, rq *http.Request) { - writer.WriteHeader(http.StatusOK) +// Assert expected metric name and labels are present. +func assertContainsMetric(t *testing.T, expected MetricInfo, mfs map[string]*promdto.MetricFamily) { + assert.True(t, containsMetric(expected, mfs), "Metric not found: %s", expected.String()) +} + +// Assert expected metric name and labels are not present. +func assertNotContainsMetric(t *testing.T, unexpected MetricInfo, mfs map[string]*promdto.MetricFamily) { + assert.False(t, containsMetric(unexpected, mfs), "Metric unexpectedly found: %s", unexpected.String()) } func labelsToString(labels prometheus.Labels) string { @@ -226,3 +397,7 @@ func labelsToString(labels prometheus.Labels) string { } return buf.String() } + +func (mi *MetricInfo) String() string { + return fmt.Sprintf("%s{%s}", mi.Name, labelsToString(mi.Labels)) +} From 71302140e5583df62309426a0ac5ba2d3ae86cb6 Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Thu, 26 Dec 2024 14:42:34 -0500 Subject: [PATCH 43/44] Revise WithGroups() to use interface instead of callback. --- promexporter/README.md | 3 ++- promexporter/exporter.go | 24 +++++++++++++++++------- promexporter/exporter_test.go | 15 ++++++++++++--- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/promexporter/README.md b/promexporter/README.md index 277f033..437040d 100644 --- a/promexporter/README.md +++ b/promexporter/README.md @@ -8,11 +8,12 @@ This exporter extracts statistics from groupcache instances and exports Promethe import ( "github.com/mailgun/groupcache/v2" "github.com/mailgun/groupcache/v2/promexporter" + "github.com/prometheus/client_golang/prometheus" ) // ... -collector := promexporter.NewExporter("", nil) +collector := promexporter.NewExporter() prometheus.MustRegister(collector) // Collector will discover newly created group. diff --git a/promexporter/exporter.go b/promexporter/exporter.go index d6e25e9..7597168 100644 --- a/promexporter/exporter.go +++ b/promexporter/exporter.go @@ -10,7 +10,7 @@ import ( type Exporter struct { namespace string labels map[string]string - getGroups func() []*groupcache.Group + groupProvider GroupProvider groupGets *prometheus.Desc groupHits *prometheus.Desc groupGetFromPeersLatencyLower *prometheus.Desc @@ -95,16 +95,22 @@ type labelsOption struct { } type groupsOption struct { - groupsFn func() []*groupcache.Group + provider GroupProvider } +type GroupProvider interface { + Groups() []*groupcache.Group +} + +type allGroupsProvider struct{} + // NewExporter creates Exporter. // namespace is usually the empty string. func NewExporter(opts ...Option) *Exporter { const subsystem = "groupcache" e := &Exporter{ - getGroups: groupcache.GetGroups, + groupProvider: new(allGroupsProvider), } for _, opt := range opts { opt.apply(e) @@ -209,7 +215,7 @@ func NewExporter(opts ...Option) *Exporter { } func (e *Exporter) getStatGroups() []GroupStatistics { - groups := e.getGroups() + groups := e.groupProvider.Groups() statgroups := make([]GroupStatistics, 0, len(groups)) for _, g := range groups { statgroups = append(statgroups, newStatsAdapter(g)) @@ -297,10 +303,14 @@ func (o *labelsOption) apply(e *Exporter) { } // Set function used to get groups to export. Called on every scrape. -func WithGroups(groupsFn func() []*groupcache.Group) Option { - return &groupsOption{groupsFn: groupsFn} +func WithGroups(groups GroupProvider) Option { + return &groupsOption{provider: groups} } func (o *groupsOption) apply(e *Exporter) { - e.getGroups = o.groupsFn + e.groupProvider = o.provider +} + +func (gp *allGroupsProvider) Groups() []*groupcache.Group { + return groupcache.GetGroups() } diff --git a/promexporter/exporter_test.go b/promexporter/exporter_test.go index 8ed86a7..7c42917 100644 --- a/promexporter/exporter_test.go +++ b/promexporter/exporter_test.go @@ -198,6 +198,14 @@ func TestExporterWithLabels(t *testing.T) { } } +type TestGroupProvider struct { + groups []*groupcache.Group +} + +func (gp *TestGroupProvider) Groups() []*groupcache.Group { + return gp.groups +} + func TestExporterWithGroups(t *testing.T) { // Given var wg sync.WaitGroup @@ -213,9 +221,10 @@ func TestExporterWithGroups(t *testing.T) { groupcache.DeregisterGroup(group2.Name()) groupcache.DeregisterGroup(group3.Name()) }() - gcexporter := promexporter.NewExporter(promexporter.WithGroups(func() []*groupcache.Group { - return []*groupcache.Group{group1, group2} - })) + groupProvider := &TestGroupProvider{ + groups: []*groupcache.Group{group1, group2}, + } + gcexporter := promexporter.NewExporter(promexporter.WithGroups(groupProvider)) registry := prometheus.NewRegistry() registry.MustRegister(gcexporter) From f3b98d8f369ed8a17579a5d8070cce781a6603da Mon Sep 17 00:00:00 2001 From: Shawn Poulson Date: Thu, 26 Dec 2024 15:23:10 -0500 Subject: [PATCH 44/44] Revise README.md. --- promexporter/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/promexporter/README.md b/promexporter/README.md index 437040d..5a7b5e4 100644 --- a/promexporter/README.md +++ b/promexporter/README.md @@ -1,8 +1,8 @@ # Prometheus Groupcache Exporter -This exporter extracts statistics from groupcache instances and exports Prometheus metrics. +This exporter extracts statistics from group instances and exports as Prometheus metrics. -# Example +## Example ```go import ( @@ -20,14 +20,17 @@ prometheus.MustRegister(collector) group := groupcache.NewGroup("mygroup", cacheSize, getter) ``` -## Exported Metrics +## Metrics +### Exported from groupcache's `CacheStats()` - `groupcache_cache_bytes{group,type="main|hot"}`: Gauge of current bytes in use - `groupcache_cache_evictions_nonexpired_total{group,type="main|hot"}`: Count of cache evictions for non-expired keys due to memory full - `groupcache_cache_evictions_total{group,type="main|hot"}`: Count of cache evictions - `groupcache_cache_gets_total{group,type="main|hot"}`: Count of cache gets - `groupcache_cache_hits_total{group,type="main|hot"}`: Count of cache hits - `groupcache_cache_items{group,type="main|hot"}`: Gauge of current items in use + +### Exported from groupcache's `Stats()` - `groupcache_get_from_peers_latency_lower{group}`: Represent slowest duration to request value from peers - `groupcache_gets_total{group}`: Count of cache gets (including from peers, from either main or hot caches) - `groupcache_hits_total{group}`: Count of cache hits (from either main or hot caches) @@ -39,6 +42,6 @@ group := groupcache.NewGroup("mygroup", cacheSize, getter) - `groupcache_peer_loads_total{group}`: Count of loads or cache hits from peers - `groupcache_server_requests_total{group}`: Count of gets received from peers -# Attribution +## Attribution -This package source was copied from https://github.com/udhos/groupcache_exporter. See LICENSE for MIT license details impacting the contents of this package directory in addition to the LICENSE at the root of this repo for co-existing Apache license details. +This package source originated from https://github.com/udhos/groupcache_exporter. See LICENSE for MIT license details impacting the contents of this package directory in addition to the LICENSE at the root of this repo for co-existing Apache license details.