diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d63801c7..467834793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,8 +40,8 @@ ### Added - Added prometheus metrics for Konnect entity operations in the metrics server: - - `gateway_operator_konnect_entity_operation_count` for number of operations - - `gateway_operator_konnect_entity_operation_duration` for duration of operations + - `gateway_operator_konnect_entity_operation_count` for number of operations. + - `gateway_operator_konnect_entity_operation_duration_milliseconds` for duration of operations. [#953](https://github.com/Kong/gateway-operator/pull/953) ## [v1.4.1] diff --git a/controller/konnect/ops/ops.go b/controller/konnect/ops/ops.go index 8e880b8eb..0e9c157a4 100644 --- a/controller/konnect/ops/ops.go +++ b/controller/konnect/ops/ops.go @@ -38,35 +38,6 @@ const ( DeleteOp Op = "delete" ) -// EntityTypeName is the type of the Konnect entity name used for distinguish operations on different types of entities in the prometheus metrics. -type EntityTypeName string - -// Entity type names for Konnect entity as labels in metrics. -const ( - // Entity type names used in metrics. - // REVIEW: Should we use the path inside the API as the type names? These are not very consistent in - EntityTypeControlPlane EntityTypeName = "control_planes" - EntityTypeService EntityTypeName = "services" - EntityTypeRoute EntityTypeName = "routes" - EntityTypeConsumer EntityTypeName = "consumers" - EntityTypeConsumerGroup EntityTypeName = "consumer_groups" - EntityTypePlugin EntityTypeName = "plugins" - EntityTypeUpstream EntityTypeName = "upstreams" - EntityTypeTarget EntityTypeName = "targets" - EntityTypeBasicAuthCredential EntityTypeName = "basic_auth_credentials" //nolint:gosec - EntityTypeAPIKeyCredential EntityTypeName = "api_key_credentials" //nolint:gosec - EntityTypeACLCredential EntityTypeName = "acl_credentials" - EntityTypeJWTCredential EntityTypeName = "jwt_credentials" - EntityTypeHMACCredential EntityTypeName = "hmac_credentials" - EntityTypeCACertificate EntityTypeName = "ca_certificates" - EntityTypeCertificate EntityTypeName = "certificates" - EntityTypeSNI EntityTypeName = "snis" - EntityTypeKey EntityTypeName = "keys" - EntityTypeKeySet EntityTypeName = "key_sets" - EntityTypeVault EntityTypeName = "vaults" - EntityTypeDataPlaneCertificate EntityTypeName = "data_plane_certificates" -) - // Create creates a Konnect entity. func Create[ T constraints.SupportedKonnectEntityType, @@ -82,69 +53,49 @@ func Create[ err error start = time.Now() - entityType EntityTypeName + entityType = e.GetTypeName() statusCode int ) switch ent := any(e).(type) { case *konnectv1alpha1.KonnectGatewayControlPlane: - entityType = EntityTypeControlPlane err = createControlPlane(ctx, sdk.GetControlPlaneSDK(), sdk.GetControlPlaneGroupSDK(), cl, ent) case *configurationv1alpha1.KongService: - entityType = EntityTypeService err = createService(ctx, sdk.GetServicesSDK(), ent) case *configurationv1alpha1.KongRoute: - entityType = EntityTypeRoute err = createRoute(ctx, sdk.GetRoutesSDK(), ent) case *configurationv1.KongConsumer: - entityType = EntityTypeConsumer err = createConsumer(ctx, sdk.GetConsumersSDK(), sdk.GetConsumerGroupsSDK(), cl, ent) case *configurationv1beta1.KongConsumerGroup: - entityType = EntityTypeConsumerGroup err = createConsumerGroup(ctx, sdk.GetConsumerGroupsSDK(), ent) case *configurationv1alpha1.KongPluginBinding: - entityType = EntityTypePlugin err = createPlugin(ctx, cl, sdk.GetPluginSDK(), ent) case *configurationv1alpha1.KongUpstream: - entityType = EntityTypeUpstream err = createUpstream(ctx, sdk.GetUpstreamsSDK(), ent) case *configurationv1alpha1.KongCredentialBasicAuth: - entityType = EntityTypeBasicAuthCredential err = createKongCredentialBasicAuth(ctx, sdk.GetBasicAuthCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialAPIKey: - entityType = EntityTypeAPIKeyCredential err = createKongCredentialAPIKey(ctx, sdk.GetAPIKeyCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialACL: - entityType = EntityTypeACLCredential err = createKongCredentialACL(ctx, sdk.GetACLCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialJWT: - entityType = EntityTypeJWTCredential err = createKongCredentialJWT(ctx, sdk.GetJWTCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialHMAC: - entityType = EntityTypeHMACCredential err = createKongCredentialHMAC(ctx, sdk.GetHMACCredentialsSDK(), ent) case *configurationv1alpha1.KongCACertificate: - entityType = EntityTypeCACertificate err = createCACertificate(ctx, sdk.GetCACertificatesSDK(), ent) case *configurationv1alpha1.KongCertificate: - entityType = EntityTypeCertificate err = createCertificate(ctx, sdk.GetCertificatesSDK(), ent) case *configurationv1alpha1.KongTarget: - entityType = EntityTypeTarget err = createTarget(ctx, sdk.GetTargetsSDK(), ent) case *configurationv1alpha1.KongVault: - entityType = EntityTypeVault err = createVault(ctx, sdk.GetVaultSDK(), ent) case *configurationv1alpha1.KongKey: - entityType = EntityTypeKey err = createKey(ctx, sdk.GetKeysSDK(), ent) case *configurationv1alpha1.KongKeySet: - entityType = EntityTypeKeySet err = createKeySet(ctx, sdk.GetKeySetsSDK(), ent) case *configurationv1alpha1.KongSNI: - entityType = EntityTypeSNI err = createSNI(ctx, sdk.GetSNIsSDK(), ent) case *configurationv1alpha1.KongDataPlaneClientCertificate: - entityType = EntityTypeDataPlaneCertificate err = createKongDataPlaneClientCertificate(ctx, sdk.GetDataPlaneCertificatesSDK(), ent) // --------------------------------------------------------------------- // TODO: add other Konnect types @@ -229,15 +180,17 @@ func Create[ if err != nil { metricRecorder.RecordKonnectEntityOperationFailure( + sdk.GetServerURL(), metrics.KonnectEntityOperationCreate, - string(entityType), + entityType, time.Since(start), statusCode, ) } else { metricRecorder.RecordKonnectEntityOperationSuccess( + sdk.GetServerURL(), metrics.KonnectEntityOperationCreate, - string(entityType), + entityType, time.Since(start), ) } @@ -267,69 +220,49 @@ func Delete[ err error start = time.Now() - entityType EntityTypeName + entityType = ent.GetTypeName() statusCode int ) switch ent := any(ent).(type) { case *konnectv1alpha1.KonnectGatewayControlPlane: - entityType = EntityTypeControlPlane err = deleteControlPlane(ctx, sdk.GetControlPlaneSDK(), ent) case *configurationv1alpha1.KongService: - entityType = EntityTypeService err = deleteService(ctx, sdk.GetServicesSDK(), ent) case *configurationv1alpha1.KongRoute: - entityType = EntityTypeRoute err = deleteRoute(ctx, sdk.GetRoutesSDK(), ent) case *configurationv1.KongConsumer: - entityType = EntityTypeConsumer err = deleteConsumer(ctx, sdk.GetConsumersSDK(), ent) case *configurationv1beta1.KongConsumerGroup: - entityType = EntityTypeConsumerGroup err = deleteConsumerGroup(ctx, sdk.GetConsumerGroupsSDK(), ent) case *configurationv1alpha1.KongPluginBinding: - entityType = EntityTypePlugin err = deletePlugin(ctx, sdk.GetPluginSDK(), ent) case *configurationv1alpha1.KongUpstream: - entityType = EntityTypeUpstream err = deleteUpstream(ctx, sdk.GetUpstreamsSDK(), ent) case *configurationv1alpha1.KongCredentialBasicAuth: - entityType = EntityTypeBasicAuthCredential err = deleteKongCredentialBasicAuth(ctx, sdk.GetBasicAuthCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialAPIKey: - entityType = EntityTypeAPIKeyCredential err = deleteKongCredentialAPIKey(ctx, sdk.GetAPIKeyCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialACL: - entityType = EntityTypeACLCredential err = deleteKongCredentialACL(ctx, sdk.GetACLCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialJWT: - entityType = EntityTypeJWTCredential err = deleteKongCredentialJWT(ctx, sdk.GetJWTCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialHMAC: - entityType = EntityTypeHMACCredential err = deleteKongCredentialHMAC(ctx, sdk.GetHMACCredentialsSDK(), ent) case *configurationv1alpha1.KongCACertificate: - entityType = EntityTypeCACertificate err = deleteCACertificate(ctx, sdk.GetCACertificatesSDK(), ent) case *configurationv1alpha1.KongCertificate: - entityType = EntityTypeCertificate err = deleteCertificate(ctx, sdk.GetCertificatesSDK(), ent) case *configurationv1alpha1.KongTarget: - entityType = EntityTypeTarget err = deleteTarget(ctx, sdk.GetTargetsSDK(), ent) case *configurationv1alpha1.KongVault: - entityType = EntityTypeVault err = deleteVault(ctx, sdk.GetVaultSDK(), ent) case *configurationv1alpha1.KongKey: - entityType = EntityTypeKey err = deleteKey(ctx, sdk.GetKeysSDK(), ent) case *configurationv1alpha1.KongKeySet: - entityType = EntityTypeKeySet err = deleteKeySet(ctx, sdk.GetKeySetsSDK(), ent) case *configurationv1alpha1.KongSNI: - entityType = EntityTypeSNI err = deleteSNI(ctx, sdk.GetSNIsSDK(), ent) case *configurationv1alpha1.KongDataPlaneClientCertificate: - entityType = EntityTypeDataPlaneCertificate err = deleteKongDataPlaneClientCertificate(ctx, sdk.GetDataPlaneCertificatesSDK(), ent) // --------------------------------------------------------------------- // TODO: add other Konnect types @@ -343,15 +276,17 @@ func Delete[ statusCode = errSDK.StatusCode } metricRecorder.RecordKonnectEntityOperationFailure( + sdk.GetServerURL(), metrics.KonnectEntityOperationDelete, - string(entityType), + entityType, time.Since(start), statusCode, ) } else { metricRecorder.RecordKonnectEntityOperationSuccess( + sdk.GetServerURL(), metrics.KonnectEntityOperationDelete, - string(entityType), + entityType, time.Since(start), ) } @@ -426,67 +361,48 @@ func Update[ var ( err error - entityType EntityTypeName + entityType = e.GetTypeName() statusCode int start = time.Now() ) switch ent := any(e).(type) { case *konnectv1alpha1.KonnectGatewayControlPlane: - entityType = EntityTypeControlPlane err = updateControlPlane(ctx, sdk.GetControlPlaneSDK(), sdk.GetControlPlaneGroupSDK(), cl, ent) case *configurationv1alpha1.KongService: - entityType = EntityTypeService err = updateService(ctx, sdk.GetServicesSDK(), ent) case *configurationv1alpha1.KongRoute: - entityType = EntityTypeRoute err = updateRoute(ctx, sdk.GetRoutesSDK(), ent) case *configurationv1.KongConsumer: - entityType = EntityTypeConsumer err = updateConsumer(ctx, sdk.GetConsumersSDK(), sdk.GetConsumerGroupsSDK(), cl, ent) case *configurationv1beta1.KongConsumerGroup: - entityType = EntityTypeConsumerGroup err = updateConsumerGroup(ctx, sdk.GetConsumerGroupsSDK(), ent) case *configurationv1alpha1.KongPluginBinding: - entityType = EntityTypePlugin err = updatePlugin(ctx, sdk.GetPluginSDK(), cl, ent) case *configurationv1alpha1.KongUpstream: - entityType = EntityTypeUpstream err = updateUpstream(ctx, sdk.GetUpstreamsSDK(), ent) case *configurationv1alpha1.KongCredentialBasicAuth: - entityType = EntityTypeBasicAuthCredential err = updateKongCredentialBasicAuth(ctx, sdk.GetBasicAuthCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialAPIKey: - entityType = EntityTypeAPIKeyCredential err = updateKongCredentialAPIKey(ctx, sdk.GetAPIKeyCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialACL: - entityType = EntityTypeACLCredential err = updateKongCredentialACL(ctx, sdk.GetACLCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialJWT: - entityType = EntityTypeJWTCredential err = updateKongCredentialJWT(ctx, sdk.GetJWTCredentialsSDK(), ent) case *configurationv1alpha1.KongCredentialHMAC: - entityType = EntityTypeJWTCredential err = updateKongCredentialHMAC(ctx, sdk.GetHMACCredentialsSDK(), ent) case *configurationv1alpha1.KongCACertificate: - entityType = EntityTypeCACertificate err = updateCACertificate(ctx, sdk.GetCACertificatesSDK(), ent) case *configurationv1alpha1.KongCertificate: - entityType = EntityTypeCertificate err = updateCertificate(ctx, sdk.GetCertificatesSDK(), ent) case *configurationv1alpha1.KongTarget: - entityType = EntityTypeTarget err = updateTarget(ctx, sdk.GetTargetsSDK(), ent) case *configurationv1alpha1.KongVault: - entityType = EntityTypeVault err = updateVault(ctx, sdk.GetVaultSDK(), ent) case *configurationv1alpha1.KongKey: - entityType = EntityTypeKey err = updateKey(ctx, sdk.GetKeysSDK(), ent) case *configurationv1alpha1.KongKeySet: - entityType = EntityTypeKeySet err = updateKeySet(ctx, sdk.GetKeySetsSDK(), ent) case *configurationv1alpha1.KongSNI: - entityType = EntityTypeSNI err = updateSNI(ctx, sdk.GetSNIsSDK(), ent) case *configurationv1alpha1.KongDataPlaneClientCertificate: err = nil // DataPlaneCertificates are immutable. @@ -516,15 +432,17 @@ func Update[ if err != nil { metricRecorder.RecordKonnectEntityOperationFailure( + sdk.GetServerURL(), metrics.KonnectEnttiyOperationUpdate, - string(entityType), + entityType, time.Since(start), statusCode, ) } else { metricRecorder.RecordKonnectEntityOperationSuccess( + sdk.GetServerURL(), metrics.KonnectEnttiyOperationUpdate, - string(entityType), + entityType, time.Since(start), ) } diff --git a/controller/konnect/ops/sdk/mocks/sdkfactory_mock.go b/controller/konnect/ops/sdk/mocks/sdkfactory_mock.go index a5714c932..e92752d93 100644 --- a/controller/konnect/ops/sdk/mocks/sdkfactory_mock.go +++ b/controller/konnect/ops/sdk/mocks/sdkfactory_mock.go @@ -62,6 +62,14 @@ func NewMockSDKWrapperWithT(t *testing.T) *MockSDKWrapper { } } +const ( + mockSDKServerURL = "http://mock-api.konnect.test" +) + +func (m MockSDKWrapper) GetServerURL() string { + return mockSDKServerURL +} + func (m MockSDKWrapper) GetControlPlaneSDK() sdkops.ControlPlaneSDK { return m.ControlPlaneSDK } diff --git a/controller/konnect/ops/sdk/sdkfactory.go b/controller/konnect/ops/sdk/sdkfactory.go index 8823b9c99..be48578a9 100644 --- a/controller/konnect/ops/sdk/sdkfactory.go +++ b/controller/konnect/ops/sdk/sdkfactory.go @@ -29,14 +29,23 @@ type SDKWrapper interface { GetKeySetsSDK() KeySetsSDK GetSNIsSDK() SNIsSDK GetDataPlaneCertificatesSDK() DataPlaneClientCertificatesSDK + + // GetServerURL returns the server URL for recording metrics. + GetServerURL() string } type sdkWrapper struct { - sdk *sdkkonnectgo.SDK + serverURL string + sdk *sdkkonnectgo.SDK } var _ SDKWrapper = sdkWrapper{} +// GetServerURL returns the Konnect server URL for recording metrics. +func (w sdkWrapper) GetServerURL() string { + return w.serverURL +} + // GetControlPlaneSDK returns the SDK to operate Konnect control planes. func (w sdkWrapper) GetControlPlaneSDK() ControlPlaneSDK { return w.sdk.ControlPlanes @@ -165,6 +174,7 @@ func NewSDKFactory() SDKFactory { // NewKonnectSDK creates a new Konnect SDK. func (f sdkFactory) NewKonnectSDK(serverURL string, token SDKToken) SDKWrapper { return sdkWrapper{ + serverURL: serverURL, sdk: sdkkonnectgo.New( sdkkonnectgo.WithSecurity( sdkkonnectcomp.Security{ diff --git a/internal/metrics/prometheus.go b/internal/metrics/prometheus.go index c4ea9e2fc..f4e104c17 100644 --- a/internal/metrics/prometheus.go +++ b/internal/metrics/prometheus.go @@ -9,16 +9,16 @@ import ( ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics" ) -// Recorder is the interface fir recording metrics on a certain operation. +// Recorder is the interface for recording metrics for provided operation. type Recorder interface { - // REVIEW: add URL of Konnect API as a label? - RecordKonnectEntityOperationSuccess(operationType KonnectEntityOperation, entityType string, duration time.Duration) - RecordKonnectEntityOperationFailure(operationType KonnectEntityOperation, entityType string, duration time.Duration, statusCode int) + RecordKonnectEntityOperationSuccess(serverURL string, operationType KonnectEntityOperation, entityType string, duration time.Duration) + RecordKonnectEntityOperationFailure(serverURL string, operationType KonnectEntityOperation, entityType string, duration time.Duration, statusCode int) } type KonnectEntityOperation string const ( + KonnectServerURLKey = "server_url" KonnectEntityOperationTypeKey = "operation_type" KonnectEntityOperationCreate KonnectEntityOperation = "create" KonnectEnttiyOperationUpdate KonnectEntityOperation = "update" @@ -35,9 +35,8 @@ const ( // metric names for konnect entity operations. const ( - // REVIEW: define a Namespace `gateway_operator` for creating prometheus metrics here? MetricNameKonnectEntityOperationCount = "gateway_operator_konnect_entity_operation_count" - MetricNameKonnectEntityOperationDuration = "gateway_operator_konnect_entity_operation_duration" + MetricNameKonnectEntityOperationDuration = "gateway_operator_konnect_entity_operation_duration_milliseconds" ) var ( @@ -46,37 +45,45 @@ var ( Name: MetricNameKonnectEntityOperationCount, Help: fmt.Sprintf( "Count of successful/failed entity operations in Konnect. "+ + "`%s` describes the URL of the Konnect server. "+ "`%s` describes the operation type (`%s`, `%s`, or `%s`)."+ "`%s` describes the type of the operated entity. "+ "`%s` describes whether the operation is successful (`%s`) or not (`%s`). "+ - "`%s` is populated in case of `%s=\"%s\"` and describes the status code returned from Konnect API.", + "`%s` is populated in case of `%s=\"%s\"` and describes the status code returned from Konnect API. "+ + "`%s`=\"0\" and %s=\"%s\" means we cannot collect the status code or error happens in the process other than Konnect API call.", + KonnectServerURLKey, KonnectEntityOperationTypeKey, KonnectEntityOperationCreate, KonnectEnttiyOperationUpdate, KonnectEntityOperationDelete, KonnectEntityTypeKey, SuccessKey, SuccessTrue, SuccessFalse, StatusCodeKey, SuccessKey, SuccessFalse, + StatusCodeKey, SuccessKey, SuccessFalse, ), }, - []string{KonnectEntityOperationTypeKey, KonnectEntityTypeKey, SuccessKey, StatusCodeKey}, + []string{KonnectServerURLKey, KonnectEntityOperationTypeKey, KonnectEntityTypeKey, SuccessKey, StatusCodeKey}, ) konnectEntityOperationDuration = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: MetricNameKonnectEntityOperationDuration, Help: fmt.Sprintf( - "How long did the Konnect entity operation take in seconds. "+ + "How long did the Konnect entity operation take in milliseconds. "+ + "`%s` describes the URL of the Konnect server. "+ "`%s` describes the operation type (`%s`, `%s`, or `%s`)."+ "`%s` describes the type of the operated entity. "+ "`%s` describes whether the operation is successful (`%s`) or not (`%s`). "+ - "`%s` is populated in case of `%s=\"%s\"` and describes the status code returned from Konnect API.", + "`%s` is populated in case of `%s=\"%s\"` and describes the status code returned from Konnect API. "+ + "`%s`=\"0\" and %s=\"%s\" means we cannot collect the status code or error happens in the process other than Konnect API call.", + KonnectServerURLKey, KonnectEntityOperationTypeKey, KonnectEntityOperationCreate, KonnectEnttiyOperationUpdate, KonnectEntityOperationDelete, KonnectEntityTypeKey, SuccessKey, SuccessTrue, SuccessFalse, StatusCodeKey, SuccessKey, SuccessFalse, + StatusCodeKey, SuccessKey, SuccessFalse, ), - // Duration range from 0.1s to 10min (600s). - Buckets: prometheus.ExponentialBucketsRange(0.1, 600, 20), + // Duration range from 1ms to 10min. + Buckets: prometheus.ExponentialBucketsRange(1, 10*float64(time.Minute.Milliseconds()), 20), }, - []string{KonnectEntityOperationTypeKey, KonnectEntityTypeKey, SuccessKey, StatusCodeKey}, + []string{KonnectServerURLKey, KonnectEntityOperationTypeKey, KonnectEntityTypeKey, SuccessKey, StatusCodeKey}, ) ) @@ -95,34 +102,36 @@ func NewGlobalCtrlRuntimeMetricsRecorder() *GlobalCtrlRuntimeMetricsRecorder { } func (r *GlobalCtrlRuntimeMetricsRecorder) RecordKonnectEntityOperationSuccess( - operationType KonnectEntityOperation, entityType string, duration time.Duration) { - r.recordKonnectEntityOperationCount(operationType, entityType, true, 0) - r.recordKonnectEntityOperationDuration(operationType, entityType, true, 0, duration) + serverURL string, operationType KonnectEntityOperation, entityType string, duration time.Duration) { + r.recordKonnectEntityOperationCount(serverURL, operationType, entityType, true, 0) + r.recordKonnectEntityOperationDuration(serverURL, operationType, entityType, true, 0, duration) } func (r *GlobalCtrlRuntimeMetricsRecorder) RecordKonnectEntityOperationFailure( - operationType KonnectEntityOperation, entityType string, duration time.Duration, statusCode int) { - r.recordKonnectEntityOperationCount(operationType, entityType, false, statusCode) - r.recordKonnectEntityOperationDuration(operationType, entityType, false, statusCode, duration) + serverURL string, operationType KonnectEntityOperation, entityType string, duration time.Duration, statusCode int) { + r.recordKonnectEntityOperationCount(serverURL, operationType, entityType, false, statusCode) + r.recordKonnectEntityOperationDuration(serverURL, operationType, entityType, false, statusCode, duration) } func (r *GlobalCtrlRuntimeMetricsRecorder) recordKonnectEntityOperationCount( - operationType KonnectEntityOperation, entityType string, success bool, statusCode int, + serverURL string, operationType KonnectEntityOperation, entityType string, success bool, statusCode int, ) { - labels := konnectEntityOperationLabels(operationType, entityType, success, statusCode) + labels := konnectEntityOperationLabels(serverURL, operationType, entityType, success, statusCode) konnectEntityOperationCount.With(labels).Inc() } func (r *GlobalCtrlRuntimeMetricsRecorder) recordKonnectEntityOperationDuration( - operationType KonnectEntityOperation, entityType string, success bool, statusCode int, duration time.Duration, + serverURL string, operationType KonnectEntityOperation, entityType string, success bool, statusCode int, duration time.Duration, ) { - labels := konnectEntityOperationLabels(operationType, entityType, success, statusCode) + labels := konnectEntityOperationLabels(serverURL, operationType, entityType, success, statusCode) konnectEntityOperationDuration.With(labels).Observe(duration.Seconds()) } -func konnectEntityOperationLabels(operationType KonnectEntityOperation, entityType string, success bool, statusCode int, +func konnectEntityOperationLabels( + serverURL string, operationType KonnectEntityOperation, entityType string, success bool, statusCode int, ) prometheus.Labels { labels := prometheus.Labels{ + KonnectServerURLKey: serverURL, KonnectEntityOperationTypeKey: string(operationType), KonnectEntityTypeKey: entityType, } @@ -146,14 +155,16 @@ func init() { } } +// TODO: move all the mocks to a place inside `/test`: +// https://github.com/Kong/gateway-operator/issues/955 type MockRecorder struct{} var _ Recorder = &MockRecorder{} func (m *MockRecorder) RecordKonnectEntityOperationSuccess( - operationType KonnectEntityOperation, entityType string, duration time.Duration) { + serverURL string, operationType KonnectEntityOperation, entityType string, duration time.Duration) { } func (m *MockRecorder) RecordKonnectEntityOperationFailure( - operationType KonnectEntityOperation, entityType string, duration time.Duration, statusCode int) { + serverURL string, operationType KonnectEntityOperation, entityType string, duration time.Duration, statusCode int) { } diff --git a/modules/manager/controller_setup.go b/modules/manager/controller_setup.go index 3cda88b9b..f1810b79c 100644 --- a/modules/manager/controller_setup.go +++ b/modules/manager/controller_setup.go @@ -189,6 +189,8 @@ func setupIndexes(ctx context.Context, mgr manager.Manager, cfg Config) error { // SetupControllers returns a list of ControllerDefs based on config. func SetupControllers(mgr manager.Manager, c *Config) (map[string]ControllerDef, error) { ctx := context.Background() + // metricRecorder is the recorder used to record custom metrics in the controller manager's metrics server. + metricRecorder := metrics.NewGlobalCtrlRuntimeMetricsRecorder() // These checks prevent controller-runtime spamming in logs about failing // to get informer from cache. @@ -509,8 +511,7 @@ func SetupControllers(mgr manager.Manager, c *Config) (map[string]ControllerDef, return nil, err } - // REVIEW: Should we define the recorder here, or define it out of the section to allow setting custom metrics in other controllers? - metricRecorder := metrics.NewGlobalCtrlRuntimeMetricsRecorder() + // REVIEW: Should we define the recorder here, or define it out of the section to allow setting custom metrics in other controllers sdkFactory := sdkops.NewSDKFactory() controllerFactory := konnectControllerFactory{