1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-31 00:16:47 +01:00

fix: measure frontend times only when flag enabled (#6535)

Moving to controller level to measure only for flag. Other option would
have been to check flag also at service.
This commit is contained in:
Jaanus Sellin 2024-03-13 14:28:59 +02:00 committed by GitHub
parent 1aca59747e
commit c4412d8276
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 22 deletions

View File

@ -23,6 +23,8 @@ import rateLimit from 'express-rate-limit';
import { minutesToMilliseconds } from 'date-fns'; import { minutesToMilliseconds } from 'date-fns';
import isEqual from 'lodash.isequal'; import isEqual from 'lodash.isequal';
import { diff } from 'json-diff'; import { diff } from 'json-diff';
import metricsHelper from '../../util/metrics-helper';
import { FUNCTION_TIME } from '../../metric-events';
interface ApiUserRequest< interface ApiUserRequest<
PARAM = any, PARAM = any,
@ -43,11 +45,19 @@ export default class FrontendAPIController extends Controller {
private services: Services; private services: Services;
private timer: Function;
constructor(config: IUnleashConfig, services: Services) { constructor(config: IUnleashConfig, services: Services) {
super(config); super(config);
this.logger = config.getLogger('frontend-api-controller.ts'); this.logger = config.getLogger('frontend-api-controller.ts');
this.services = services; this.services = services;
this.timer = (functionName) =>
metricsHelper.wrapTimer(config.eventBus, FUNCTION_TIME, {
className: 'FrontendAPIController',
functionName,
});
// Support CORS requests for the frontend endpoints. // Support CORS requests for the frontend endpoints.
// Preflight requests are handled in `app.ts`. // Preflight requests are handled in `app.ts`.
this.app.use(corsOriginMiddleware(services, config)); this.app.use(corsOriginMiddleware(services, config));
@ -181,14 +191,8 @@ export default class FrontendAPIController extends Controller {
if (this.config.flagResolver.isEnabled('globalFrontendApiCache')) { if (this.config.flagResolver.isEnabled('globalFrontendApiCache')) {
const context = FrontendAPIController.createContext(req); const context = FrontendAPIController.createContext(req);
[toggles, newToggles] = await Promise.all([ [toggles, newToggles] = await Promise.all([
this.services.frontendApiService.getFrontendApiFeatures( this.getTimedFrontendApiFeatures(req.user, context),
req.user, this.getTimedNewFrontendApiFeatures(req.user, context),
context,
),
this.services.frontendApiService.getNewFrontendApiFeatures(
req.user,
context,
),
]); ]);
const sortedToggles = toggles.sort((a, b) => const sortedToggles = toggles.sort((a, b) =>
a.name.localeCompare(b.name), a.name.localeCompare(b.name),
@ -233,6 +237,28 @@ export default class FrontendAPIController extends Controller {
); );
} }
private async getTimedFrontendApiFeatures(req, context) {
const stopTimer = this.timer('getFrontendApiFeatures');
const features =
await this.services.frontendApiService.getFrontendApiFeatures(
req.user,
context,
);
stopTimer();
return features;
}
private async getTimedNewFrontendApiFeatures(req, context) {
const stopTimer = this.timer('getNewFrontendApiFeatures');
const features =
await this.services.frontendApiService.getNewFrontendApiFeatures(
req.user,
context,
);
stopTimer();
return features;
}
private async registerFrontendApiMetrics( private async registerFrontendApiMetrics(
req: ApiUserRequest<unknown, unknown, ClientMetricsSchema>, req: ApiUserRequest<unknown, unknown, ClientMetricsSchema>,
res: Response, res: Response,

View File

@ -16,14 +16,12 @@ import {
import { validateOrigins } from '../../util'; import { validateOrigins } from '../../util';
import { BadDataError, InvalidTokenError } from '../../error'; import { BadDataError, InvalidTokenError } from '../../error';
import { import {
FUNCTION_TIME,
FRONTEND_API_REPOSITORY_CREATED, FRONTEND_API_REPOSITORY_CREATED,
PROXY_REPOSITORY_CREATED, PROXY_REPOSITORY_CREATED,
} from '../../metric-events'; } from '../../metric-events';
import { FrontendApiRepository } from './frontend-api-repository'; import { FrontendApiRepository } from './frontend-api-repository';
import { GlobalFrontendApiCache } from './global-frontend-api-cache'; import { GlobalFrontendApiCache } from './global-frontend-api-cache';
import { ProxyRepository } from './proxy-repository'; import { ProxyRepository } from './proxy-repository';
import metricsHelper from '../../util/metrics-helper';
export type Config = Pick< export type Config = Pick<
IUnleashConfig, IUnleashConfig,
@ -63,8 +61,6 @@ export class FrontendApiService {
private cachedFrontendSettings?: FrontendSettings; private cachedFrontendSettings?: FrontendSettings;
private timer: Function;
constructor( constructor(
config: Config, config: Config,
stores: Stores, stores: Stores,
@ -76,19 +72,12 @@ export class FrontendApiService {
this.stores = stores; this.stores = stores;
this.services = services; this.services = services;
this.globalFrontendApiCache = globalFrontendApiCache; this.globalFrontendApiCache = globalFrontendApiCache;
this.timer = (functionName) =>
metricsHelper.wrapTimer(config.eventBus, FUNCTION_TIME, {
className: 'FrontendApiService',
functionName,
});
} }
async getFrontendApiFeatures( async getFrontendApiFeatures(
token: IApiUser, token: IApiUser,
context: Context, context: Context,
): Promise<FrontendApiFeatureSchema[]> { ): Promise<FrontendApiFeatureSchema[]> {
const stopTimer = this.timer('getFrontendApiFeatures');
const client = await this.clientForFrontendApiToken(token); const client = await this.clientForFrontendApiToken(token);
const definitions = client.getFeatureToggleDefinitions() || []; const definitions = client.getFeatureToggleDefinitions() || [];
const sessionId = context.sessionId || String(Math.random()); const sessionId = context.sessionId || String(Math.random());
@ -109,7 +98,6 @@ export class FrontendApiService {
}), }),
impressionData: Boolean(feature.impressionData), impressionData: Boolean(feature.impressionData),
})); }));
stopTimer();
return resultDefinitions; return resultDefinitions;
} }
@ -117,7 +105,6 @@ export class FrontendApiService {
token: IApiUser, token: IApiUser,
context: Context, context: Context,
): Promise<FrontendApiFeatureSchema[]> { ): Promise<FrontendApiFeatureSchema[]> {
const stopTimer = this.timer('getNewFrontendApiFeatures');
const client = await this.newClientForFrontendApiToken(token); const client = await this.newClientForFrontendApiToken(token);
const definitions = client.getFeatureToggleDefinitions() || []; const definitions = client.getFeatureToggleDefinitions() || [];
const sessionId = context.sessionId || String(Math.random()); const sessionId = context.sessionId || String(Math.random());
@ -139,7 +126,6 @@ export class FrontendApiService {
}), }),
impressionData: Boolean(feature.impressionData), impressionData: Boolean(feature.impressionData),
})); }));
stopTimer();
return resultDefinitions; return resultDefinitions;
} }