diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index 8ce2f89d7d..778a78c7af 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -81,6 +81,7 @@ exports[`should create default config 1`] = ` "disableBulkToggle": false, "disableMetrics": false, "disableNotifications": false, + "edgeBulkMetricsKillSwitch": false, "embedProxy": true, "embedProxyFrontend": true, "enableLicense": false, diff --git a/src/lib/routes/edge-api/index.ts b/src/lib/routes/edge-api/index.ts index 4141dcd34d..be0864236f 100644 --- a/src/lib/routes/edge-api/index.ts +++ b/src/lib/routes/edge-api/index.ts @@ -1,6 +1,6 @@ import { Response } from 'express'; import Controller from '../controller'; -import { IUnleashConfig, IUnleashServices } from '../../types'; +import { IFlagResolver, IUnleashConfig, IUnleashServices } from '../../types'; import { Logger } from '../../logger'; import { NONE } from '../../types/permissions'; import { createResponseSchema } from '../../openapi/util/create-response-schema'; @@ -33,6 +33,8 @@ export default class EdgeController extends Controller { private clientInstanceService: ClientInstanceService; + private flagResolver: IFlagResolver; + constructor( config: IUnleashConfig, { @@ -54,6 +56,7 @@ export default class EdgeController extends Controller { this.openApiService = openApiService; this.metricsV2 = clientMetricsServiceV2; this.clientInstanceService = clientInstanceService; + this.flagResolver = config.flagResolver; this.route({ method: 'post', @@ -115,25 +118,37 @@ export default class EdgeController extends Controller { req: IAuthRequest, res: Response, ): Promise { - const { body, ip: clientIp } = req; - const { metrics, applications } = body; + if (!this.flagResolver.isEnabled('edgeBulkMetricsKillSwitch')) { + const { body, ip: clientIp } = req; + const { metrics, applications } = body; - try { - const promises: Promise[] = []; - for (const app of applications) { - promises.push( - this.clientInstanceService.registerClient(app, clientIp), - ); + try { + const promises: Promise[] = []; + for (const app of applications) { + promises.push( + this.clientInstanceService.registerClient( + app, + clientIp, + ), + ); + } + if (metrics && metrics.length > 0) { + const data = + await clientMetricsEnvBulkSchema.validateAsync(metrics); + promises.push(this.metricsV2.registerBulkMetrics(data)); + } + await Promise.all(promises); + res.status(202).end(); + } catch (e) { + res.status(400).end(); } - if (metrics && metrics.length > 0) { - const data = - await clientMetricsEnvBulkSchema.validateAsync(metrics); - promises.push(this.metricsV2.registerBulkMetrics(data)); - } - await Promise.all(promises); - res.status(202).end(); - } catch (e) { - res.status(400).end(); + } else { + // @ts-expect-error Expected result here is void, but since we want to communicate extra information in our 404, we allow this to avoid type-checking + res.status(404).json({ + status: 'disabled', + reason: 'disabled by killswitch', + help: 'You should upgrade Edge to the most recent version to not lose metrics', + }); } } } diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index cf72291c4b..96d62bb383 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -37,7 +37,8 @@ export type IFlagKey = | 'increaseUnleashWidth' | 'featureSearchFeedback' | 'featureSearchFeedbackPosting' - | 'newStrategyConfigurationFeedback'; + | 'newStrategyConfigurationFeedback' + | 'edgeBulkMetricsKillSwitch'; export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>; @@ -168,6 +169,10 @@ const flags: IFlags = { process.env.UNLEASH_EXPERIMENTAL_NEW_STRATEGY_CONFIGURATION_FEEDBACK, false, ), + edgeBulkMetricsKillSwitch: parseEnvVarBoolean( + process.env.UNLEASH_EXPERIMENTAL_EDGE_BULK_METRICS_KILL_SWITCH, + false, + ), }; export const defaultExperimentalOptions: IExperimentalOptions = {