diff --git a/cmd/server/handler.go b/cmd/server/handler.go index 9bb552fdf16..5dab6745c03 100644 --- a/cmd/server/handler.go +++ b/cmd/server/handler.go @@ -50,9 +50,9 @@ import ( "github.com/ory/hydra/driver" "github.com/ory/hydra/driver/config" "github.com/ory/hydra/jwk" - "github.com/ory/hydra/metrics/prometheus" "github.com/ory/hydra/oauth2" "github.com/ory/hydra/x" + "github.com/ory/x/prometheusx" ) var _ = &consent.Handler{} diff --git a/contrib/quickstart/5-min/hydra.yml b/contrib/quickstart/5-min/hydra.yml index df60e1f355e..a1b3a7c80da 100644 --- a/contrib/quickstart/5-min/hydra.yml +++ b/contrib/quickstart/5-min/hydra.yml @@ -21,3 +21,5 @@ oidc: pairwise: salt: youReallyNeedToChangeThis + +dsn: memory diff --git a/driver/registry.go b/driver/registry.go index a5b5ba2a3b1..2d2661e7cf6 100644 --- a/driver/registry.go +++ b/driver/registry.go @@ -14,7 +14,7 @@ import ( "github.com/ory/hydra/persistence" - "github.com/ory/hydra/metrics/prometheus" + "github.com/ory/x/prometheusx" "github.com/ory/x/dbal" "github.com/ory/x/healthx" diff --git a/driver/registry_base.go b/driver/registry_base.go index 8f412b033d8..7bc5727c32a 100644 --- a/driver/registry_base.go +++ b/driver/registry_base.go @@ -3,6 +3,7 @@ package driver import ( "context" "fmt" + "github.com/ory/x/prometheusx" "net" "net/http" "strings" @@ -16,7 +17,6 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/ory/hydra/metrics/prometheus" "github.com/ory/x/logrusx" "github.com/gorilla/sessions" @@ -442,7 +442,7 @@ func (m *RegistryBase) Tracer(ctx context.Context) *tracing.Tracer { func (m *RegistryBase) PrometheusManager() *prometheus.MetricsManager { if m.pmm == nil { - m.pmm = prometheus.NewMetricsManager(m.buildVersion, m.buildHash, m.buildDate) + m.pmm = prometheus.NewMetricsManager("Hydra", m.buildVersion, m.buildHash, m.buildDate) } return m.pmm } diff --git a/go.mod b/go.mod index e2c32cccef3..09423890825 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/ory/go-acc v0.2.6 github.com/ory/graceful v0.1.1 github.com/ory/herodot v0.9.3 - github.com/ory/x v0.0.233 + github.com/ory/x v0.0.237 github.com/pborman/uuid v1.2.1 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/philhofer/fwd v1.1.1 // indirect diff --git a/go.sum b/go.sum index 5fd6e757159..9f4bc4d5872 100644 --- a/go.sum +++ b/go.sum @@ -1210,6 +1210,8 @@ github.com/ory/x v0.0.205/go.mod h1:A1s4iwmFIppRXZLF3J9GGWeY/HpREVm0Dk5z/787iek= github.com/ory/x v0.0.207/go.mod h1:sBgvUAcmc2lmtOBe5VMcV2vNAlADT4bkFHomG29y7N4= github.com/ory/x v0.0.233 h1:AiBvucFkE054XJ04OnUziM9Ect5nR/NbMe5101EBjVE= github.com/ory/x v0.0.233/go.mod h1:0mSGWLFgcqckIvgexka1GJK/sshYrFFkU7lPajzGTFw= +github.com/ory/x v0.0.237 h1:sFcWr8EcOYrPb30tsWk3BZM7jdzHeBAqaOSHveizmfs= +github.com/ory/x v0.0.237/go.mod h1:KPgNsUzpztH15EZdw5HjurtTe+mXQ34yqMCCTb5BZAc= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= diff --git a/metrics/prometheus/doc.go b/metrics/prometheus/doc.go deleted file mode 100644 index dbdf42d3d3d..00000000000 --- a/metrics/prometheus/doc.go +++ /dev/null @@ -1,26 +0,0 @@ -package prometheus - -// Outputs Prometheus metrics -// -// swagger:route GET /metrics/prometheus admin prometheus -// -// Get Snapshot Metrics from the Hydra Service. -// -// If you're using k8s, you can then add annotations to your deployment like so: -// -// ``` -// metadata: -// annotations: -// prometheus.io/port: "4445" -// prometheus.io/path: "/metrics/prometheus" -// ``` -// -// If the service supports TLS Edge Termination, this endpoint does not require the -// `X-Forwarded-Proto` header to be set. -// -// Produces: -// - plain/text -// -// Responses: -// 200: emptyResponse -func swaggerPublicPrometheus() {} diff --git a/metrics/prometheus/metrics.go b/metrics/prometheus/metrics.go deleted file mode 100644 index 23a4d71f87c..00000000000 --- a/metrics/prometheus/metrics.go +++ /dev/null @@ -1,68 +0,0 @@ -package prometheus - -import "github.com/prometheus/client_golang/prometheus" - -const ( - MetricsPrometheusPath = "/metrics/prometheus" -) - -// Metrics prototypes -// Example: -// Counter *prometheus.CounterVec -// ResponseTime *prometheus.HistogramVec -type Metrics struct { - ResponseTime *prometheus.HistogramVec -} - -// Method for creation new custom Prometheus metrics -// Example: -// pm := &Metrics{ -// Counter: prometheus.NewCounterVec( -// prometheus.CounterOpts{ -// Name: "servicename_requests_total", -// Help: "Description", -// ConstLabels: map[string]string{ -// "version": version, -// "hash": hash, -// "buildTime": buildTime, -// }, -// }, -// []string{"endpoint"}, -// ), -// ResponseTime: prometheus.NewHistogramVec( -// prometheus.HistogramOpts{ -// Name: "servicename_response_time_seconds", -// Help: "Description", -// ConstLabels: map[string]string{ -// "version": version, -// "hash": hash, -// "buildTime": buildTime, -// }, -// }, -// []string{"endpoint"}, -// ), -// } -// prometheus.Register(pm.Counter) -// prometheus.Register(pm.ResponseTime) -func NewMetrics(version, hash, date string) *Metrics { - pm := &Metrics{ - ResponseTime: prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "hydra_response_time_seconds", - Help: "Description", - ConstLabels: map[string]string{ - "version": version, - "hash": hash, - "buildTime": date, - }, - }, - []string{"endpoint"}, - ), - } - err := prometheus.Register(pm.ResponseTime) - - if err != nil { - panic(err) - } - return pm -} diff --git a/metrics/prometheus/middleware.go b/metrics/prometheus/middleware.go deleted file mode 100644 index 49fee4c88bb..00000000000 --- a/metrics/prometheus/middleware.go +++ /dev/null @@ -1,75 +0,0 @@ -package prometheus - -import ( - "net/http" - "strings" - "time" - - "github.com/julienschmidt/httprouter" -) - -type MetricsManager struct { - prometheusMetrics *Metrics - routers []*httprouter.Router -} - -func NewMetricsManager(version, hash, buildTime string) *MetricsManager { - return &MetricsManager{ - prometheusMetrics: NewMetrics(version, hash, buildTime), - } -} - -// Main middleware method to collect metrics for Prometheus. -// Example: -// start := time.Now() -// next(rw, r) -// Request counter metric -// pmm.prometheusMetrics.Counter.WithLabelValues(r.URL.Path).Inc() -// Response time metric -// pmm.prometheusMetrics.ResponseTime.WithLabelValues(r.URL.Path).Observe(time.Since(start).Seconds()) -func (pmm *MetricsManager) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - start := time.Now() - next(rw, r) - - pmm.prometheusMetrics.ResponseTime.WithLabelValues( - pmm.getLabelForPath(r), - ).Observe(time.Since(start).Seconds()) -} - -func (pmm *MetricsManager) RegisterRouter(router *httprouter.Router) { - pmm.routers = append(pmm.routers, router) -} - -func (pmm *MetricsManager) getLabelForPath(r *http.Request) string { - // looking for a match in one of registered routers - for _, router := range pmm.routers { - handler, params, _ := router.Lookup(r.Method, r.URL.Path) - if handler != nil { - return reconstructEndpoint(r.URL.Path, params) - } - } - return "{unmatched}" -} - -// To reduce cardinality of labels, values of matched path parameters must be replaced with {param} -func reconstructEndpoint(path string, params httprouter.Params) string { - // if map is empty, then nothing to change in the path - if len(params) == 0 { - return path - } - - // construct a list of parameter values - paramValues := make(map[string]struct{}, len(params)) - for _, param := range params { - paramValues[param.Value] = struct{}{} - } - - parts := strings.Split(path, "/") - for index, part := range parts { - if _, ok := paramValues[part]; ok { - parts[index] = "{param}" - } - } - - return strings.Join(parts, "/") -} diff --git a/metrics/prometheus/middleware_test.go b/metrics/prometheus/middleware_test.go deleted file mode 100644 index c7ca4804db9..00000000000 --- a/metrics/prometheus/middleware_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package prometheus - -import ( - "github.com/julienschmidt/httprouter" - "github.com/stretchr/testify/assert" - "net/http" - "net/http/httptest" - "strings" - "testing" -) - -func EmptyHandle(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - // do nothing -} - -func TestMetricsManagerGetLabelForPath(t *testing.T) { - t.Run("case=no-router", func(t *testing.T) { - mm := NewMetricsManager("", "", "") - r := httptest.NewRequest("GET", "/test", strings.NewReader("")) - assert.Equal(t, "{unmatched}", mm.getLabelForPath(r)) - }) - - t.Run("case=registered-routers-no-match", func(t *testing.T) { - router := httprouter.New() - mm := MetricsManager{} - mm.RegisterRouter(router) - r := httptest.NewRequest("GET", "/test", strings.NewReader("")) - assert.Equal(t, "{unmatched}", mm.getLabelForPath(r)) - }) - - t.Run("case=registered-routers-match-no-params", func(t *testing.T) { - router := httprouter.New() - router.GET("/test", EmptyHandle) - mm := MetricsManager{} - mm.RegisterRouter(router) - r := httptest.NewRequest("GET", "/test", strings.NewReader("")) - assert.Equal(t, "/test", mm.getLabelForPath(r)) - }) - - t.Run("case=registered-routers-match-with-param", func(t *testing.T) { - router := httprouter.New() - router.GET("/test/:id", EmptyHandle) - mm := MetricsManager{} - mm.RegisterRouter(router) - r := httptest.NewRequest("GET", "/test/randomId", strings.NewReader("")) - assert.Equal(t, "/test/{param}", mm.getLabelForPath(r)) - }) -} - - -func TestEndpointsReconstruction(t *testing.T) { - //c := internal.NewConfigurationWithDefaults() - - t.Run("case=reconstruct-endpoint-no-params", func(t *testing.T) { - assert.Equal(t, "/test", reconstructEndpoint("/test", httprouter.Params{})) - }) - - t.Run("case=reconstruct-endpoint-one-param", func(t *testing.T) { - assert.Equal(t, "/test/{param}/test", reconstructEndpoint("/test/12345/test", httprouter.Params{httprouter.Param{ - Key: "id", - Value: "12345", - }})) - }) - - t.Run("case=reconstruct-endpoint-multiple-param", func(t *testing.T) { - assert.Equal(t, "/test/{param}/{param}", reconstructEndpoint("/test/12345/abcdef", httprouter.Params{ - httprouter.Param{ - Key: "id", - Value: "12345", - }, - httprouter.Param{ - Key: "id2", - Value: "abcdef", - }, - })) - }) - - // FIXME: parameter value in some caese can match with a static part of URL, which produces a wrong label. - // As of now, httprouter does not provide enough information in the context or in results of Lookup() call, - // so this issue can't be fixed. - t.Run("case=reconstruct-endpoint-param-matches-path-part", func(t *testing.T) { - assert.Equal(t, "/{param}/{param}", reconstructEndpoint("/test/test", httprouter.Params{ - httprouter.Param{ - Key: "id", - Value: "test", - }, - })) - }) -} - diff --git a/x/tls_termination.go b/x/tls_termination.go index 7eb72d428a3..a8ee2e61bbe 100644 --- a/x/tls_termination.go +++ b/x/tls_termination.go @@ -10,8 +10,8 @@ import ( "github.com/pkg/errors" "github.com/urfave/negroni" - "github.com/ory/hydra/metrics/prometheus" "github.com/ory/x/healthx" + "github.com/ory/x/prometheusx" "github.com/ory/x/stringsx" )