diff --git a/src/lib/metric-events.ts b/src/lib/metric-events.ts index fa8f9da344..bd17408139 100644 --- a/src/lib/metric-events.ts +++ b/src/lib/metric-events.ts @@ -1,6 +1,7 @@ const REQUEST_TIME = 'request_time'; const DB_TIME = 'db_time'; const SCHEDULER_JOB_TIME = 'scheduler_job_time'; +const FRONTEND_API_TIME = 'frontend_api_time'; const FEATURES_CREATED_BY_PROCESSED = 'features_created_by_processed'; const EVENTS_CREATED_BY_PROCESSED = 'events_created_by_processed'; const PROXY_REPOSITORY_CREATED = 'proxy_repository_created'; @@ -10,6 +11,7 @@ export { REQUEST_TIME, DB_TIME, SCHEDULER_JOB_TIME, + FRONTEND_API_TIME, FEATURES_CREATED_BY_PROCESSED, EVENTS_CREATED_BY_PROCESSED, PROXY_REPOSITORY_CREATED, diff --git a/src/lib/metrics.ts b/src/lib/metrics.ts index fcf154c1f6..cbcab49fcc 100644 --- a/src/lib/metrics.ts +++ b/src/lib/metrics.ts @@ -77,6 +77,14 @@ export default class MetricsMonitor { maxAgeSeconds: 600, ageBuckets: 5, }); + const frontendApiEvaluationDuration = createSummary({ + name: 'frontend_api_duration_seconds', + help: 'Frontend API evaluation duration time', + labelNames: ['action'], + percentiles: [0.1, 0.5, 0.9, 0.95, 0.99], + maxAgeSeconds: 600, + ageBuckets: 5, + }); const dbDuration = createSummary({ name: 'db_query_duration_seconds', help: 'DB query duration time', @@ -401,6 +409,10 @@ export default class MetricsMonitor { schedulerDuration.labels(jobId).observe(time); }); + eventBus.on(events.FRONTEND_API_TIME, ({ action, time }) => { + frontendApiEvaluationDuration.labels(action).observe(time); + }); + eventBus.on(events.EVENTS_CREATED_BY_PROCESSED, ({ updated }) => { eventCreatedByMigration.inc(updated); }); diff --git a/src/lib/services/proxy-service.ts b/src/lib/services/proxy-service.ts index fb6d2f55bf..5338708391 100644 --- a/src/lib/services/proxy-service.ts +++ b/src/lib/services/proxy-service.ts @@ -16,7 +16,8 @@ import { } from '../types/settings/frontend-settings'; import { validateOrigins } from '../util'; import { BadDataError, InvalidTokenError } from '../error'; -import { PROXY_REPOSITORY_CREATED } from '../metric-events'; +import { FRONTEND_API_TIME, PROXY_REPOSITORY_CREATED } from '../metric-events'; +import metricsHelper from '../util/metrics-helper'; type Config = Pick< IUnleashConfig, @@ -45,6 +46,8 @@ export class ProxyService { private readonly services: Services; + private readonly timer: Function; + /** * This is intentionally a Promise becasue we want to be able to await * until the client (which might be being created by a different request) is ready @@ -60,6 +63,10 @@ export class ProxyService { this.logger = config.getLogger('services/proxy-service.ts'); this.stores = stores; this.services = services; + this.timer = (action) => + metricsHelper.wrapTimer(config.eventBus, FRONTEND_API_TIME, { + action, + }); } async getProxyFeatures( @@ -67,11 +74,12 @@ export class ProxyService { context: Context, ): Promise { const client = await this.clientForProxyToken(token); + + const stopTimer = this.timer('evaluateEnabledFeatures'); + const definitions = client.getFeatureToggleDefinitions() || []; - const sessionId = context.sessionId || String(Math.random()); - - return definitions + const enabledFeatures = definitions .filter((feature) => client.isEnabled(feature.name, { ...context, sessionId }), ) @@ -84,6 +92,10 @@ export class ProxyService { }), impressionData: Boolean(feature.impressionData), })); + + stopTimer(); + + return enabledFeatures; } async registerProxyMetrics(