mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: store memory footprints to grafana (#9001)
When there is new revision, we will start storing memory footprint for old client-api and the new delta-api. We will be sending it as prometheus metrics. The memory size will only be recalculated if revision changes, which does not happen very often.
This commit is contained in:
		
							parent
							
								
									3bed01bb8c
								
							
						
					
					
						commit
						b701fec75d
					
				@ -35,6 +35,7 @@ import {
 | 
				
			|||||||
import type ConfigurationRevisionService from '../feature-toggle/configuration-revision-service';
 | 
					import type ConfigurationRevisionService from '../feature-toggle/configuration-revision-service';
 | 
				
			||||||
import type { ClientFeatureToggleService } from './client-feature-toggle-service';
 | 
					import type { ClientFeatureToggleService } from './client-feature-toggle-service';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 | 
					    CLIENT_FEATURES_MEMORY,
 | 
				
			||||||
    CLIENT_METRICS_NAMEPREFIX,
 | 
					    CLIENT_METRICS_NAMEPREFIX,
 | 
				
			||||||
    CLIENT_METRICS_TAGS,
 | 
					    CLIENT_METRICS_TAGS,
 | 
				
			||||||
} from '../../internals';
 | 
					} from '../../internals';
 | 
				
			||||||
@ -69,6 +70,8 @@ export default class FeatureController extends Controller {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private eventBus: EventEmitter;
 | 
					    private eventBus: EventEmitter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private clientFeaturesCacheMap = new Map<string, number>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private featuresAndSegments: (
 | 
					    private featuresAndSegments: (
 | 
				
			||||||
        query: IFeatureToggleQuery,
 | 
					        query: IFeatureToggleQuery,
 | 
				
			||||||
        etag: string,
 | 
					        etag: string,
 | 
				
			||||||
@ -162,6 +165,32 @@ export default class FeatureController extends Controller {
 | 
				
			|||||||
    private async resolveFeaturesAndSegments(
 | 
					    private async resolveFeaturesAndSegments(
 | 
				
			||||||
        query?: IFeatureToggleQuery,
 | 
					        query?: IFeatureToggleQuery,
 | 
				
			||||||
    ): Promise<[FeatureConfigurationClient[], IClientSegment[]]> {
 | 
					    ): Promise<[FeatureConfigurationClient[], IClientSegment[]]> {
 | 
				
			||||||
 | 
					        if (this.flagResolver.isEnabled('deltaApi')) {
 | 
				
			||||||
 | 
					            const features =
 | 
				
			||||||
 | 
					                await this.clientFeatureToggleService.getClientFeatures(query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const segments =
 | 
				
			||||||
 | 
					                await this.clientFeatureToggleService.getActiveSegmentsForClient();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                const featuresSize = this.getCacheSizeInBytes(features);
 | 
				
			||||||
 | 
					                const segmentsSize = this.getCacheSizeInBytes(segments);
 | 
				
			||||||
 | 
					                this.clientFeaturesCacheMap.set(
 | 
				
			||||||
 | 
					                    JSON.stringify(query),
 | 
				
			||||||
 | 
					                    featuresSize + segmentsSize,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                await this.clientFeatureToggleService.getClientDelta(
 | 
				
			||||||
 | 
					                    undefined,
 | 
				
			||||||
 | 
					                    query!,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                this.storeFootprint();
 | 
				
			||||||
 | 
					            } catch (e) {
 | 
				
			||||||
 | 
					                this.logger.error('Delta diff failed', e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return [features, segments];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        return Promise.all([
 | 
					        return Promise.all([
 | 
				
			||||||
            this.clientFeatureToggleService.getClientFeatures(query),
 | 
					            this.clientFeatureToggleService.getClientFeatures(query),
 | 
				
			||||||
            this.clientFeatureToggleService.getActiveSegmentsForClient(),
 | 
					            this.clientFeatureToggleService.getActiveSegmentsForClient(),
 | 
				
			||||||
@ -270,7 +299,6 @@ export default class FeatureController extends Controller {
 | 
				
			|||||||
            query,
 | 
					            query,
 | 
				
			||||||
            etag,
 | 
					            etag,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (this.clientSpecService.requestSupportsSpec(req, 'segments')) {
 | 
					        if (this.clientSpecService.requestSupportsSpec(req, 'segments')) {
 | 
				
			||||||
            this.openApiService.respondWithValidation(
 | 
					            this.openApiService.respondWithValidation(
 | 
				
			||||||
                200,
 | 
					                200,
 | 
				
			||||||
@ -335,4 +363,17 @@ export default class FeatureController extends Controller {
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    storeFootprint() {
 | 
				
			||||||
 | 
					        let memory = 0;
 | 
				
			||||||
 | 
					        for (const value of this.clientFeaturesCacheMap.values()) {
 | 
				
			||||||
 | 
					            memory += value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.eventBus.emit(CLIENT_FEATURES_MEMORY, { memory });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getCacheSizeInBytes(value: any): number {
 | 
				
			||||||
 | 
					        const jsonString = JSON.stringify(value);
 | 
				
			||||||
 | 
					        return Buffer.byteLength(jsonString, 'utf8');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ import type {
 | 
				
			|||||||
    IFeatureToggleQuery,
 | 
					    IFeatureToggleQuery,
 | 
				
			||||||
    IFlagResolver,
 | 
					    IFlagResolver,
 | 
				
			||||||
    ISegmentReadModel,
 | 
					    ISegmentReadModel,
 | 
				
			||||||
 | 
					    IUnleashConfig,
 | 
				
			||||||
} from '../../../types';
 | 
					} from '../../../types';
 | 
				
			||||||
import type ConfigurationRevisionService from '../../feature-toggle/configuration-revision-service';
 | 
					import type ConfigurationRevisionService from '../../feature-toggle/configuration-revision-service';
 | 
				
			||||||
import { UPDATE_REVISION } from '../../feature-toggle/configuration-revision-service';
 | 
					import { UPDATE_REVISION } from '../../feature-toggle/configuration-revision-service';
 | 
				
			||||||
@ -13,6 +14,9 @@ import type {
 | 
				
			|||||||
    FeatureConfigurationDeltaClient,
 | 
					    FeatureConfigurationDeltaClient,
 | 
				
			||||||
    IClientFeatureToggleDeltaReadModel,
 | 
					    IClientFeatureToggleDeltaReadModel,
 | 
				
			||||||
} from './client-feature-toggle-delta-read-model-type';
 | 
					} from './client-feature-toggle-delta-read-model-type';
 | 
				
			||||||
 | 
					import { CLIENT_DELTA_MEMORY } from '../../../metric-events';
 | 
				
			||||||
 | 
					import type EventEmitter from 'events';
 | 
				
			||||||
 | 
					import type { Logger } from '../../../logger';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DeletedFeature = {
 | 
					type DeletedFeature = {
 | 
				
			||||||
    name: string;
 | 
					    name: string;
 | 
				
			||||||
@ -86,7 +90,6 @@ export const calculateRequiredClientRevision = (
 | 
				
			|||||||
    const targetedRevisions = revisions.filter(
 | 
					    const targetedRevisions = revisions.filter(
 | 
				
			||||||
        (revision) => revision.revisionId > requiredRevisionId,
 | 
					        (revision) => revision.revisionId > requiredRevisionId,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    console.log('targeted revisions', targetedRevisions);
 | 
					 | 
				
			||||||
    const projectFeatureRevisions = targetedRevisions.map((revision) =>
 | 
					    const projectFeatureRevisions = targetedRevisions.map((revision) =>
 | 
				
			||||||
        filterRevisionByProject(revision, projects),
 | 
					        filterRevisionByProject(revision, projects),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
@ -105,20 +108,23 @@ export class ClientFeatureToggleDelta {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private currentRevisionId: number = 0;
 | 
					    private currentRevisionId: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private interval: NodeJS.Timer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private flagResolver: IFlagResolver;
 | 
					    private flagResolver: IFlagResolver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private configurationRevisionService: ConfigurationRevisionService;
 | 
					    private configurationRevisionService: ConfigurationRevisionService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly segmentReadModel: ISegmentReadModel;
 | 
					    private readonly segmentReadModel: ISegmentReadModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private eventBus: EventEmitter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly logger: Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        clientFeatureToggleDeltaReadModel: IClientFeatureToggleDeltaReadModel,
 | 
					        clientFeatureToggleDeltaReadModel: IClientFeatureToggleDeltaReadModel,
 | 
				
			||||||
        segmentReadModel: ISegmentReadModel,
 | 
					        segmentReadModel: ISegmentReadModel,
 | 
				
			||||||
        eventStore: IEventStore,
 | 
					        eventStore: IEventStore,
 | 
				
			||||||
        configurationRevisionService: ConfigurationRevisionService,
 | 
					        configurationRevisionService: ConfigurationRevisionService,
 | 
				
			||||||
        flagResolver: IFlagResolver,
 | 
					        flagResolver: IFlagResolver,
 | 
				
			||||||
 | 
					        config: IUnleashConfig,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        this.eventStore = eventStore;
 | 
					        this.eventStore = eventStore;
 | 
				
			||||||
        this.configurationRevisionService = configurationRevisionService;
 | 
					        this.configurationRevisionService = configurationRevisionService;
 | 
				
			||||||
@ -126,6 +132,8 @@ export class ClientFeatureToggleDelta {
 | 
				
			|||||||
            clientFeatureToggleDeltaReadModel;
 | 
					            clientFeatureToggleDeltaReadModel;
 | 
				
			||||||
        this.flagResolver = flagResolver;
 | 
					        this.flagResolver = flagResolver;
 | 
				
			||||||
        this.segmentReadModel = segmentReadModel;
 | 
					        this.segmentReadModel = segmentReadModel;
 | 
				
			||||||
 | 
					        this.eventBus = config.eventBus;
 | 
				
			||||||
 | 
					        this.logger = config.getLogger('delta/client-feature-toggle-delta.js');
 | 
				
			||||||
        this.onUpdateRevisionEvent = this.onUpdateRevisionEvent.bind(this);
 | 
					        this.onUpdateRevisionEvent = this.onUpdateRevisionEvent.bind(this);
 | 
				
			||||||
        this.delta = {};
 | 
					        this.delta = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -161,6 +169,8 @@ export class ClientFeatureToggleDelta {
 | 
				
			|||||||
            await this.updateSegments();
 | 
					            await this.updateSegments();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: 19.12 this logic seems to be not logical, when no revisionId is coming, it should not go to db, but take latest from cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Should get the latest state if revision does not exist or if sdkRevision is not present
 | 
					        // Should get the latest state if revision does not exist or if sdkRevision is not present
 | 
				
			||||||
        // We should be able to do this without going to the database by merging revisions from the delta with
 | 
					        // We should be able to do this without going to the database by merging revisions from the delta with
 | 
				
			||||||
        // the base case
 | 
					        // the base case
 | 
				
			||||||
@ -203,12 +213,13 @@ export class ClientFeatureToggleDelta {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private async onUpdateRevisionEvent() {
 | 
					    private async onUpdateRevisionEvent() {
 | 
				
			||||||
        if (this.flagResolver.isEnabled('deltaApi')) {
 | 
					        if (this.flagResolver.isEnabled('deltaApi')) {
 | 
				
			||||||
            await this.listenToRevisionChange();
 | 
					            await this.updateFeaturesDelta();
 | 
				
			||||||
            await this.updateSegments();
 | 
					            await this.updateSegments();
 | 
				
			||||||
 | 
					            this.storeFootprint();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async listenToRevisionChange() {
 | 
					    public async updateFeaturesDelta() {
 | 
				
			||||||
        const keys = Object.keys(this.delta);
 | 
					        const keys = Object.keys(this.delta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (keys.length === 0) return;
 | 
					        if (keys.length === 0) return;
 | 
				
			||||||
@ -248,7 +259,6 @@ export class ClientFeatureToggleDelta {
 | 
				
			|||||||
                removed,
 | 
					                removed,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.currentRevisionId = latestRevision;
 | 
					        this.currentRevisionId = latestRevision;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -279,8 +289,9 @@ export class ClientFeatureToggleDelta {
 | 
				
			|||||||
                removed: [],
 | 
					                removed: [],
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.delta[environment] = delta;
 | 
					        this.delta[environment] = delta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.storeFootprint();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async getClientFeatures(
 | 
					    async getClientFeatures(
 | 
				
			||||||
@ -294,4 +305,20 @@ export class ClientFeatureToggleDelta {
 | 
				
			|||||||
    private async updateSegments(): Promise<void> {
 | 
					    private async updateSegments(): Promise<void> {
 | 
				
			||||||
        this.segments = await this.segmentReadModel.getActiveForClient();
 | 
					        this.segments = await this.segmentReadModel.getActiveForClient();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    storeFootprint() {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            const featuresMemory = this.getCacheSizeInBytes(this.delta);
 | 
				
			||||||
 | 
					            const segmentsMemory = this.getCacheSizeInBytes(this.segments);
 | 
				
			||||||
 | 
					            const memory = featuresMemory + segmentsMemory;
 | 
				
			||||||
 | 
					            this.eventBus.emit(CLIENT_DELTA_MEMORY, { memory });
 | 
				
			||||||
 | 
					        } catch (e) {
 | 
				
			||||||
 | 
					            this.logger.error('Client delta footprint error', e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getCacheSizeInBytes(value: any): number {
 | 
				
			||||||
 | 
					        const jsonString = JSON.stringify(value);
 | 
				
			||||||
 | 
					        return Buffer.byteLength(jsonString, 'utf8');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@ export const createClientFeatureToggleDelta = (
 | 
				
			|||||||
        eventStore,
 | 
					        eventStore,
 | 
				
			||||||
        configurationRevisionService,
 | 
					        configurationRevisionService,
 | 
				
			||||||
        flagResolver,
 | 
					        flagResolver,
 | 
				
			||||||
 | 
					        config,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return clientFeatureToggleDelta;
 | 
					    return clientFeatureToggleDelta;
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ export class RevisionDelta {
 | 
				
			|||||||
    private delta: Revision[];
 | 
					    private delta: Revision[];
 | 
				
			||||||
    private maxLength: number;
 | 
					    private maxLength: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(data: Revision[] = [], maxLength: number = 100) {
 | 
					    constructor(data: Revision[] = [], maxLength: number = 20) {
 | 
				
			||||||
        this.delta = data;
 | 
					        this.delta = data;
 | 
				
			||||||
        this.maxLength = maxLength;
 | 
					        this.maxLength = maxLength;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,8 @@ const REQUEST_ORIGIN = 'request_origin' as const;
 | 
				
			|||||||
const ADDON_EVENTS_HANDLED = 'addon-event-handled' as const;
 | 
					const ADDON_EVENTS_HANDLED = 'addon-event-handled' as const;
 | 
				
			||||||
const CLIENT_METRICS_NAMEPREFIX = 'client-api-nameprefix';
 | 
					const CLIENT_METRICS_NAMEPREFIX = 'client-api-nameprefix';
 | 
				
			||||||
const CLIENT_METRICS_TAGS = 'client-api-tags';
 | 
					const CLIENT_METRICS_TAGS = 'client-api-tags';
 | 
				
			||||||
 | 
					const CLIENT_FEATURES_MEMORY = 'client_features_memory';
 | 
				
			||||||
 | 
					const CLIENT_DELTA_MEMORY = 'client_delta_memory';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MetricEvent =
 | 
					type MetricEvent =
 | 
				
			||||||
    | typeof REQUEST_TIME
 | 
					    | typeof REQUEST_TIME
 | 
				
			||||||
@ -32,7 +34,9 @@ type MetricEvent =
 | 
				
			|||||||
    | typeof EXCEEDS_LIMIT
 | 
					    | typeof EXCEEDS_LIMIT
 | 
				
			||||||
    | typeof REQUEST_ORIGIN
 | 
					    | typeof REQUEST_ORIGIN
 | 
				
			||||||
    | typeof CLIENT_METRICS_NAMEPREFIX
 | 
					    | typeof CLIENT_METRICS_NAMEPREFIX
 | 
				
			||||||
    | typeof CLIENT_METRICS_TAGS;
 | 
					    | typeof CLIENT_METRICS_TAGS
 | 
				
			||||||
 | 
					    | typeof CLIENT_FEATURES_MEMORY
 | 
				
			||||||
 | 
					    | typeof CLIENT_DELTA_MEMORY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type RequestOriginEventPayload = {
 | 
					type RequestOriginEventPayload = {
 | 
				
			||||||
    type: 'UI' | 'API';
 | 
					    type: 'UI' | 'API';
 | 
				
			||||||
@ -82,6 +86,8 @@ export {
 | 
				
			|||||||
    ADDON_EVENTS_HANDLED,
 | 
					    ADDON_EVENTS_HANDLED,
 | 
				
			||||||
    CLIENT_METRICS_NAMEPREFIX,
 | 
					    CLIENT_METRICS_NAMEPREFIX,
 | 
				
			||||||
    CLIENT_METRICS_TAGS,
 | 
					    CLIENT_METRICS_TAGS,
 | 
				
			||||||
 | 
					    CLIENT_FEATURES_MEMORY,
 | 
				
			||||||
 | 
					    CLIENT_DELTA_MEMORY,
 | 
				
			||||||
    type MetricEvent,
 | 
					    type MetricEvent,
 | 
				
			||||||
    type MetricEventPayload,
 | 
					    type MetricEventPayload,
 | 
				
			||||||
    emitMetricEvent,
 | 
					    emitMetricEvent,
 | 
				
			||||||
 | 
				
			|||||||
@ -624,6 +624,16 @@ export function registerPrometheusMetrics(
 | 
				
			|||||||
        help: 'Number of API tokens without a project',
 | 
					        help: 'Number of API tokens without a project',
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const clientFeaturesMemory = createGauge({
 | 
				
			||||||
 | 
					        name: 'client_features_memory',
 | 
				
			||||||
 | 
					        help: 'The amount of memory client features endpoint is using for caching',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const clientDeltaMemory = createGauge({
 | 
				
			||||||
 | 
					        name: 'client_delta_memory',
 | 
				
			||||||
 | 
					        help: 'The amount of memory client features delta endpoint is using for caching',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const orphanedTokensActive = createGauge({
 | 
					    const orphanedTokensActive = createGauge({
 | 
				
			||||||
        name: 'orphaned_api_tokens_active',
 | 
					        name: 'orphaned_api_tokens_active',
 | 
				
			||||||
        help: 'Number of API tokens without a project, last seen within 3 months',
 | 
					        help: 'Number of API tokens without a project, last seen within 3 months',
 | 
				
			||||||
@ -752,6 +762,16 @@ export function registerPrometheusMetrics(
 | 
				
			|||||||
        tagsUsed.inc();
 | 
					        tagsUsed.inc();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eventBus.on(events.CLIENT_FEATURES_MEMORY, (event: { memory: number }) => {
 | 
				
			||||||
 | 
					        clientFeaturesMemory.reset();
 | 
				
			||||||
 | 
					        clientFeaturesMemory.set(event.memory);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    eventBus.on(events.CLIENT_DELTA_MEMORY, (event: { memory: number }) => {
 | 
				
			||||||
 | 
					        clientDeltaMemory.reset();
 | 
				
			||||||
 | 
					        clientDeltaMemory.set(event.memory);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    events.onMetricEvent(
 | 
					    events.onMetricEvent(
 | 
				
			||||||
        eventBus,
 | 
					        eventBus,
 | 
				
			||||||
        events.REQUEST_ORIGIN,
 | 
					        events.REQUEST_ORIGIN,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user