diff --git a/cmd/server/server.go b/cmd/server/server.go index cbaec12afa..0c9f91f8b1 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -46,9 +46,13 @@ func runProxy(d driver.Driver, n *negroni.Negroni, logger *logrusx.Logger, prom }, } - promCollapsePaths := d.Configuration().PrometheusCollapseRequestPaths() - - n.Use(metrics.NewMiddleware(prom, "oathkeeper-proxy").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath).CollapsePaths(promCollapsePaths)) + promHidePaths := d.Configuration().PrometheusHideRequestPaths() + if promHidePaths { + n.Use(metrics.NewMiddleware(prom, "oathkeeper-proxy").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath).HidePaths(promHidePaths)) + } else { + promCollapsePaths := d.Configuration().PrometheusCollapseRequestPaths() + n.Use(metrics.NewMiddleware(prom, "oathkeeper-proxy").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath).CollapsePaths(promCollapsePaths)) + } n.Use(reqlog.NewMiddlewareFromLogger(logger, "oathkeeper-proxy").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath)) n.UseHandler(handler) @@ -89,7 +93,11 @@ func runAPI(d driver.Driver, n *negroni.Negroni, logger *logrusx.Logger, prom *m promCollapsePaths := d.Configuration().PrometheusCollapseRequestPaths() - n.Use(metrics.NewMiddleware(prom, "oathkeeper-api").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath).CollapsePaths(promCollapsePaths)) + if true { + n.Use(metrics.NewMiddleware(prom, "oathkeeper-api").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath).HidePaths(true)) + } else { + n.Use(metrics.NewMiddleware(prom, "oathkeeper-api").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath).CollapsePaths(promCollapsePaths)) + } n.Use(reqlog.NewMiddlewareFromLogger(logger, "oathkeeper-api").ExcludePaths(healthx.ReadyCheckPath, healthx.AliveCheckPath)) n.Use(d.Registry().DecisionHandler()) // This needs to be the last entry, otherwise the judge API won't work diff --git a/driver/configuration/provider.go b/driver/configuration/provider.go index fa4f8d8807..5910c0251d 100644 --- a/driver/configuration/provider.go +++ b/driver/configuration/provider.go @@ -55,6 +55,7 @@ type Provider interface { PrometheusServeAddress() string PrometheusMetricsPath() string PrometheusMetricsNamePrefix() string + PrometheusHideRequestPaths() bool PrometheusCollapseRequestPaths() bool ToScopeStrategy(value string, key string) fosite.ScopeStrategy diff --git a/driver/configuration/provider_viper.go b/driver/configuration/provider_viper.go index 38c926c6b7..1a329ded7b 100644 --- a/driver/configuration/provider_viper.go +++ b/driver/configuration/provider_viper.go @@ -52,6 +52,7 @@ const ( ViperKeyPrometheusServeAddressPort = "serve.prometheus.port" ViperKeyPrometheusServeMetricsPath = "serve.prometheus.metrics_path" ViperKeyPrometheusServeMetricsNamePrefix = "serve.prometheus.metric_name_prefix" + ViperKeyPrometheusServeHideRequestPaths = "serve.prometheus.hide_request_paths" ViperKeyPrometheusServeCollapseRequestPaths = "serve.prometheus.collapse_request_paths" ViperKeyAccessRuleRepositories = "access_rules.repositories" ViperKeyAccessRuleMatchingStrategy = "access_rules.matching_strategy" @@ -216,6 +217,10 @@ func (v *ViperProvider) PrometheusMetricsNamePrefix() string { return viperx.GetString(v.l, ViperKeyPrometheusServeMetricsNamePrefix, "ory_oathkeeper_") } +func (v *ViperProvider) PrometheusHideRequestPaths() bool { + return viperx.GetBool(v.l, ViperKeyPrometheusServeHideRequestPaths, false) +} + func (v *ViperProvider) PrometheusCollapseRequestPaths() bool { return viperx.GetBool(v.l, ViperKeyPrometheusServeCollapseRequestPaths, true) } diff --git a/metrics/middleware.go b/metrics/middleware.go index b8664b904c..a21350f9d7 100644 --- a/metrics/middleware.go +++ b/metrics/middleware.go @@ -38,6 +38,7 @@ type Middleware struct { mutex sync.RWMutex silencePaths map[string]bool collapsePaths bool + hidePaths bool } // NewMiddleware returns a new *Middleware, yay! @@ -48,6 +49,7 @@ func NewMiddleware(prom *PrometheusRepository, name string) *Middleware { clock: &realClock{}, silencePaths: map[string]bool{}, collapsePaths: true, + hidePaths: true, } } @@ -73,6 +75,18 @@ func (m *Middleware) CollapsePaths(flag bool) *Middleware { return m } +// HidePaths if set to true, forces the value of the "request" label +// of the prometheus request metrics to be set to a constant "hidden" value. +// eg. (when set to true): +// - /decisions/service/my-service -> /hidden +// - /decisions -> /hidden +func (m *Middleware) HidePaths(flag bool) *Middleware { + m.mutex.Lock() + m.hidePaths = flag + m.mutex.Unlock() + return m +} + func (m *Middleware) getFirstPathSegment(requestURI string) string { // Will split /my/example/uri in []string{"", "my", "example/uri"} uriSegments := strings.SplitN(requestURI, "/", 3) @@ -91,10 +105,15 @@ func (m *Middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next htt if _, silent := m.silencePaths[r.URL.Path]; !silent { requestURI := r.RequestURI - if m.collapsePaths { - requestURI = m.getFirstPathSegment(requestURI) + if m.hidePaths { + requestURI = "/hidden" + } else { + if m.collapsePaths { + requestURI = m.getFirstPathSegment(requestURI) + } } - m.Prometheus.RequestDurationObserve(m.Name, requestURI, r.Method, res.Status())(float64(latency.Seconds())) + + m.Prometheus.RequestDurationObserve(m.Name, requestURI, r.Method, res.Status())(latency.Seconds()) m.Prometheus.UpdateRequest(m.Name, requestURI, r.Method, res.Status()) } }