diff --git a/conf/config-example.yaml b/conf/config-example.yaml index b00231ac..71f3bdbf 100644 --- a/conf/config-example.yaml +++ b/conf/config-example.yaml @@ -7,6 +7,11 @@ log: # Log file path # filePath: +# Metrics configuration +metrics: + # Disable router path save in HTTP metrics + disableRouterPath: false + # Server configurations # server: # listenAddr: "" diff --git a/docs/configuration/example.md b/docs/configuration/example.md index eb1950a2..8ea357e7 100644 --- a/docs/configuration/example.md +++ b/docs/configuration/example.md @@ -17,6 +17,11 @@ log: # Log file path # filePath: +# Metrics configuration +metrics: + # Disable router path save in HTTP metrics + disableRouterPath: false + # Server configurations # server: # listenAddr: "" diff --git a/docs/configuration/structure.md b/docs/configuration/structure.md index 718a6bf5..609542e9 100644 --- a/docs/configuration/structure.md +++ b/docs/configuration/structure.md @@ -19,6 +19,13 @@ You can see a full example in the [Example section](./example.md) | targets | Map[String][targetconfiguration](#targetconfiguration) | No | None | Targets configuration. Map key will be considered as the target name. (This will used in urls and list of targets.) | | authProviders | [AuthProvidersConfiguration](#authprovidersconfiguration) | No | None | Authentication providers configuration | | listTargets | [ListTargetsConfiguration](#listtargetsconfiguration) | No | None | List targets feature configuration | +| metrics | [MetricsConfiguration](#metricsconfiguration) | No | None | Metrics configurations | + +## MetricsConfiguration + +| Key | Type | Required | Default | Description | +| ----------------- | ------- | -------- | ------- | ---------------------------------------- | +| disableRouterPath | Boolean | No | `false` | Disable router path exported in metrics. | ## LogConfiguration diff --git a/pkg/s3-proxy/bucket/mocks/mock_Client.go b/pkg/s3-proxy/bucket/mocks/mock_Client.go index d9025bdd..0144bbc2 100644 --- a/pkg/s3-proxy/bucket/mocks/mock_Client.go +++ b/pkg/s3-proxy/bucket/mocks/mock_Client.go @@ -5,6 +5,7 @@ // // mockgen -destination=./mocks/mock_Client.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/bucket Client // + // Package mocks is a generated GoMock package. package mocks diff --git a/pkg/s3-proxy/config/config.go b/pkg/s3-proxy/config/config.go index e113b8e0..f8ea109e 100644 --- a/pkg/s3-proxy/config/config.go +++ b/pkg/s3-proxy/config/config.go @@ -145,6 +145,7 @@ const oidcCallbackPathTemplate = "/auth/%s/callback" type Config struct { Log *LogConfig `mapstructure:"log"` Tracing *TracingConfig `mapstructure:"tracing"` + Metrics *MetricsConfig `mapstructure:"metrics"` Server *ServerConfig `mapstructure:"server"` InternalServer *ServerConfig `mapstructure:"internalServer"` Targets map[string]*TargetConfig `mapstructure:"targets"` @@ -153,6 +154,11 @@ type Config struct { ListTargets *ListTargetsConfig `mapstructure:"listTargets"` } +// MetricsConfig represents the metrics configuration structure. +type MetricsConfig struct { + DisableRouterPath bool `mapstructure:"disableRouterPath"` +} + // TracingConfig represents the Tracing configuration structure. type TracingConfig struct { FixedTags map[string]interface{} `mapstructure:"fixedTags"` diff --git a/pkg/s3-proxy/config/managerimpl.go b/pkg/s3-proxy/config/managerimpl.go index 89e0c8b4..ae301254 100644 --- a/pkg/s3-proxy/config/managerimpl.go +++ b/pkg/s3-proxy/config/managerimpl.go @@ -735,6 +735,11 @@ func loadBusinessDefaultValues(out *Config) error { out.Tracing = &TracingConfig{Enabled: false} } + // Manage default values for metrics configuration + if out.Metrics == nil { + out.Metrics = &MetricsConfig{} + } + return nil } diff --git a/pkg/s3-proxy/config/managerimpl_integration_test.go b/pkg/s3-proxy/config/managerimpl_integration_test.go index e4e6fe9d..25e11991 100644 --- a/pkg/s3-proxy/config/managerimpl_integration_test.go +++ b/pkg/s3-proxy/config/managerimpl_integration_test.go @@ -140,6 +140,7 @@ func Test_managercontext_Load(t *testing.T) { Enabled: false, }, Targets: nil, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -166,6 +167,7 @@ func Test_managercontext_Load(t *testing.T) { Enabled: false, }, Targets: nil, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -199,6 +201,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -264,6 +267,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -336,6 +340,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -417,6 +422,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -492,6 +498,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -673,6 +680,7 @@ targets: }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -813,6 +821,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -927,6 +936,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1001,6 +1011,7 @@ VALUE1 }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1104,6 +1115,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1187,6 +1199,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1260,6 +1273,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1342,6 +1356,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1424,6 +1439,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1619,6 +1635,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1690,6 +1707,7 @@ log: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1822,6 +1840,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -1890,6 +1909,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -2022,6 +2042,7 @@ targets: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -2093,6 +2114,7 @@ configuration with error }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -2235,6 +2257,7 @@ targets: }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -2307,6 +2330,7 @@ authProviders: }, Templates: defaultTemplateCfg, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, ListTargets: &ListTargetsConfig{ Enabled: false, }, @@ -2460,6 +2484,7 @@ targets: Timeouts: svrTimeoutsCfg, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, Templates: defaultTemplateCfg, AuthProviders: &AuthProviderConfig{ Basic: map[string]*BasicAuthConfig{ diff --git a/pkg/s3-proxy/config/managerimpl_test.go b/pkg/s3-proxy/config/managerimpl_test.go index 560837aa..ef2ea61b 100644 --- a/pkg/s3-proxy/config/managerimpl_test.go +++ b/pkg/s3-proxy/config/managerimpl_test.go @@ -29,6 +29,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { result: &Config{ ListTargets: &ListTargetsConfig{Enabled: false}, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -42,6 +43,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { result: &Config{ ListTargets: &ListTargetsConfig{Enabled: false}, Tracing: &TracingConfig{Enabled: false, LogSpan: true}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -65,6 +67,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -104,6 +107,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -150,6 +154,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -171,6 +176,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -210,6 +216,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -249,6 +256,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, }, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -271,6 +279,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, ListTargets: &ListTargetsConfig{Enabled: false}, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -308,6 +317,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, ListTargets: &ListTargetsConfig{Enabled: false}, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, { @@ -373,6 +383,7 @@ func Test_loadBusinessDefaultValues(t *testing.T) { }, ListTargets: &ListTargetsConfig{Enabled: false}, Tracing: &TracingConfig{Enabled: false}, + Metrics: &MetricsConfig{DisableRouterPath: false}, }, }, } diff --git a/pkg/s3-proxy/config/mocks/mock_Manager.go b/pkg/s3-proxy/config/mocks/mock_Manager.go index 30578d51..11700ced 100644 --- a/pkg/s3-proxy/config/mocks/mock_Manager.go +++ b/pkg/s3-proxy/config/mocks/mock_Manager.go @@ -5,6 +5,7 @@ // // mockgen -destination=./mocks/mock_Manager.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/config Manager // + // Package mocks is a generated GoMock package. package mocks diff --git a/pkg/s3-proxy/metrics/client.go b/pkg/s3-proxy/metrics/client.go index 6c44f24f..3cf884a9 100644 --- a/pkg/s3-proxy/metrics/client.go +++ b/pkg/s3-proxy/metrics/client.go @@ -1,13 +1,17 @@ package metrics -import "net/http" +import ( + "net/http" + + "github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/config" +) // Client Client metrics interface. // //go:generate mockgen -destination=./mocks/mock_Client.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/metrics Client type Client interface { // Will return a middleware to instrument http routers. - Instrument(serverLabel string) func(next http.Handler) http.Handler + Instrument(serverLabel string, metricsCfg *config.MetricsConfig) func(next http.Handler) http.Handler // Will return a handler to expose metrics over a http server. GetExposeHandler() http.Handler // Will increase counter of S3 operations done by service. diff --git a/pkg/s3-proxy/metrics/mocks/mock_Client.go b/pkg/s3-proxy/metrics/mocks/mock_Client.go index e97f2f3c..6ee1650b 100644 --- a/pkg/s3-proxy/metrics/mocks/mock_Client.go +++ b/pkg/s3-proxy/metrics/mocks/mock_Client.go @@ -5,6 +5,7 @@ // // mockgen -destination=./mocks/mock_Client.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/metrics Client // + // Package mocks is a generated GoMock package. package mocks @@ -12,6 +13,7 @@ import ( http "net/http" reflect "reflect" + config "github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/config" gomock "go.uber.org/mock/gomock" ) @@ -113,15 +115,15 @@ func (mr *MockClientMockRecorder) IncSucceedWebhooks(arg0, arg1 any) *gomock.Cal } // Instrument mocks base method. -func (m *MockClient) Instrument(arg0 string) func(http.Handler) http.Handler { +func (m *MockClient) Instrument(arg0 string, arg1 *config.MetricsConfig) func(http.Handler) http.Handler { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Instrument", arg0) + ret := m.ctrl.Call(m, "Instrument", arg0, arg1) ret0, _ := ret[0].(func(http.Handler) http.Handler) return ret0 } // Instrument indicates an expected call of Instrument. -func (mr *MockClientMockRecorder) Instrument(arg0 any) *gomock.Call { +func (mr *MockClientMockRecorder) Instrument(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Instrument", reflect.TypeOf((*MockClient)(nil).Instrument), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Instrument", reflect.TypeOf((*MockClient)(nil).Instrument), arg0, arg1) } diff --git a/pkg/s3-proxy/metrics/prometheus.go b/pkg/s3-proxy/metrics/prometheus.go index 9e8f2f8f..c1fca179 100644 --- a/pkg/s3-proxy/metrics/prometheus.go +++ b/pkg/s3-proxy/metrics/prometheus.go @@ -5,6 +5,7 @@ import ( "strconv" "time" + "github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/config" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) @@ -23,7 +24,7 @@ type prometheusClient struct { } // Instrument will instrument gin routes. -func (cl *prometheusClient) Instrument(serverLabel string) func(next http.Handler) http.Handler { +func (cl *prometheusClient) Instrument(serverLabel string, metricsCfg *config.MetricsConfig) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Begin timer @@ -42,11 +43,18 @@ func (cl *prometheusClient) Instrument(serverLabel string) func(next http.Handle // Get response size resSz := float64(sw.length) + // Init path + path := r.URL.Path + // Check if router path metrics is disabled + if metricsCfg != nil && metricsCfg.DisableRouterPath { + path = "" + } + // Manage prometheus metrics - cl.reqDur.WithLabelValues(serverLabel, status, r.Method, r.Host, r.URL.Path).Observe(elapsed) - cl.reqCnt.WithLabelValues(serverLabel, status, r.Method, r.Host, r.URL.Path).Inc() - cl.reqSz.WithLabelValues(serverLabel, status, r.Method, r.Host, r.URL.Path).Observe(float64(reqSz)) - cl.resSz.WithLabelValues(serverLabel, status, r.Method, r.Host, r.URL.Path).Observe(resSz) + cl.reqDur.WithLabelValues(serverLabel, status, r.Method, r.Host, path).Observe(elapsed) + cl.reqCnt.WithLabelValues(serverLabel, status, r.Method, r.Host, path).Inc() + cl.reqSz.WithLabelValues(serverLabel, status, r.Method, r.Host, path).Observe(float64(reqSz)) + cl.resSz.WithLabelValues(serverLabel, status, r.Method, r.Host, path).Observe(resSz) }) } } diff --git a/pkg/s3-proxy/response-handler/mocks/mock_ResponseHandler.go b/pkg/s3-proxy/response-handler/mocks/mock_ResponseHandler.go index 7d621ac1..ff0ceed0 100644 --- a/pkg/s3-proxy/response-handler/mocks/mock_ResponseHandler.go +++ b/pkg/s3-proxy/response-handler/mocks/mock_ResponseHandler.go @@ -5,6 +5,7 @@ // // mockgen -destination=./mocks/mock_ResponseHandler.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/response-handler ResponseHandler // + // Package mocks is a generated GoMock package. package mocks diff --git a/pkg/s3-proxy/s3client/mocks/mock_Client.go b/pkg/s3-proxy/s3client/mocks/mock_Client.go index 1be7f9a2..efb1d29d 100644 --- a/pkg/s3-proxy/s3client/mocks/mock_Client.go +++ b/pkg/s3-proxy/s3client/mocks/mock_Client.go @@ -5,6 +5,7 @@ // // mockgen -destination=./mocks/mock_Client.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/s3client Client // + // Package mocks is a generated GoMock package. package mocks diff --git a/pkg/s3-proxy/s3client/mocks/mock_Manager.go b/pkg/s3-proxy/s3client/mocks/mock_Manager.go index ffff6745..325b212c 100644 --- a/pkg/s3-proxy/s3client/mocks/mock_Manager.go +++ b/pkg/s3-proxy/s3client/mocks/mock_Manager.go @@ -5,6 +5,7 @@ // // mockgen -destination=./mocks/mock_Manager.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/s3client Manager // + // Package mocks is a generated GoMock package. package mocks diff --git a/pkg/s3-proxy/server/internal-server.go b/pkg/s3-proxy/server/internal-server.go index d37fcece..75f16938 100644 --- a/pkg/s3-proxy/server/internal-server.go +++ b/pkg/s3-proxy/server/internal-server.go @@ -115,7 +115,7 @@ func (svr *InternalServer) generateInternalRouter() http.Handler { tracing.GetTraceIDFromRequest, )) r.Use(log.HTTPAddLoggerToContextMiddleware()) - r.Use(svr.metricsCl.Instrument("internal")) + r.Use(svr.metricsCl.Instrument("internal", cfg.Metrics)) r.Use(middleware.Recoverer) healthHandler := health.NewHandler() diff --git a/pkg/s3-proxy/server/server.go b/pkg/s3-proxy/server/server.go index 5b98c9f4..1c427ef5 100644 --- a/pkg/s3-proxy/server/server.go +++ b/pkg/s3-proxy/server/server.go @@ -172,7 +172,7 @@ func (svr *Server) generateRouter() (http.Handler, error) { tracing.GetTraceIDFromRequest, )) r.Use(log.HTTPAddLoggerToContextMiddleware()) - r.Use(svr.metricsCl.Instrument("business")) + r.Use(svr.metricsCl.Instrument("business", cfg.Metrics)) // Recover panic r.Use(middleware.Recoverer) diff --git a/pkg/s3-proxy/webhook/mocks/mock_Manager.go b/pkg/s3-proxy/webhook/mocks/mock_Manager.go index 78ea02c1..5b9bef51 100644 --- a/pkg/s3-proxy/webhook/mocks/mock_Manager.go +++ b/pkg/s3-proxy/webhook/mocks/mock_Manager.go @@ -5,6 +5,7 @@ // // mockgen -destination=./mocks/mock_Manager.go -package=mocks github.com/oxyno-zeta/s3-proxy/pkg/s3-proxy/webhook Manager // + // Package mocks is a generated GoMock package. package mocks