From b1282545de533dc95ed2df7f25a6e1335bd653ef Mon Sep 17 00:00:00 2001 From: anandtiwary <52081890+anandtiwary@users.noreply.github.com> Date: Thu, 15 Jul 2021 15:28:48 -0700 Subject: [PATCH 1/2] feat: adding topology custom metric model and service --- .../metrics/topology-metric-category.model.ts | 74 +++++++++++++++++ .../topology-metric-with-category.model.ts | 58 ++++++++++++++ .../metrics/topology-metrics.model.ts | 48 +++++++++++ .../topology/metric/edge-metric-category.ts | 80 +++++++++++++++++++ .../topology/metric/node-metric-category.ts | 80 +++++++++++++++++++ ...gy-data-source-model-properties.service.ts | 45 +++++++++++ 6 files changed, 385 insertions(+) create mode 100644 projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.ts create mode 100644 projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.ts create mode 100644 projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metrics.model.ts create mode 100644 projects/observability/src/shared/dashboard/widgets/topology/metric/edge-metric-category.ts create mode 100644 projects/observability/src/shared/dashboard/widgets/topology/metric/node-metric-category.ts create mode 100644 projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.ts diff --git a/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.ts b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.ts new file mode 100644 index 000000000..d844453d0 --- /dev/null +++ b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.ts @@ -0,0 +1,74 @@ +import { Color } from '@hypertrace/common'; +import { BOOLEAN_PROPERTY, Model, ModelProperty, NUMBER_PROPERTY, STRING_PROPERTY } from '@hypertrace/hyperdash'; +import { kebabCase, uniqueId } from 'lodash-es'; + +@Model({ + type: 'topology-metric-category' +}) +export class TopologyMetricCategoryModel implements TopologyMetricCategoryData { + @ModelProperty({ + key: 'name', + required: true, + type: STRING_PROPERTY.type + }) + public name!: string; + + @ModelProperty({ + key: 'minValue', + required: true, + type: NUMBER_PROPERTY.type + }) + public minValue!: number; + + @ModelProperty({ + key: 'maxValue', + required: false, + type: NUMBER_PROPERTY.type + }) + public maxValue?: number; + + @ModelProperty({ + key: 'fillColor', + required: true, + type: STRING_PROPERTY.type + }) + public fillColor!: Color; + + @ModelProperty({ + key: 'strokeColor', + required: true, + type: STRING_PROPERTY.type + }) + public strokeColor!: Color; + + @ModelProperty({ + key: 'focusColor', + required: true, + type: STRING_PROPERTY.type + }) + public focusColor!: Color; + + @ModelProperty({ + key: 'highestPrecedence', + required: false, + type: BOOLEAN_PROPERTY.type + }) + public highestPrecedence?: boolean = false; + + private readonly id: string = uniqueId(); + + public getCategoryClassName(): string { + return `${kebabCase(this.name)}-${this.id}`; + } +} + +export interface TopologyMetricCategoryData { + name: string; + minValue: number; + maxValue?: number; + fillColor: string; + strokeColor: string; + focusColor: string; + highestPrecedence?: boolean; + getCategoryClassName(): string; +} diff --git a/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.ts b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.ts new file mode 100644 index 000000000..644ff2afe --- /dev/null +++ b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.ts @@ -0,0 +1,58 @@ +import { Dictionary } from '@hypertrace/common'; +import { MetricAggregation } from '@hypertrace/distributed-tracing'; +import { + ARRAY_PROPERTY, + Model, + ModelModelPropertyTypeInstance, + ModelProperty, + ModelPropertyType +} from '@hypertrace/hyperdash'; +import { MetricAggregationSpecificationModel } from '../../specifiers/metric-aggregation-specification.model'; +import { MetricAggregationSpecification } from './../../../../../graphql/model/schema/specifications/metric-aggregation-specification'; +import { TopologyMetricCategoryData, TopologyMetricCategoryModel } from './topology-metric-category.model'; + +@Model({ + type: 'topology-metric-with-category' +}) +export class TopologyMetricWithCategoryModel implements TopologyMetricWithCategoryData { + @ModelProperty({ + key: 'specification', + required: true, + // tslint:disable-next-line: no-object-literal-type-assertion + type: { + key: ModelPropertyType.TYPE, + defaultModelClass: MetricAggregationSpecificationModel + } as ModelModelPropertyTypeInstance + }) + public specification!: MetricAggregationSpecificationModel; + + @ModelProperty({ + key: 'categories', + required: false, + type: ARRAY_PROPERTY.type + }) + public categories: TopologyMetricCategoryModel[] = []; + + public extractAndGetDataCategoryForMetric(data: Dictionary): TopologyMetricCategoryData | undefined { + const aggregation = this.extractDataForMetric(data); + + return aggregation !== undefined ? this.getDataCategoryForMetric(aggregation.value) : undefined; + } + + public extractDataForMetric(data: Dictionary): MetricAggregation | undefined { + return data[this.specification.resultAlias()] as MetricAggregation | undefined; + } + + private getDataCategoryForMetric(value: number): TopologyMetricCategoryData | undefined { + return this.categories.find( + category => value >= category.minValue && (category.maxValue !== undefined ? value < category.maxValue : true) + ); + } +} + +export interface TopologyMetricWithCategoryData { + specification: MetricAggregationSpecification; + categories: TopologyMetricCategoryData[]; + extractDataForMetric(data: Dictionary): MetricAggregation | undefined; + extractAndGetDataCategoryForMetric(data: Dictionary): TopologyMetricCategoryData | undefined; +} diff --git a/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metrics.model.ts b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metrics.model.ts new file mode 100644 index 000000000..934912632 --- /dev/null +++ b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metrics.model.ts @@ -0,0 +1,48 @@ +import { + ARRAY_PROPERTY, + Model, + ModelModelPropertyTypeInstance, + ModelProperty, + ModelPropertyType +} from '@hypertrace/hyperdash'; +import { TopologyMetricWithCategoryData, TopologyMetricWithCategoryModel } from './topology-metric-with-category.model'; + +@Model({ + type: 'topology-metrics' +}) +export class TopologyMetricsModel implements TopologyMetricsData { + @ModelProperty({ + key: 'primary', + required: true, + // tslint:disable-next-line: no-object-literal-type-assertion + type: { + key: ModelPropertyType.TYPE, + defaultModelClass: TopologyMetricWithCategoryModel + } as ModelModelPropertyTypeInstance + }) + public primary!: TopologyMetricWithCategoryModel; + + @ModelProperty({ + key: 'secondary', + required: false, + // tslint:disable-next-line: no-object-literal-type-assertion + type: { + key: ModelPropertyType.TYPE, + defaultModelClass: TopologyMetricWithCategoryModel + } as ModelModelPropertyTypeInstance + }) + public secondary?: TopologyMetricWithCategoryModel; + + @ModelProperty({ + key: 'others', + required: false, + type: ARRAY_PROPERTY.type + }) + public others?: TopologyMetricWithCategoryModel[]; +} + +export interface TopologyMetricsData { + primary: TopologyMetricWithCategoryData; + secondary?: TopologyMetricWithCategoryData; + others?: TopologyMetricWithCategoryData[]; +} diff --git a/projects/observability/src/shared/dashboard/widgets/topology/metric/edge-metric-category.ts b/projects/observability/src/shared/dashboard/widgets/topology/metric/edge-metric-category.ts new file mode 100644 index 000000000..be98800a0 --- /dev/null +++ b/projects/observability/src/shared/dashboard/widgets/topology/metric/edge-metric-category.ts @@ -0,0 +1,80 @@ +import { Color } from '@hypertrace/common'; +import { TopologyMetricCategoryData } from '../../../data/graphql/topology/metrics/topology-metric-category.model'; + +const enum PrimaryEdgeMetricCategoryValueType { + LessThan20 = 'less-than-20', + From20To100 = 'from-20-to-100', + From100To500 = 'from-100-to-500', + From500To1000 = 'from-500-to-1000', + GreaterThanOrEqualTo1000 = 'greater-than-or-equal-to-1000', + NotSpecified = 'not-specified' +} + +const enum SecondaryEdgeMetricCategoryValueType { + LessThan5 = 'less-than-5', + GreaterThanOrEqualTo5 = 'greater-than-or-equal-to-5', + NotSpecified = 'not-specified' +} + +export const defaultPrimaryEdgeMetricCategories: Omit[] = [ + { + name: PrimaryEdgeMetricCategoryValueType.LessThan20, + minValue: 0, + maxValue: 20, + fillColor: Color.BlueGray1, + strokeColor: Color.BlueGray1, + focusColor: Color.BlueGray1 + }, + { + name: PrimaryEdgeMetricCategoryValueType.From20To100, + minValue: 20, + maxValue: 100, + fillColor: Color.BlueGray2, + strokeColor: Color.BlueGray2, + focusColor: Color.BlueGray2 + }, + { + name: PrimaryEdgeMetricCategoryValueType.From100To500, + minValue: 100, + maxValue: 500, + fillColor: Color.BlueGray3, + strokeColor: Color.BlueGray3, + focusColor: Color.BlueGray3 + }, + { + name: PrimaryEdgeMetricCategoryValueType.From500To1000, + minValue: 500, + maxValue: 1000, + fillColor: Color.BlueGray4, + strokeColor: Color.BlueGray4, + focusColor: Color.BlueGray4 + }, + { + name: PrimaryEdgeMetricCategoryValueType.GreaterThanOrEqualTo1000, + minValue: 1000, + maxValue: undefined, + fillColor: Color.BlueGray4, + strokeColor: Color.BlueGray4, + focusColor: Color.BlueGray4 + } +]; + +export const defaultSecondaryEdgeMetricCategories: Omit[] = [ + { + name: SecondaryEdgeMetricCategoryValueType.LessThan5, + minValue: 0, + maxValue: 5, + fillColor: Color.Gray2, + strokeColor: Color.Gray2, + focusColor: Color.Gray2 + }, + { + name: SecondaryEdgeMetricCategoryValueType.GreaterThanOrEqualTo5, + minValue: 5, + maxValue: undefined, + fillColor: Color.Red5, + strokeColor: Color.Red5, + focusColor: Color.Red5, + highestPrecedence: true + } +]; diff --git a/projects/observability/src/shared/dashboard/widgets/topology/metric/node-metric-category.ts b/projects/observability/src/shared/dashboard/widgets/topology/metric/node-metric-category.ts new file mode 100644 index 000000000..688f9a313 --- /dev/null +++ b/projects/observability/src/shared/dashboard/widgets/topology/metric/node-metric-category.ts @@ -0,0 +1,80 @@ +import { Color } from '@hypertrace/common'; +import { TopologyMetricCategoryData } from '../../../data/graphql/topology/metrics/topology-metric-category.model'; + +const enum PrimaryNodeMetricCategoryValueType { + LessThan20 = 'less-than-20', + From20To100 = 'from-20-to-100', + From100To500 = 'from-100-to-500', + From500To1000 = 'from-500-to-1000', + GreaterThanOrEqualTo1000 = 'greater-than-or-equal-to-1000', + NotSpecified = 'not-specified' +} + +const enum SecondaryNodeMetricCategoryValueType { + LessThan5 = 'less-than-5', + GreaterThanOrEqualTo5 = 'greater-than-or-equal-to-5', + NotSpecified = 'not-specified' +} + +export const defaultPrimaryNodeMetricCategories: Omit[] = [ + { + name: PrimaryNodeMetricCategoryValueType.LessThan20, + minValue: 0, + maxValue: 20, + fillColor: Color.BlueGray1, + strokeColor: Color.BlueGray1, + focusColor: Color.Blue4 + }, + { + name: PrimaryNodeMetricCategoryValueType.From20To100, + minValue: 20, + maxValue: 100, + fillColor: Color.BlueGray2, + strokeColor: Color.BlueGray2, + focusColor: Color.Blue4 + }, + { + name: PrimaryNodeMetricCategoryValueType.From100To500, + minValue: 100, + maxValue: 500, + fillColor: Color.BlueGray3, + strokeColor: Color.BlueGray3, + focusColor: Color.Blue4 + }, + { + name: PrimaryNodeMetricCategoryValueType.From500To1000, + minValue: 500, + maxValue: 1000, + fillColor: Color.BlueGray4, + strokeColor: Color.BlueGray4, + focusColor: Color.Blue4 + }, + { + name: PrimaryNodeMetricCategoryValueType.GreaterThanOrEqualTo1000, + minValue: 1000, + maxValue: undefined, + fillColor: Color.BlueGray4, + strokeColor: Color.BlueGray4, + focusColor: Color.Blue4 + } +]; + +export const defaultSecondaryNodeMetricCategories: Omit[] = [ + { + name: SecondaryNodeMetricCategoryValueType.LessThan5, + minValue: 0, + maxValue: 5, + fillColor: Color.Gray2, + strokeColor: Color.Gray2, + focusColor: Color.Blue4 + }, + { + name: SecondaryNodeMetricCategoryValueType.GreaterThanOrEqualTo5, + minValue: 5, + maxValue: undefined, + fillColor: Color.Red1, + strokeColor: Color.Red5, + focusColor: Color.Red5, + highestPrecedence: true + } +]; diff --git a/projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.ts b/projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.ts new file mode 100644 index 000000000..941652b03 --- /dev/null +++ b/projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@angular/core'; +import { TopologyMetricCategoryData } from '../../data/graphql/topology/metrics/topology-metric-category.model'; +import { TopologyMetricWithCategoryData } from '../../data/graphql/topology/metrics/topology-metric-with-category.model'; +import { TopologyMetricsData } from '../../data/graphql/topology/metrics/topology-metrics.model'; + +@Injectable() +export class TopologyDataSourceModelPropertiesService { + private nodeMetrics?: TopologyMetricsData; + private edgeMetrics?: TopologyMetricsData; + + public setModelProperties(nodeMetrics: TopologyMetricsData, edgeMetrics: TopologyMetricsData): void { + this.nodeMetrics = nodeMetrics; + this.edgeMetrics = edgeMetrics; + } + + public getPrimaryNodeMetric(): TopologyMetricWithCategoryData | undefined { + return this.nodeMetrics?.primary; + } + + public getSecondaryNodeMetric(): TopologyMetricWithCategoryData | undefined { + return this.nodeMetrics?.secondary; + } + + public getPrimaryEdgeMetric(): TopologyMetricWithCategoryData | undefined { + return this.edgeMetrics?.primary; + } + + public getSecondaryEdgeMetric(): TopologyMetricWithCategoryData | undefined { + return this.edgeMetrics?.secondary; + } + + public getAllNodeCategories(): TopologyMetricCategoryData[] { + return [this.nodeMetrics?.primary, this.nodeMetrics?.secondary, this.nodeMetrics?.others] + .flat() + .map(categoryData => categoryData?.categories ?? []) + .flat(); + } + + public getAllEdgeCategories(): TopologyMetricCategoryData[] { + return [this.edgeMetrics?.primary, this.edgeMetrics?.secondary, this.edgeMetrics?.others] + .flat() + .map(categoryData => categoryData?.categories ?? []) + .flat(); + } +} From dd26de0cd42b1bb10fe307ec3aa11a9154c5728a Mon Sep 17 00:00:00 2001 From: anandtiwary <52081890+anandtiwary@users.noreply.github.com> Date: Thu, 15 Jul 2021 18:33:34 -0700 Subject: [PATCH 2/2] refactor: adding test --- .../topology-metric-category.model.test.ts | 22 +++ ...opology-metric-with-category.model.test.ts | 72 ++++++++++ ...ta-source-model-properties.service.test.ts | 125 ++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.test.ts create mode 100644 projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.test.ts create mode 100644 projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.test.ts diff --git a/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.test.ts b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.test.ts new file mode 100644 index 000000000..6c09a13b2 --- /dev/null +++ b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-category.model.test.ts @@ -0,0 +1,22 @@ +import { Color } from '@hypertrace/common'; +import { createModelFactory } from '@hypertrace/dashboards/testing'; +import { TopologyMetricCategoryModel } from './topology-metric-category.model'; + +describe('Topology Metric with category model', () => { + const modelFactory = createModelFactory(); + + test('provides category name correctly', () => { + const spectator = modelFactory(TopologyMetricCategoryModel, { + properties: { + name: 'test name', + minValue: 0, + maxValue: 10, + fillColor: Color.Blue2, + strokeColor: Color.Blue3, + focusColor: Color.Blue4 + } + }); + + expect(spectator.model.getCategoryClassName()).toContain('test-name'); + }); +}); diff --git a/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.test.ts b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.test.ts new file mode 100644 index 000000000..4d496b2f1 --- /dev/null +++ b/projects/observability/src/shared/dashboard/data/graphql/topology/metrics/topology-metric-with-category.model.test.ts @@ -0,0 +1,72 @@ +import { Color } from '@hypertrace/common'; +import { createModelFactory } from '@hypertrace/dashboards/testing'; +import { MetricAggregationType } from '@hypertrace/distributed-tracing'; +import { MetricAggregationSpecificationModel } from '../../specifiers/metric-aggregation-specification.model'; +import { TopologyMetricCategoryModel } from './topology-metric-category.model'; +import { TopologyMetricWithCategoryModel } from './topology-metric-with-category.model'; + +describe('Topology Metric with category model', () => { + const modelFactory = createModelFactory(); + + const createCategoryModel = ( + name: string, + minValue: number, + fillColor: Color, + strokeColor: Color, + focusColor: Color, + maxValue?: number + ): TopologyMetricCategoryModel => { + const categoryModel = new TopologyMetricCategoryModel(); + categoryModel.name = name; + categoryModel.minValue = minValue; + categoryModel.maxValue = maxValue; + categoryModel.fillColor = fillColor; + categoryModel.strokeColor = strokeColor; + categoryModel.focusColor = focusColor; + + return categoryModel; + }; + test('provides category name correctly', () => { + const specification = new MetricAggregationSpecificationModel(); + specification.metric = 'metric-name'; + specification.aggregation = MetricAggregationType.Average; + specification.modelOnInit(); + + const categories = [ + createCategoryModel('first', 0, Color.Blue2, Color.Blue3, Color.Blue4, 10), + createCategoryModel('second', 10, Color.Red1, Color.Red3, Color.Red4, 50), + createCategoryModel('third', 50, Color.Blue2, Color.Blue3, Color.Blue4) + ]; + + const spectator = modelFactory(TopologyMetricWithCategoryModel, { + properties: { + specification: specification, + categories: categories + } + }); + + expect( + spectator.model.extractAndGetDataCategoryForMetric({ + [specification.resultAlias()]: { value: 50 } + }) + ).toEqual(categories[2]); + + expect( + spectator.model.extractAndGetDataCategoryForMetric({ + [specification.resultAlias()]: { value: 5 } + }) + ).toEqual(categories[0]); + + expect( + spectator.model.extractAndGetDataCategoryForMetric({ + [specification.resultAlias()]: { value: 22 } + }) + ).toEqual(categories[1]); + + expect( + spectator.model.extractAndGetDataCategoryForMetric({ + [specification.resultAlias()]: { value: -10 } + }) + ).toEqual(undefined); + }); +}); diff --git a/projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.test.ts b/projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.test.ts new file mode 100644 index 000000000..02c494f5f --- /dev/null +++ b/projects/observability/src/shared/dashboard/widgets/topology/topology-data-source-model-properties.service.test.ts @@ -0,0 +1,125 @@ +import { Color } from '@hypertrace/common'; +import { MetricAggregationType } from '@hypertrace/distributed-tracing'; +import { MetricAggregationSpecificationModel } from '@hypertrace/observability'; +import { createServiceFactory } from '@ngneat/spectator/jest'; +import { TopologyMetricCategoryModel } from '../../data/graphql/topology/metrics/topology-metric-category.model'; +import { TopologyMetricWithCategoryModel } from '../../data/graphql/topology/metrics/topology-metric-with-category.model'; +import { TopologyMetricsData } from '../../data/graphql/topology/metrics/topology-metrics.model'; +import { TopologyDataSourceModelPropertiesService } from './topology-data-source-model-properties.service'; + +describe('TopologyDataSourceModelPropertiesService', () => { + const createService = createServiceFactory({ + service: TopologyDataSourceModelPropertiesService + }); + + const createCategoryModel = ( + name: string, + minValue: number, + fillColor: Color, + strokeColor: Color, + focusColor: Color, + maxValue?: number + ): TopologyMetricCategoryModel => { + const categoryModel = new TopologyMetricCategoryModel(); + categoryModel.name = name; + categoryModel.minValue = minValue; + categoryModel.maxValue = maxValue; + categoryModel.fillColor = fillColor; + categoryModel.strokeColor = strokeColor; + categoryModel.focusColor = focusColor; + + return categoryModel; + }; + + const createSpecificationModel = (metric: string, aggregation: MetricAggregationType) => { + const specification = new MetricAggregationSpecificationModel(); + specification.metric = metric; + specification.aggregation = aggregation; + + specification.modelOnInit(); + + return specification; + }; + + const createMetricWithCategory = ( + spec: MetricAggregationSpecificationModel, + categories: TopologyMetricCategoryModel[] + ) => { + const model = new TopologyMetricWithCategoryModel(); + model.specification = spec; + model.categories = categories; + + return model; + }; + + test('should return correct results', () => { + const spectator = createService(); + + const nodePrimary = createMetricWithCategory( + createSpecificationModel('node-metric-1', MetricAggregationType.Average), + [ + createCategoryModel('node-first-1', 0, Color.Blue2, Color.Blue3, Color.Blue4, 10), + createCategoryModel('node-second-1', 10, Color.Red1, Color.Red3, Color.Red4, 50), + createCategoryModel('node-third-1', 50, Color.Blue2, Color.Blue3, Color.Blue4) + ] + ); + + const nodeSecondary = createMetricWithCategory( + createSpecificationModel('node-metric-2', MetricAggregationType.Average), + [ + createCategoryModel('node-first-2', 0, Color.Blue2, Color.Blue3, Color.Blue4, 10), + createCategoryModel('node-second-2', 10, Color.Red1, Color.Red3, Color.Red4, 50), + createCategoryModel('node-third-2', 50, Color.Blue2, Color.Blue3, Color.Blue4) + ] + ); + + const nodeOthers = [ + createMetricWithCategory(createSpecificationModel('node-metric-5', MetricAggregationType.Average), [ + createCategoryModel('node-others-2', 0, Color.Blue2, Color.Blue3, Color.Blue4, 10) + ]) + ]; + + const nodeMetrics: TopologyMetricsData = { + primary: nodePrimary, + secondary: nodeSecondary, + others: nodeOthers + }; + + const edgePrimary = createMetricWithCategory( + createSpecificationModel('edge-metric-3', MetricAggregationType.Average), + [ + createCategoryModel('edge-first-1', 0, Color.Blue2, Color.Blue3, Color.Blue4, 10), + createCategoryModel('edge-second-1', 10, Color.Red1, Color.Red3, Color.Red4, 50), + createCategoryModel('edge-third-1', 50, Color.Blue2, Color.Blue3, Color.Blue4) + ] + ); + + const edgeSecondary = createMetricWithCategory( + createSpecificationModel('metric-4', MetricAggregationType.Average), + [ + createCategoryModel('edge-first-2', 0, Color.Blue2, Color.Blue3, Color.Blue4, 10), + createCategoryModel('edge-second-2', 10, Color.Red1, Color.Red3, Color.Red4, 50), + createCategoryModel('edge-third-2', 50, Color.Blue2, Color.Blue3, Color.Blue4) + ] + ); + + const edgeOthers = [ + createMetricWithCategory(createSpecificationModel('metric-4', MetricAggregationType.Average), [ + createCategoryModel('edge-others-2', 0, Color.Blue2, Color.Blue3, Color.Blue4, 10) + ]) + ]; + + const edgeMetrics: TopologyMetricsData = { + primary: edgePrimary, + secondary: edgeSecondary, + others: edgeOthers + }; + spectator.service.setModelProperties(nodeMetrics, edgeMetrics); + + expect(spectator.service.getPrimaryNodeMetric()).toEqual(nodePrimary); + expect(spectator.service.getSecondaryNodeMetric()).toEqual(nodeSecondary); + + expect(spectator.service.getPrimaryEdgeMetric()).toEqual(edgePrimary); + expect(spectator.service.getSecondaryEdgeMetric()).toEqual(edgeSecondary); + }); +});