From e99487095c2e1c115d0a0726d801e659686fc140 Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Fri, 12 Apr 2024 12:01:50 +0530 Subject: [PATCH 1/9] Add context property to Metric model and update CRUD operations --- .../controllers/ExperimentClientController.ts | 2 +- .../ExperimentClientController.v1.ts | 2 +- .../ExperimentClientController.v4.ts | 2 +- .../ExperimentClientController.v5.ts | 2 +- .../src/api/controllers/MetricController.ts | 31 ++++++++++++++++-- .../controllers/validators/MetricValidator.ts | 32 +++++++++++++------ .../packages/Upgrade/src/api/models/Metric.ts | 3 ++ .../src/api/repositories/MetricRepository.ts | 10 ++++++ .../Upgrade/src/api/services/MetricService.ts | 25 ++++++++++++--- .../1712553037665-contextInMetric.ts | 13 ++++++++ 10 files changed, 102 insertions(+), 20 deletions(-) create mode 100644 backend/packages/Upgrade/src/database/migrations/1712553037665-contextInMetric.ts diff --git a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.ts b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.ts index 0ffd73e75c..04f3cd0f3b 100644 --- a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.ts +++ b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.ts @@ -884,7 +884,7 @@ export class ExperimentClientController { @Body({ validate: false }) metric: MetricValidator ): Promise { - return await this.metricService.saveAllMetrics(metric.metricUnit, request.logger); + return await this.metricService.saveAllMetrics(metric.metricUnit, metric.context, request.logger); } /** diff --git a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v1.ts b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v1.ts index ec2fd99b36..982d2be29d 100644 --- a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v1.ts +++ b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v1.ts @@ -851,7 +851,7 @@ export class ExperimentClientController { @Body({ validate: false }) metric: MetricValidator ): Promise { - return await this.metricService.saveAllMetrics(metric.metricUnit, request.logger); + return await this.metricService.saveAllMetrics(metric.metricUnit, metric.context, request.logger); } /** diff --git a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v4.ts b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v4.ts index 9adcc25247..c5bf4489ca 100644 --- a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v4.ts +++ b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v4.ts @@ -813,7 +813,7 @@ export class ExperimentClientController { @Body({ validate: false }) metric: MetricValidator ): Promise { - return await this.metricService.saveAllMetrics(metric.metricUnit, request.logger); + return await this.metricService.saveAllMetrics(metric.metricUnit, metric.context, request.logger); } /** diff --git a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v5.ts b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v5.ts index 5b89a616f5..1e4e5aeb6e 100644 --- a/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v5.ts +++ b/backend/packages/Upgrade/src/api/controllers/ExperimentClientController.v5.ts @@ -770,7 +770,7 @@ export class ExperimentClientController { @Body({ validate: true }) metric: MetricValidator ): Promise { - return await this.metricService.saveAllMetrics(metric.metricUnit, request.logger); + return await this.metricService.saveAllMetrics(metric.metricUnit, metric.context, request.logger); } /** diff --git a/backend/packages/Upgrade/src/api/controllers/MetricController.ts b/backend/packages/Upgrade/src/api/controllers/MetricController.ts index 6638b35249..0fe22e59d1 100644 --- a/backend/packages/Upgrade/src/api/controllers/MetricController.ts +++ b/backend/packages/Upgrade/src/api/controllers/MetricController.ts @@ -1,6 +1,6 @@ import { Authorized, JsonController, Get, Delete, Param, Post, Req, Body } from 'routing-controllers'; import { MetricService } from '../services/MetricService'; -import { IMetricUnit, SERVER_ERROR, } from 'upgrade_types'; +import { IMetricUnit, SERVER_ERROR } from 'upgrade_types'; import { AppRequest } from '../../types'; import { MetricValidator } from './validators/MetricValidator'; @@ -33,6 +33,33 @@ export class MetricController { return this.metricService.getAllMetrics(request.logger); } + /** + * @swagger + * /metric/{context}: + * get: + * description: Get all metrics with context + * parameters: + * - in: path + * name: context + * required: true + * schema: + * type: string + * description: context + * tags: + * - Metrics + * produces: + * - application/json + * responses: + * '200': + * description: Get all metrics with context + * '404': + * description: Context not found + */ + @Get('/:context') + public getMetricsByContext(@Param('context') context: string, @Req() request: AppRequest): Promise { + return this.metricService.getMetricsByContext(context, request.logger); + } + /** * @swagger * /metric/save: @@ -75,7 +102,7 @@ export class MetricController { @Body({ validate: true }) metric: MetricValidator, @Req() request: AppRequest ): Promise { - return this.metricService.upsertAllMetrics(metric.metricUnit, request.logger); + return this.metricService.upsertAllMetrics(metric.metricUnit, metric.context, request.logger); } /** diff --git a/backend/packages/Upgrade/src/api/controllers/validators/MetricValidator.ts b/backend/packages/Upgrade/src/api/controllers/validators/MetricValidator.ts index da3fca338a..93fa670962 100644 --- a/backend/packages/Upgrade/src/api/controllers/validators/MetricValidator.ts +++ b/backend/packages/Upgrade/src/api/controllers/validators/MetricValidator.ts @@ -1,4 +1,13 @@ -import { IsArray, IsEnum, IsNotEmpty, IsOptional, IsString, ValidateNested, ValidationOptions, registerDecorator } from 'class-validator'; +import { + IsArray, + IsEnum, + IsNotEmpty, + IsOptional, + IsString, + ValidateNested, + ValidationOptions, + registerDecorator, +} from 'class-validator'; import { IMetricMetaData } from 'upgrade_types'; const IsMetricUnit = (validationOptions?: ValidationOptions) => { @@ -14,7 +23,7 @@ const IsMetricUnit = (validationOptions?: ValidationOptions) => { }, validator: { validate(value: any) { - return validateMetricUnit(value) + return validateMetricUnit(value); }, }, }); @@ -23,11 +32,11 @@ const IsMetricUnit = (validationOptions?: ValidationOptions) => { function validateMetricUnit(data: unknown) { if (Array.isArray(data) && data.every(isValidMetric)) { - return true + return true; } else { - return false + return false; } -}; +} function isValidMetric(value: any): value is IGroupMetric | ISingleMetric { if ('groupClass' in value) { @@ -49,9 +58,7 @@ function isValidMetric(value: any): value is IGroupMetric | ISingleMetric { (value.allowedValues === undefined || (Array.isArray(value.allowedValues) && value.allowedValues.every( - (allowedValue) => - typeof allowedValue === 'string' || - typeof allowedValue === 'number' + (allowedValue) => typeof allowedValue === 'string' || typeof allowedValue === 'number' ))) ); } @@ -68,7 +75,7 @@ class ISingleMetric { datatype: IMetricMetaData; @IsOptional() - @IsArray({each: true}) + @IsArray({ each: true }) allowedValues?: (string | number)[]; } @@ -77,7 +84,7 @@ class IGroupMetric { groupClass: string; @IsArray() - @IsString({each: true}) + @IsString({ each: true }) allowedKeys: string[]; @IsArray() @@ -91,4 +98,9 @@ export class MetricValidator { @IsNotEmpty() @IsMetricUnit() metricUnit: (ISingleMetric | IGroupMetric)[]; + + @IsArray() + @IsNotEmpty() + @IsString({ each: true }) + context: string[]; } diff --git a/backend/packages/Upgrade/src/api/models/Metric.ts b/backend/packages/Upgrade/src/api/models/Metric.ts index 36ebb53664..ada36f5bb3 100644 --- a/backend/packages/Upgrade/src/api/models/Metric.ts +++ b/backend/packages/Upgrade/src/api/models/Metric.ts @@ -19,6 +19,9 @@ export class Metric extends BaseModel { @Column({ type: 'simple-array', nullable: true }) public allowedData: string[]; + @Column('text', { array: true }) + public context: string[]; + @ManyToMany(() => Log, (log) => log.metrics, { cascade: true, }) diff --git a/backend/packages/Upgrade/src/api/repositories/MetricRepository.ts b/backend/packages/Upgrade/src/api/repositories/MetricRepository.ts index 794963e74f..43944e9524 100644 --- a/backend/packages/Upgrade/src/api/repositories/MetricRepository.ts +++ b/backend/packages/Upgrade/src/api/repositories/MetricRepository.ts @@ -30,6 +30,16 @@ export class MetricRepository extends Repository { }); } + public async getMetricsByContext(context: string): Promise { + return this.createQueryBuilder('metrics') + .where('context @> :searchContext', { searchContext: [context] }) + .getMany() + .catch((errorMsg: any) => { + const errorMsgString = repositoryError(this.constructor.name, 'getMetricsByContext', { context }, errorMsg); + throw errorMsgString; + }); + } + public async findMetricsWithQueries(ids: string[]): Promise { return this.createQueryBuilder('metrics') .innerJoin('metrics.queries', 'queries') diff --git a/backend/packages/Upgrade/src/api/services/MetricService.ts b/backend/packages/Upgrade/src/api/services/MetricService.ts index 4d70d1d41c..15a671b3ad 100644 --- a/backend/packages/Upgrade/src/api/services/MetricService.ts +++ b/backend/packages/Upgrade/src/api/services/MetricService.ts @@ -19,17 +19,28 @@ export class MetricService { return this.metricDocumentToJson(metricData); } - public async saveAllMetrics(metrics: Array, logger: UpgradeLogger): Promise { + public async getMetricsByContext(context: string, logger: UpgradeLogger): Promise { + logger.info({ message: `Get metrics by context ${context}` }); + const metricData = await this.metricRepository.getMetricsByContext(context); + return this.metricDocumentToJson(metricData); + } + + public async saveAllMetrics( + metrics: Array, + contexts: string[], + logger: UpgradeLogger + ): Promise { logger.info({ message: 'Save all metrics' }); - return await this.addAllMetrics(metrics, logger); + return await this.addAllMetrics(metrics, contexts, logger); } public async upsertAllMetrics( metrics: Array, + contexts: string[], logger: UpgradeLogger ): Promise { logger.info({ message: 'Upsert all metrics' }); - const upsertedMetrics = await this.addAllMetrics(metrics, logger); + const upsertedMetrics = await this.addAllMetrics(metrics, contexts, logger); return this.metricDocumentToJson(upsertedMetrics); } @@ -41,7 +52,11 @@ export class MetricService { return this.metricDocumentToJson(updatedMetric); } - private async addAllMetrics(metrics: Array, logger: UpgradeLogger): Promise { + private async addAllMetrics( + metrics: Array, + contexts: string[], + logger: UpgradeLogger + ): Promise { // check permission for metrics const isAllowed = await this.checkMetricsPermission(logger); if (!isAllowed) { @@ -57,6 +72,7 @@ export class MetricService { key: metric.key, type: metric.type, allowedData: metric.allowedData, + context: contexts, })); return this.metricRepository.save(metricDoc); } @@ -138,6 +154,7 @@ export class MetricService { children: [], metadata: { type: metric.type as any }, allowedData: metric.allowedData, + context: metric.context, }; metricPointer.push(newMetric); diff --git a/backend/packages/Upgrade/src/database/migrations/1712553037665-contextInMetric.ts b/backend/packages/Upgrade/src/database/migrations/1712553037665-contextInMetric.ts new file mode 100644 index 0000000000..41fbd37b9c --- /dev/null +++ b/backend/packages/Upgrade/src/database/migrations/1712553037665-contextInMetric.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class contextInMetric1712553037665 implements MigrationInterface { + name = 'contextInMetric1712553037665'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "metric" ADD "context" text array NOT NULL`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "metric" DROP COLUMN "context"`); + } +} From a281aad31becd56f45c82e7ba82864cea1bde365 Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Fri, 12 Apr 2024 12:03:52 +0530 Subject: [PATCH 2/9] Stepper update to show metric as per context --- .../upgrade/src/app/core/analysis/store/analysis.models.ts | 1 + .../dashboard/home/components/metrics/metrics.component.ts | 7 +++++-- types/src/Experiment/interfaces.ts | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/projects/upgrade/src/app/core/analysis/store/analysis.models.ts b/frontend/projects/upgrade/src/app/core/analysis/store/analysis.models.ts index de6d0e32c6..ec878e2d43 100644 --- a/frontend/projects/upgrade/src/app/core/analysis/store/analysis.models.ts +++ b/frontend/projects/upgrade/src/app/core/analysis/store/analysis.models.ts @@ -8,6 +8,7 @@ export const METRICS_JOIN_TEXT = '@__@'; export interface MetricUnit { key: string; children: MetricUnit[]; + context?: string[]; } export interface UpsertMetrics { diff --git a/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts b/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts index fd087be9a0..f8d70976bd 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts +++ b/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts @@ -85,13 +85,16 @@ export class MonitoredMetricsComponent implements OnInit, OnChanges, OnDestroy { ) {} optionsSub() { + console.log('this.currentContext:', this.currentContext, this.experimentInfo?.context); this.allMetricsSub = this.analysisService.allMetrics$.subscribe((metrics) => { this.allMetrics = metrics; // Hide global metrics options if Within-subjects is selected this.options = this.currentAssignmentUnit === ASSIGNMENT_UNIT.WITHIN_SUBJECTS ? this.allMetrics.filter((metric) => metric.children.length > 0) - : this.allMetrics; + : this.allMetrics.filter((metric) => + metric.context.includes(this.currentContext || this.experimentInfo?.context) + ); }); } @@ -711,7 +714,7 @@ export class MonitoredMetricsComponent implements OnInit, OnChanges, OnDestroy { ngOnChanges() { if (this.isContextChanged || this.isExperimentTypeChanged) { - this.isContextChanged = false; + this.optionsSub(); this.isExperimentTypeChanged = false; this.queries.clear(); this.metricsDataSource.next(this.queries.controls); diff --git a/types/src/Experiment/interfaces.ts b/types/src/Experiment/interfaces.ts index 904859dc7f..96aa7dde5a 100644 --- a/types/src/Experiment/interfaces.ts +++ b/types/src/Experiment/interfaces.ts @@ -110,6 +110,7 @@ export interface IExperimentSortParams { export interface IMetricUnit { key: string | string[]; + context?: string[]; children?: IMetricUnit[]; metadata?: { type: IMetricMetaData }; allowedData?: string[]; From ab42f555b99475ba8785ae490ab0e984baaba892 Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Wed, 24 Apr 2024 09:57:57 +0530 Subject: [PATCH 3/9] solved failing testcases --- .../integration/Experiment/dataLog/CreateLog.ts | 2 +- .../Experiment/dataLog/LogOperations.ts | 2 +- .../Experiment/dataLog/RepeatedMeasure.ts | 2 +- .../integration/Experiment/metric/MetricCRUD.ts | 2 +- .../integration/Experiment/query/QueryCRUD.ts | 2 +- .../stratification/MetricQueriesCheck.ts | 15 +++++++++++---- .../withinSubject/MetricQueriesCheck.ts | 11 +++++++---- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/backend/packages/Upgrade/test/integration/Experiment/dataLog/CreateLog.ts b/backend/packages/Upgrade/test/integration/Experiment/dataLog/CreateLog.ts index 354e90fe5f..77a8fbf35a 100644 --- a/backend/packages/Upgrade/test/integration/Experiment/dataLog/CreateLog.ts +++ b/backend/packages/Upgrade/test/integration/Experiment/dataLog/CreateLog.ts @@ -45,7 +45,7 @@ export default async function CreateLog(): Promise { await settingService.setClientCheck(false, true, new UpgradeLogger()); - await metricService.saveAllMetrics(metrics as any, new UpgradeLogger()); + await metricService.saveAllMetrics(metrics as any, experimentObject.context, new UpgradeLogger()); const findMetric = await metricRepository.find(); expect(findMetric.length).toEqual(36); diff --git a/backend/packages/Upgrade/test/integration/Experiment/dataLog/LogOperations.ts b/backend/packages/Upgrade/test/integration/Experiment/dataLog/LogOperations.ts index 8918a65527..f2810f362c 100644 --- a/backend/packages/Upgrade/test/integration/Experiment/dataLog/LogOperations.ts +++ b/backend/packages/Upgrade/test/integration/Experiment/dataLog/LogOperations.ts @@ -50,7 +50,7 @@ export default async function LogOperations(): Promise { await settingService.setClientCheck(false, true, new UpgradeLogger()); - await metricService.saveAllMetrics(metrics as any, new UpgradeLogger()); + await metricService.saveAllMetrics(metrics as any, experimentObject.context, new UpgradeLogger()); const findMetric = await metricRepository.find(); expect(findMetric.length).toEqual(36); diff --git a/backend/packages/Upgrade/test/integration/Experiment/dataLog/RepeatedMeasure.ts b/backend/packages/Upgrade/test/integration/Experiment/dataLog/RepeatedMeasure.ts index d0fa3bd04d..d729ebeebb 100644 --- a/backend/packages/Upgrade/test/integration/Experiment/dataLog/RepeatedMeasure.ts +++ b/backend/packages/Upgrade/test/integration/Experiment/dataLog/RepeatedMeasure.ts @@ -52,7 +52,7 @@ export default async function RepeatedMeasure(): Promise { await settingService.setClientCheck(false, true, new UpgradeLogger()); - await metricService.saveAllMetrics(metrics as any, new UpgradeLogger()); + await metricService.saveAllMetrics(metrics as any, experimentObject.context, new UpgradeLogger()); // change experiment status to Enrolling const experimentId = experiments[0].id; diff --git a/backend/packages/Upgrade/test/integration/Experiment/metric/MetricCRUD.ts b/backend/packages/Upgrade/test/integration/Experiment/metric/MetricCRUD.ts index 931bae6187..0903242214 100644 --- a/backend/packages/Upgrade/test/integration/Experiment/metric/MetricCRUD.ts +++ b/backend/packages/Upgrade/test/integration/Experiment/metric/MetricCRUD.ts @@ -14,7 +14,7 @@ export default async function MetricCRUD(): Promise { await settingService.setClientCheck(false, true, new UpgradeLogger()); // create metrics service - await metricService.saveAllMetrics(metrics as any, new UpgradeLogger()); + await metricService.saveAllMetrics(metrics as any, ['home'], new UpgradeLogger()); let findMetric = await metricRepository.find(); expect(findMetric.length).toEqual(36); diff --git a/backend/packages/Upgrade/test/integration/Experiment/query/QueryCRUD.ts b/backend/packages/Upgrade/test/integration/Experiment/query/QueryCRUD.ts index 4bdb0aa5d1..84ae29efd3 100644 --- a/backend/packages/Upgrade/test/integration/Experiment/query/QueryCRUD.ts +++ b/backend/packages/Upgrade/test/integration/Experiment/query/QueryCRUD.ts @@ -45,7 +45,7 @@ export default async function QueryCRUD(): Promise { ); // create metrics service - await metricService.saveAllMetrics(metrics as any, new UpgradeLogger()); + await metricService.saveAllMetrics(metrics as any, experimentObject.context, new UpgradeLogger()); const findMetric = await metricRepository.find(); expect(findMetric.length).toEqual(36); diff --git a/backend/packages/Upgrade/test/integration/Experiment/stratification/MetricQueriesCheck.ts b/backend/packages/Upgrade/test/integration/Experiment/stratification/MetricQueriesCheck.ts index 6650403dfc..7273d61e10 100644 --- a/backend/packages/Upgrade/test/integration/Experiment/stratification/MetricQueriesCheck.ts +++ b/backend/packages/Upgrade/test/integration/Experiment/stratification/MetricQueriesCheck.ts @@ -26,7 +26,11 @@ export default async function MetricQueriesCheck(): Promise { await settingService.setClientCheck(false, true, new UpgradeLogger()); // create metrics service - await metricService.saveAllMetrics(metrics as any, new UpgradeLogger()); + await metricService.saveAllMetrics( + metrics as any, + stratificationRandomExperimentAssignmentExperiment2.context, + new UpgradeLogger() + ); // creating new user const user = await userService.upsertUser(systemUser as any, new UpgradeLogger()); @@ -412,7 +416,11 @@ export default async function MetricQueriesCheck(): Promise { ]; // experiment object - const experimentObject = { ...stratificationRandomExperimentAssignmentExperiment2, queries: metricsQueries, conditionOrder: CONDITION_ORDER.ORDERED_ROUND_ROBIN }; + const experimentObject = { + ...stratificationRandomExperimentAssignmentExperiment2, + queries: metricsQueries, + conditionOrder: CONDITION_ORDER.ORDERED_ROUND_ROBIN, + }; await experimentService.update(experimentObject as any, user, new UpgradeLogger()); experiments = await experimentService.find(new UpgradeLogger()); const experimentTarget = experimentObject.partitions[0].target; @@ -537,7 +545,7 @@ export default async function MetricQueriesCheck(): Promise { ], { logger: new UpgradeLogger(), userDoc: experimentUserDoc } ); - + const condition2 = experimentObject.conditions[1].conditionCode; // user 1 mark experiment point on condition2 markedExperimentPoint = await markExperimentPoint( @@ -699,7 +707,6 @@ export default async function MetricQueriesCheck(): Promise { const queryResult = await queryService.analyze([query.id], new UpgradeLogger()); let expectedValue; switch (query.query.operationType) { - case OPERATION_TYPES.SUM: { switch (query.repeatedMeasure) { case REPEATED_MEASURE.mostRecent: { diff --git a/backend/packages/Upgrade/test/integration/Experiment/withinSubject/MetricQueriesCheck.ts b/backend/packages/Upgrade/test/integration/Experiment/withinSubject/MetricQueriesCheck.ts index 27bb8709d7..47802ccaea 100644 --- a/backend/packages/Upgrade/test/integration/Experiment/withinSubject/MetricQueriesCheck.ts +++ b/backend/packages/Upgrade/test/integration/Experiment/withinSubject/MetricQueriesCheck.ts @@ -26,7 +26,7 @@ export default async function MetricQueriesCheck(): Promise { await settingService.setClientCheck(false, true, new UpgradeLogger()); // create metrics service - await metricService.saveAllMetrics(metrics as any, new UpgradeLogger()); + await metricService.saveAllMetrics(metrics as any, withinSubjectExperiment.context, new UpgradeLogger()); // creating new user const user = await userService.upsertUser(systemUser as any, new UpgradeLogger()); @@ -412,7 +412,11 @@ export default async function MetricQueriesCheck(): Promise { ]; // experiment object - const experimentObject = { ...withinSubjectExperiment, queries: metricsQueries, conditionOrder: CONDITION_ORDER.ORDERED_ROUND_ROBIN }; + const experimentObject = { + ...withinSubjectExperiment, + queries: metricsQueries, + conditionOrder: CONDITION_ORDER.ORDERED_ROUND_ROBIN, + }; await experimentService.update(experimentObject as any, user, new UpgradeLogger()); experiments = await experimentService.find(new UpgradeLogger()); const experimentTarget = experimentObject.partitions[0].target; @@ -537,7 +541,7 @@ export default async function MetricQueriesCheck(): Promise { ], { logger: new UpgradeLogger(), userDoc: experimentUserDoc } ); - + const condition2 = experimentObject.conditions[1].conditionCode; // user 1 mark experiment point on condition2 markedExperimentPoint = await markExperimentPoint( @@ -699,7 +703,6 @@ export default async function MetricQueriesCheck(): Promise { const queryResult = await queryService.analyze([query.id], new UpgradeLogger()); let expectedValue; switch (query.query.operationType) { - case OPERATION_TYPES.SUM: { switch (query.repeatedMeasure) { case REPEATED_MEASURE.mostRecent: { From c861048a13074287d1ba62cba6904cd9cc7b976e Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Wed, 24 Apr 2024 10:02:47 +0530 Subject: [PATCH 4/9] Update initMetrics to save metrics from env file --- backend/packages/Upgrade/src/init/seed/initMetrics.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/packages/Upgrade/src/init/seed/initMetrics.ts b/backend/packages/Upgrade/src/init/seed/initMetrics.ts index ca1569e496..f18534d43d 100644 --- a/backend/packages/Upgrade/src/init/seed/initMetrics.ts +++ b/backend/packages/Upgrade/src/init/seed/initMetrics.ts @@ -8,7 +8,11 @@ export function InitMetrics(logger: UpgradeLogger): Promise { // Init default metrics in system if (env.initialization.metrics) { try { - return metricService.saveAllMetrics(JSON.parse(env.initialization.metrics), logger); + return metricService.saveAllMetrics( + JSON.parse(env.initialization.metrics), + Object.keys(env.initialization.contextMetadata), + logger + ); } catch (err) { const error = new Error('Error while initializing metrics'); logger.error(error); From 875443581ac4c1431259134a55e3ffc85340345d Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Wed, 24 Apr 2024 10:41:51 +0530 Subject: [PATCH 5/9] Solved failing unit testcases --- .../test/unit/controllers/MetricController.test.ts | 1 + .../Upgrade/test/unit/services/MetricService.test.ts | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/packages/Upgrade/test/unit/controllers/MetricController.test.ts b/backend/packages/Upgrade/test/unit/controllers/MetricController.test.ts index a514333202..451639562e 100644 --- a/backend/packages/Upgrade/test/unit/controllers/MetricController.test.ts +++ b/backend/packages/Upgrade/test/unit/controllers/MetricController.test.ts @@ -32,6 +32,7 @@ describe('Metric Controller Testing', () => { .post('/api/metric/save') .send({ metricUnit: [], + context: [], }) .set('Accept', 'application/json') .expect('Content-Type', /json/) diff --git a/backend/packages/Upgrade/test/unit/services/MetricService.test.ts b/backend/packages/Upgrade/test/unit/services/MetricService.test.ts index 6f9ad43507..97e4bce29f 100644 --- a/backend/packages/Upgrade/test/unit/services/MetricService.test.ts +++ b/backend/packages/Upgrade/test/unit/services/MetricService.test.ts @@ -14,6 +14,8 @@ describe('Audit Service Testing', () => { let module: TestingModule; const settingRes = [{ id: 'id', toCheckAuth: false, toFilterMetric: true }]; + const contexts = ['home']; + const simpleMetric: Array = [ { metric: 'totalProblemsCompleted', @@ -39,6 +41,7 @@ describe('Audit Service Testing', () => { key: 'totalProblemsCompleted', type: IMetricMetaData.CONTINUOUS, allowedData: [], + context: ['home'], logs: [], queries: [], createdAt: new Date('2020-1-1'), @@ -52,6 +55,7 @@ describe('Audit Service Testing', () => { key: 'totalProblemsCompleted', allowedData: [], children: [], + context: ['home'], metadata: { type: IMetricMetaData.CONTINUOUS, }, @@ -102,17 +106,17 @@ describe('Audit Service Testing', () => { }); it('should save all simple metrics', async () => { - const res = await service.saveAllMetrics(simpleMetric, new UpgradeLogger()); + const res = await service.saveAllMetrics(simpleMetric, contexts, new UpgradeLogger()); expect(res).toEqual(metric); }); it('should save all group metrics', async () => { - const res = await service.saveAllMetrics(groupMetric, new UpgradeLogger()); + const res = await service.saveAllMetrics(groupMetric, contexts, new UpgradeLogger()); expect(res).toEqual(metric); }); it('should upsert all metrics', async () => { - const res = await service.upsertAllMetrics(simpleMetric, new UpgradeLogger()); + const res = await service.upsertAllMetrics(simpleMetric, contexts, new UpgradeLogger()); expect(res).toEqual(metricResult); }); @@ -125,7 +129,7 @@ describe('Audit Service Testing', () => { settingRes[0].toFilterMetric = false; expect(async () => { - await service.saveAllMetrics(groupMetric, new UpgradeLogger()); + await service.saveAllMetrics(groupMetric, contexts, new UpgradeLogger()); }).rejects.toThrow('Metrics filter not enabled'); }); }); From 7e0c873d6005ed90f5940b04f15259a92fc65998 Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Thu, 25 Apr 2024 11:52:20 +0530 Subject: [PATCH 6/9] update METRICS format in env file --- backend/packages/Upgrade/.env.example | 2 +- backend/packages/Upgrade/.env.test | 4 ++-- backend/packages/Upgrade/src/env.ts | 2 +- backend/packages/Upgrade/src/init/seed/initMetrics.ts | 8 +++----- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/packages/Upgrade/.env.example b/backend/packages/Upgrade/.env.example index 4d0c408d62..d73256c39c 100644 --- a/backend/packages/Upgrade/.env.example +++ b/backend/packages/Upgrade/.env.example @@ -87,4 +87,4 @@ CLIENT_API_SECRET = secret CLIENT_API_KEY = key CONTEXT_METADATA = {"add":{"EXP_IDS":["add-id1","add-id2"],"EXP_POINTS":["add-point1","add-point2"],"GROUP_TYPES":["add-group1","add-group2"],"CONDITIONS":["add-con1","add-con2","add-con3"]},"sub":{"EXP_IDS":["sub-id1","sub-id2"],"EXP_POINTS":["sub-point1","sub-point2"],"GROUP_TYPES":["sub-group1","sub-group2"],"CONDITIONS":["sub-con1","sub-con2","sub-con3"]},"mul":{"EXP_IDS":["mul-id1","mul-id2"],"EXP_POINTS":["mul-point1","mul-point2"],"GROUP_TYPES":["mul-group1","mul-group2"],"CONDITIONS":["mul-con1","mul-con2","mul-con3"]},"div":{"EXP_IDS":["div-id1","div-id2"],"EXP_POINTS":["div-point1","div-point2"],"GROUP_TYPES":["div-group1","div-group2"],"CONDITIONS":["div-con1","div-con2","div-con3"]}} -METRICS = [{"metric": "totalTimeSeconds","datatype": "continuous"}, { "groupClass": "masteryWorkspace", "allowedKeys": [ "calculating_area_various_figures", "Compare_functions_diff_reps_quadratic" ], "attributes": [{ "metric": "timeSeconds", "datatype": "continuous"}]}] +PRE_DEFINED_METRICS = [{"metrics":[{"metric":"totalTimeSeconds","datatype":"continuous"},{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]}],"contexts":["test-context1","test-context2"]},{"metrics":[{"groupClass":"addWorkspace","allowedKeys":["level1","level2"],"attributes":[{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]},{"metric":"timeSpent","datatype":"continuous"}]}],"contexts":["test-context3"]}] \ No newline at end of file diff --git a/backend/packages/Upgrade/.env.test b/backend/packages/Upgrade/.env.test index ea6368c05b..06848a9084 100644 --- a/backend/packages/Upgrade/.env.test +++ b/backend/packages/Upgrade/.env.test @@ -22,7 +22,7 @@ LOG_OUTPUT=dev # PostgreSQL DATABASE # TYPEORM_CONNECTION=postgres -TYPEORM_HOST=postgres +TYPEORM_HOST=localhost TYPEORM_HOSTNAME_REPLICAS=[] TYPEORM_PORT=5432 TYPEORM_USERNAME=postgres @@ -89,4 +89,4 @@ CLIENT_API_SECRET = secret CLIENT_API_KEY = key CONTEXT_METADATA = {"add":{"EXP_IDS":["add-id1","add-id2"],"EXP_POINTS":["add-point1","add-point2"],"GROUP_TYPES":["add-group1","add-group2"],"CONDITIONS":["add-con1","add-con2","add-con3"]},"sub":{"EXP_IDS":["sub-id1","sub-id2"],"EXP_POINTS":["sub-point1","sub-point2"],"GROUP_TYPES":["sub-group1","sub-group2"],"CONDITIONS":["sub-con1","sub-con2","sub-con3"]},"mul":{"EXP_IDS":["mul-id1","mul-id2"],"EXP_POINTS":["mul-point1","mul-point2"],"GROUP_TYPES":["mul-group1","mul-group2"],"CONDITIONS":["mul-con1","mul-con2","mul-con3"]},"div":{"EXP_IDS":["div-id1","div-id2"],"EXP_POINTS":["div-point1","div-point2"],"GROUP_TYPES":["div-group1","div-group2"],"CONDITIONS":["div-con1","div-con2","div-con3"]}} -METRICS = [{"metric": "totalTimeSeconds","datatype": "continuous"}, {"metric": "workspaceCompletionStatus","datatype": "categorical", "allowedValues": ["GRADUATED", "PROMOTED"]}, { "groupClass": "addWorkspace", "allowedKeys": [ "level1", "level2" ], "attributes": [{"metric": "workspaceCompletionStatus","datatype": "categorical", "allowedValues": ["GRADUATED", "PROMOTED"]},{"metric": "timeSpent","datatype": "continuous"}]}] +PRE_DEFINED_METRICS = [{"metrics":[{"metric":"totalTimeSeconds","datatype":"continuous"},{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]}],"contexts":["test-context1","test-context2"]},{"metrics":[{"groupClass":"addWorkspace","allowedKeys":["level1","level2"],"attributes":[{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]},{"metric":"timeSpent","datatype":"continuous"}]}],"contexts":["test-context3"]}] diff --git a/backend/packages/Upgrade/src/env.ts b/backend/packages/Upgrade/src/env.ts index dbc4233380..e183373b08 100644 --- a/backend/packages/Upgrade/src/env.ts +++ b/backend/packages/Upgrade/src/env.ts @@ -92,7 +92,7 @@ export const env = { initialization: { contextMetadata: JSON.parse(getOsEnv('CONTEXT_METADATA')), adminUsers: parseAdminUsers(getOsEnv('ADMIN_USERS')), - metrics: getOsEnvOptional('METRICS'), + metrics: getOsEnvOptional('PRE_DEFINED_METRICS'), }, hostUrl: getOsEnv('HOST_URL'), tokenSecretKey: getOsEnv('TOKEN_SECRET_KEY'), diff --git a/backend/packages/Upgrade/src/init/seed/initMetrics.ts b/backend/packages/Upgrade/src/init/seed/initMetrics.ts index f18534d43d..92ecd0f9aa 100644 --- a/backend/packages/Upgrade/src/init/seed/initMetrics.ts +++ b/backend/packages/Upgrade/src/init/seed/initMetrics.ts @@ -8,11 +8,9 @@ export function InitMetrics(logger: UpgradeLogger): Promise { // Init default metrics in system if (env.initialization.metrics) { try { - return metricService.saveAllMetrics( - JSON.parse(env.initialization.metrics), - Object.keys(env.initialization.contextMetadata), - logger - ); + return JSON.parse(env.initialization.metrics).map((metricData) => { + return metricService.saveAllMetrics(metricData.metrics, metricData.contexts, logger); + }); } catch (err) { const error = new Error('Error while initializing metrics'); logger.error(error); From 7ef24289a116fe066fbcc13fb3b94fdb499628f9 Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Thu, 25 Apr 2024 12:02:58 +0530 Subject: [PATCH 7/9] solve env test error --- backend/packages/Upgrade/.env.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/packages/Upgrade/.env.test b/backend/packages/Upgrade/.env.test index 06848a9084..a4d311f18c 100644 --- a/backend/packages/Upgrade/.env.test +++ b/backend/packages/Upgrade/.env.test @@ -22,7 +22,7 @@ LOG_OUTPUT=dev # PostgreSQL DATABASE # TYPEORM_CONNECTION=postgres -TYPEORM_HOST=localhost +TYPEORM_HOST=postgres TYPEORM_HOSTNAME_REPLICAS=[] TYPEORM_PORT=5432 TYPEORM_USERNAME=postgres From 9a65b6536b4363c5d6ee2074ff893f57f19c8598 Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Mon, 29 Apr 2024 14:25:35 +0530 Subject: [PATCH 8/9] solve git comments --- backend/packages/Upgrade/src/init/seed/initMetrics.ts | 3 ++- .../dashboard/home/components/metrics/metrics.component.ts | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/packages/Upgrade/src/init/seed/initMetrics.ts b/backend/packages/Upgrade/src/init/seed/initMetrics.ts index 92ecd0f9aa..314afbe8c3 100644 --- a/backend/packages/Upgrade/src/init/seed/initMetrics.ts +++ b/backend/packages/Upgrade/src/init/seed/initMetrics.ts @@ -8,9 +8,10 @@ export function InitMetrics(logger: UpgradeLogger): Promise { // Init default metrics in system if (env.initialization.metrics) { try { - return JSON.parse(env.initialization.metrics).map((metricData) => { + const metrics = JSON.parse(env.initialization.metrics).map((metricData) => { return metricService.saveAllMetrics(metricData.metrics, metricData.contexts, logger); }); + Promise.all(metrics); } catch (err) { const error = new Error('Error while initializing metrics'); logger.error(error); diff --git a/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts b/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts index f8d70976bd..882ecb82cf 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts +++ b/frontend/projects/upgrade/src/app/features/dashboard/home/components/metrics/metrics.component.ts @@ -85,7 +85,6 @@ export class MonitoredMetricsComponent implements OnInit, OnChanges, OnDestroy { ) {} optionsSub() { - console.log('this.currentContext:', this.currentContext, this.experimentInfo?.context); this.allMetricsSub = this.analysisService.allMetrics$.subscribe((metrics) => { this.allMetrics = metrics; // Hide global metrics options if Within-subjects is selected From 313e788bd0b8549102c94cbd67600ee407e7ca5b Mon Sep 17 00:00:00 2001 From: RidhamShah Date: Tue, 30 Apr 2024 10:34:45 +0530 Subject: [PATCH 9/9] updated env metric name --- backend/packages/Upgrade/.env.example | 2 +- backend/packages/Upgrade/.env.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/packages/Upgrade/.env.example b/backend/packages/Upgrade/.env.example index d73256c39c..5e0a02ac5c 100644 --- a/backend/packages/Upgrade/.env.example +++ b/backend/packages/Upgrade/.env.example @@ -87,4 +87,4 @@ CLIENT_API_SECRET = secret CLIENT_API_KEY = key CONTEXT_METADATA = {"add":{"EXP_IDS":["add-id1","add-id2"],"EXP_POINTS":["add-point1","add-point2"],"GROUP_TYPES":["add-group1","add-group2"],"CONDITIONS":["add-con1","add-con2","add-con3"]},"sub":{"EXP_IDS":["sub-id1","sub-id2"],"EXP_POINTS":["sub-point1","sub-point2"],"GROUP_TYPES":["sub-group1","sub-group2"],"CONDITIONS":["sub-con1","sub-con2","sub-con3"]},"mul":{"EXP_IDS":["mul-id1","mul-id2"],"EXP_POINTS":["mul-point1","mul-point2"],"GROUP_TYPES":["mul-group1","mul-group2"],"CONDITIONS":["mul-con1","mul-con2","mul-con3"]},"div":{"EXP_IDS":["div-id1","div-id2"],"EXP_POINTS":["div-point1","div-point2"],"GROUP_TYPES":["div-group1","div-group2"],"CONDITIONS":["div-con1","div-con2","div-con3"]}} -PRE_DEFINED_METRICS = [{"metrics":[{"metric":"totalTimeSeconds","datatype":"continuous"},{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]}],"contexts":["test-context1","test-context2"]},{"metrics":[{"groupClass":"addWorkspace","allowedKeys":["level1","level2"],"attributes":[{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]},{"metric":"timeSpent","datatype":"continuous"}]}],"contexts":["test-context3"]}] \ No newline at end of file +METRICS = [{"metrics":[{"metric":"totalTimeSeconds","datatype":"continuous"},{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]}],"contexts":["test-context1","test-context2"]},{"metrics":[{"groupClass":"addWorkspace","allowedKeys":["level1","level2"],"attributes":[{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]},{"metric":"timeSpent","datatype":"continuous"}]}],"contexts":["test-context3"]}] \ No newline at end of file diff --git a/backend/packages/Upgrade/.env.test b/backend/packages/Upgrade/.env.test index a4d311f18c..12c73946b9 100644 --- a/backend/packages/Upgrade/.env.test +++ b/backend/packages/Upgrade/.env.test @@ -89,4 +89,4 @@ CLIENT_API_SECRET = secret CLIENT_API_KEY = key CONTEXT_METADATA = {"add":{"EXP_IDS":["add-id1","add-id2"],"EXP_POINTS":["add-point1","add-point2"],"GROUP_TYPES":["add-group1","add-group2"],"CONDITIONS":["add-con1","add-con2","add-con3"]},"sub":{"EXP_IDS":["sub-id1","sub-id2"],"EXP_POINTS":["sub-point1","sub-point2"],"GROUP_TYPES":["sub-group1","sub-group2"],"CONDITIONS":["sub-con1","sub-con2","sub-con3"]},"mul":{"EXP_IDS":["mul-id1","mul-id2"],"EXP_POINTS":["mul-point1","mul-point2"],"GROUP_TYPES":["mul-group1","mul-group2"],"CONDITIONS":["mul-con1","mul-con2","mul-con3"]},"div":{"EXP_IDS":["div-id1","div-id2"],"EXP_POINTS":["div-point1","div-point2"],"GROUP_TYPES":["div-group1","div-group2"],"CONDITIONS":["div-con1","div-con2","div-con3"]}} -PRE_DEFINED_METRICS = [{"metrics":[{"metric":"totalTimeSeconds","datatype":"continuous"},{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]}],"contexts":["test-context1","test-context2"]},{"metrics":[{"groupClass":"addWorkspace","allowedKeys":["level1","level2"],"attributes":[{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]},{"metric":"timeSpent","datatype":"continuous"}]}],"contexts":["test-context3"]}] +METRICS = [{"metrics":[{"metric":"totalTimeSeconds","datatype":"continuous"},{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]}],"contexts":["test-context1","test-context2"]},{"metrics":[{"groupClass":"addWorkspace","allowedKeys":["level1","level2"],"attributes":[{"metric":"workspaceCompletionStatus","datatype":"categorical","allowedValues":["GRADUATED","PROMOTED"]},{"metric":"timeSpent","datatype":"continuous"}]}],"contexts":["test-context3"]}]