сleanup (#24)
* move out prometheus metrics * not use gorilla wrappers Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
ef773d8d49
commit
36c53b4917
@ -5,12 +5,9 @@ import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/unistack-org/micro/v3/api/server"
|
||||
"github.com/unistack-org/micro/v3/api/server/cors"
|
||||
"github.com/unistack-org/micro/v3/logger"
|
||||
)
|
||||
|
||||
@ -58,14 +55,6 @@ func (s *httpServer) Handle(path string, handler http.Handler) {
|
||||
handler = wrapper(handler)
|
||||
}
|
||||
|
||||
// wrap with cors
|
||||
if s.opts.EnableCORS {
|
||||
handler = cors.CombinedCORSHandler(handler)
|
||||
}
|
||||
|
||||
// wrap with logger
|
||||
handler = handlers.CombinedLoggingHandler(os.Stdout, handler)
|
||||
|
||||
s.mux.Handle(path, handler)
|
||||
}
|
||||
|
||||
|
4
go.mod
4
go.mod
@ -16,19 +16,19 @@ require (
|
||||
github.com/gobwas/ws v1.0.3
|
||||
github.com/golang/protobuf v1.4.2
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gorilla/handlers v1.4.2
|
||||
github.com/hashicorp/hcl v1.0.0
|
||||
github.com/kr/pretty v0.2.0 // indirect
|
||||
github.com/miekg/dns v1.1.27
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.7.0
|
||||
github.com/stretchr/testify v1.5.1
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013
|
||||
google.golang.org/protobuf v1.25.0
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
)
|
||||
|
20
go.sum
20
go.sum
@ -33,9 +33,7 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k=
|
||||
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/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
@ -53,8 +51,6 @@ github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6R
|
||||
github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY=
|
||||
github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok=
|
||||
@ -89,7 +85,6 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
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-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=
|
||||
@ -146,8 +141,6 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
||||
github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE=
|
||||
@ -167,8 +160,6 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
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 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
@ -237,25 +228,17 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||
github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
|
||||
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/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.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
@ -376,7 +359,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -473,8 +455,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
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 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@ -1,18 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOptions(t *testing.T) {
|
||||
|
||||
// Make some new options:
|
||||
options := NewOptions(Path("/prometheus"), DefaultTags(map[string]string{"service": "prometheus-test"}))
|
||||
|
||||
// Check that the defaults and overrides were accepted:
|
||||
assert.Equal(t, ":9000", options.Address)
|
||||
assert.Equal(t, "/prometheus", options.Path)
|
||||
assert.Equal(t, "prometheus-test", options.DefaultTags["service"])
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
Prometheus
|
||||
==========
|
||||
|
||||
A Prometheus "pull" based implementation of the metrics Reporter interface.
|
||||
|
||||
|
||||
Capabilities
|
||||
------------
|
||||
|
||||
* Go runtime metrics are handled natively by the Prometheus client library (CPU / MEM / GC / GoRoutines etc).
|
||||
* User-defined metrics are registered in the Prometheus client dynamically (they must be pre-registered, hence all of the faffing around in metric_family.go).
|
||||
* The metrics are made available on a Prometheus-compatible HTTP endpoint, which can be scraped at any time. This means that the user can very easily access stats even running locally as a standalone binary.
|
||||
* Requires a micro.Server parameter (from which it gathers the service name and version). These are included as tags with every metric.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```golang
|
||||
prometheusReporter := metrics.New(server)
|
||||
tags := metrics.Tags{"greeter": "Janos"}
|
||||
err := prometheusReporter.Count("hellos", 1, tags)
|
||||
if err != nil {
|
||||
fmt.Printf("Error setting a Count metric: %v", err)
|
||||
}
|
||||
```
|
@ -1,109 +0,0 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// metricFamily stores our cached metrics:
|
||||
type metricFamily struct {
|
||||
counters map[string]*prometheus.CounterVec
|
||||
gauges map[string]*prometheus.GaugeVec
|
||||
timings map[string]*prometheus.SummaryVec
|
||||
defaultLabels prometheus.Labels
|
||||
mutex sync.Mutex
|
||||
prometheusRegistry *prometheus.Registry
|
||||
timingObjectives map[float64]float64
|
||||
}
|
||||
|
||||
// newMetricFamily returns a new metricFamily (useful in case we want to change the structure later):
|
||||
func (r *Reporter) newMetricFamily() metricFamily {
|
||||
return metricFamily{
|
||||
counters: make(map[string]*prometheus.CounterVec),
|
||||
gauges: make(map[string]*prometheus.GaugeVec),
|
||||
timings: make(map[string]*prometheus.SummaryVec),
|
||||
defaultLabels: r.convertTags(r.options.DefaultTags),
|
||||
prometheusRegistry: r.prometheusRegistry,
|
||||
timingObjectives: r.options.TimingObjectives,
|
||||
}
|
||||
}
|
||||
|
||||
// getCounter either gets a counter, or makes a new one:
|
||||
func (mf *metricFamily) getCounter(name string, labelNames []string) *prometheus.CounterVec {
|
||||
mf.mutex.Lock()
|
||||
defer mf.mutex.Unlock()
|
||||
|
||||
// See if we already have this counter:
|
||||
counter, ok := mf.counters[name]
|
||||
if !ok {
|
||||
|
||||
// Make a new counter:
|
||||
counter = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: name,
|
||||
ConstLabels: mf.defaultLabels,
|
||||
},
|
||||
labelNames,
|
||||
)
|
||||
|
||||
// Register it and add it to our list:
|
||||
mf.prometheusRegistry.MustRegister(counter)
|
||||
mf.counters[name] = counter
|
||||
}
|
||||
|
||||
return counter
|
||||
}
|
||||
|
||||
// getGauge either gets a gauge, or makes a new one:
|
||||
func (mf *metricFamily) getGauge(name string, labelNames []string) *prometheus.GaugeVec {
|
||||
mf.mutex.Lock()
|
||||
defer mf.mutex.Unlock()
|
||||
|
||||
// See if we already have this gauge:
|
||||
gauge, ok := mf.gauges[name]
|
||||
if !ok {
|
||||
|
||||
// Make a new gauge:
|
||||
gauge = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: name,
|
||||
ConstLabels: mf.defaultLabels,
|
||||
},
|
||||
labelNames,
|
||||
)
|
||||
|
||||
// Register it and add it to our list:
|
||||
mf.prometheusRegistry.MustRegister(gauge)
|
||||
mf.gauges[name] = gauge
|
||||
}
|
||||
|
||||
return gauge
|
||||
}
|
||||
|
||||
// getTiming either gets a timing, or makes a new one:
|
||||
func (mf *metricFamily) getTiming(name string, labelNames []string) *prometheus.SummaryVec {
|
||||
mf.mutex.Lock()
|
||||
defer mf.mutex.Unlock()
|
||||
|
||||
// See if we already have this timing:
|
||||
timing, ok := mf.timings[name]
|
||||
if !ok {
|
||||
|
||||
// Make a new timing:
|
||||
timing = prometheus.NewSummaryVec(
|
||||
prometheus.SummaryOpts{
|
||||
Name: name,
|
||||
ConstLabels: mf.defaultLabels,
|
||||
Objectives: mf.timingObjectives,
|
||||
},
|
||||
labelNames,
|
||||
)
|
||||
|
||||
// Register it and add it to our list:
|
||||
mf.prometheusRegistry.MustRegister(timing)
|
||||
mf.timings[name] = timing
|
||||
}
|
||||
|
||||
return timing
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/unistack-org/micro/v3/metrics"
|
||||
)
|
||||
|
||||
// ErrPrometheusPanic is a catch-all for the panics which can be thrown by the Prometheus client:
|
||||
var ErrPrometheusPanic = errors.New("The Prometheus client panicked. Did you do something like change the tag cardinality or the type of a metric?")
|
||||
|
||||
// Count is a counter with key/value tags:
|
||||
// New values are added to any previous one (eg "number of hits")
|
||||
func (r *Reporter) Count(name string, value int64, tags metrics.Tags) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ErrPrometheusPanic
|
||||
}
|
||||
}()
|
||||
|
||||
counter := r.metrics.getCounter(r.stripUnsupportedCharacters(name), r.listTagKeys(tags))
|
||||
metric, err := counter.GetMetricWith(r.convertTags(tags))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
metric.Add(float64(value))
|
||||
return err
|
||||
}
|
||||
|
||||
// Gauge is a register with key/value tags:
|
||||
// New values simply override any previous one (eg "current connections")
|
||||
func (r *Reporter) Gauge(name string, value float64, tags metrics.Tags) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ErrPrometheusPanic
|
||||
}
|
||||
}()
|
||||
|
||||
gauge := r.metrics.getGauge(r.stripUnsupportedCharacters(name), r.listTagKeys(tags))
|
||||
metric, err := gauge.GetMetricWith(r.convertTags(tags))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
metric.Set(value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Timing is a histogram with key/valye tags:
|
||||
// New values are added into a series of aggregations
|
||||
func (r *Reporter) Timing(name string, value time.Duration, tags metrics.Tags) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ErrPrometheusPanic
|
||||
}
|
||||
}()
|
||||
|
||||
timing := r.metrics.getTiming(r.stripUnsupportedCharacters(name), r.listTagKeys(tags))
|
||||
metric, err := timing.GetMetricWith(r.convertTags(tags))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
metric.Observe(value.Seconds())
|
||||
return err
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
log "github.com/unistack-org/micro/v3/logger"
|
||||
"github.com/unistack-org/micro/v3/metrics"
|
||||
)
|
||||
|
||||
// Reporter is an implementation of metrics.Reporter:
|
||||
type Reporter struct {
|
||||
options metrics.Options
|
||||
prometheusRegistry *prometheus.Registry
|
||||
metrics metricFamily
|
||||
}
|
||||
|
||||
// New returns a configured prometheus reporter:
|
||||
func New(opts ...metrics.Option) (*Reporter, error) {
|
||||
options := metrics.NewOptions(opts...)
|
||||
|
||||
// Make a prometheus registry (this keeps track of any metrics we generate):
|
||||
prometheusRegistry := prometheus.NewRegistry()
|
||||
prometheusRegistry.Register(prometheus.NewGoCollector())
|
||||
prometheusRegistry.Register(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{Namespace: "goruntime"}))
|
||||
|
||||
// Make a new Reporter:
|
||||
newReporter := &Reporter{
|
||||
options: options,
|
||||
prometheusRegistry: prometheusRegistry,
|
||||
}
|
||||
|
||||
// Add metrics families for each type:
|
||||
newReporter.metrics = newReporter.newMetricFamily()
|
||||
|
||||
// Handle the metrics endpoint with prometheus:
|
||||
log.Infof("Metrics/Prometheus [http] Listening on %s%s", options.Address, options.Path)
|
||||
http.Handle(options.Path, promhttp.HandlerFor(prometheusRegistry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}))
|
||||
go http.ListenAndServe(options.Address, nil)
|
||||
|
||||
return newReporter, nil
|
||||
}
|
||||
|
||||
// convertTags turns Tags into prometheus labels:
|
||||
func (r *Reporter) convertTags(tags metrics.Tags) prometheus.Labels {
|
||||
labels := prometheus.Labels{}
|
||||
for key, value := range tags {
|
||||
labels[key] = r.stripUnsupportedCharacters(value)
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
// listTagKeys returns a list of tag keys (we need to provide this to the Prometheus client):
|
||||
func (r *Reporter) listTagKeys(tags metrics.Tags) (labelKeys []string) {
|
||||
for key := range tags {
|
||||
labelKeys = append(labelKeys, key)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// stripUnsupportedCharacters cleans up a metrics key or value:
|
||||
func (r *Reporter) stripUnsupportedCharacters(metricName string) string {
|
||||
valueWithoutDots := strings.Replace(metricName, ".", "_", -1)
|
||||
valueWithoutCommas := strings.Replace(valueWithoutDots, ",", "_", -1)
|
||||
valueWIthoutSpaces := strings.Replace(valueWithoutCommas, " ", "", -1)
|
||||
return valueWIthoutSpaces
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/unistack-org/micro/v3/metrics"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPrometheusReporter(t *testing.T) {
|
||||
|
||||
// Make a Reporter:
|
||||
reporter, err := New(metrics.Path("/prometheus"), metrics.DefaultTags(map[string]string{"service": "prometheus-test"}))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, reporter)
|
||||
assert.Equal(t, "prometheus-test", reporter.options.DefaultTags["service"])
|
||||
assert.Equal(t, ":9000", reporter.options.Address)
|
||||
assert.Equal(t, "/prometheus", reporter.options.Path)
|
||||
|
||||
// Check that our implementation is valid:
|
||||
assert.Implements(t, new(metrics.Reporter), reporter)
|
||||
|
||||
// Test tag conversion:
|
||||
tags := metrics.Tags{
|
||||
"tag1": "false",
|
||||
"tag2": "true",
|
||||
}
|
||||
convertedTags := reporter.convertTags(tags)
|
||||
assert.Equal(t, "false", convertedTags["tag1"])
|
||||
assert.Equal(t, "true", convertedTags["tag2"])
|
||||
|
||||
// Test tag enumeration:
|
||||
listedTags := reporter.listTagKeys(tags)
|
||||
assert.Contains(t, listedTags, "tag1")
|
||||
assert.Contains(t, listedTags, "tag2")
|
||||
|
||||
// Test string cleaning:
|
||||
preparedMetricName := reporter.stripUnsupportedCharacters("some.kind,of tag")
|
||||
assert.Equal(t, "some_kind_oftag", preparedMetricName)
|
||||
|
||||
// Test MetricFamilies:
|
||||
metricFamily := reporter.newMetricFamily()
|
||||
|
||||
// Counters:
|
||||
assert.NotNil(t, metricFamily.getCounter("testCounter", []string{"test", "counter"}))
|
||||
assert.Len(t, metricFamily.counters, 1)
|
||||
|
||||
// Gauges:
|
||||
assert.NotNil(t, metricFamily.getGauge("testGauge", []string{"test", "gauge"}))
|
||||
assert.Len(t, metricFamily.gauges, 1)
|
||||
|
||||
// Timings:
|
||||
assert.NotNil(t, metricFamily.getTiming("testTiming", []string{"test", "timing"}))
|
||||
assert.Len(t, metricFamily.timings, 1)
|
||||
|
||||
// Test submitting metrics through the interface methods:
|
||||
assert.NoError(t, reporter.Count("test.counter.1", 6, tags))
|
||||
assert.NoError(t, reporter.Count("test.counter.2", 19, tags))
|
||||
assert.NoError(t, reporter.Count("test.counter.1", 5, tags))
|
||||
assert.NoError(t, reporter.Gauge("test.gauge.1", 99, tags))
|
||||
assert.NoError(t, reporter.Gauge("test.gauge.2", 55, tags))
|
||||
assert.NoError(t, reporter.Gauge("test.gauge.1", 98, tags))
|
||||
assert.NoError(t, reporter.Timing("test.timing.1", time.Second, tags))
|
||||
assert.NoError(t, reporter.Timing("test.timing.2", time.Minute, tags))
|
||||
assert.Len(t, reporter.metrics.counters, 2)
|
||||
assert.Len(t, reporter.metrics.gauges, 2)
|
||||
assert.Len(t, reporter.metrics.timings, 2)
|
||||
|
||||
// Test reading back the metrics:
|
||||
// This could be done by hitting the /metrics endpoint
|
||||
}
|
Loading…
Reference in New Issue
Block a user