From 87ede20e0e033e8c0b96a44effc093faf82ccf47 Mon Sep 17 00:00:00 2001 From: Adrian Mroz Date: Wed, 15 Feb 2023 10:12:47 +0100 Subject: [PATCH] usedMeasures function --- src/common/models/measure/measure.fixtures.ts | 4 + src/common/models/series/expression-series.ts | 15 +-- src/common/models/series/measure-series.ts | 4 - src/common/models/series/quantile-series.ts | 4 - src/common/models/series/series.ts | 1 - .../models/series/used-measures.mocha.ts | 123 ++++++++++++++++++ src/common/models/series/used-measures.ts | 44 +++++++ .../routes/query/routes/visualization.ts | 3 +- 8 files changed, 174 insertions(+), 24 deletions(-) create mode 100644 src/common/models/series/used-measures.mocha.ts create mode 100644 src/common/models/series/used-measures.ts diff --git a/src/common/models/measure/measure.fixtures.ts b/src/common/models/measure/measure.fixtures.ts index 811664dd8..40402ccfd 100644 --- a/src/common/models/measure/measure.fixtures.ts +++ b/src/common/models/measure/measure.fixtures.ts @@ -39,6 +39,10 @@ export class MeasureFixtures { return createMeasure("avg_delta", $("main").average($("delta"))); } + static histogram(): Measure { + return createMeasure("histogram", $("main").quantile($("create_to_collect_duration_histogram"), 0.95, "k=128")); + } + static wikiCountJS(): MeasureJS { return { name: "count", diff --git a/src/common/models/series/expression-series.ts b/src/common/models/series/expression-series.ts index f61de3a09..dc8b3945d 100644 --- a/src/common/models/series/expression-series.ts +++ b/src/common/models/series/expression-series.ts @@ -16,7 +16,7 @@ import { Record } from "immutable"; import { RequireOnly } from "../../utils/functional/functional"; -import { Expression, ExpressionSeriesOperation, fromJS } from "../expression/expression"; +import { Expression, fromJS } from "../expression/expression"; import { getNameWithDerivation, SeriesDerivation } from "./concrete-series"; import { BasicSeriesValue, SeriesBehaviours } from "./series"; import { DEFAULT_FORMAT, SeriesFormat } from "./series-format"; @@ -58,17 +58,4 @@ export class ExpressionSeries extends Record(defaultSerie plywoodKey(period = SeriesDerivation.CURRENT): string { return getNameWithDerivation(this.key(), period); } - - measures(): string[] { - switch (this.expression.operation) { - case ExpressionSeriesOperation.PERCENT_OF_PARENT: - case ExpressionSeriesOperation.PERCENT_OF_TOTAL: - return [this.reference]; - case ExpressionSeriesOperation.ADD: - case ExpressionSeriesOperation.SUBTRACT: - case ExpressionSeriesOperation.MULTIPLY: - case ExpressionSeriesOperation.DIVIDE: - return [this.reference, this.expression.reference]; - } - } } diff --git a/src/common/models/series/measure-series.ts b/src/common/models/series/measure-series.ts index ce23d7215..9bbfde27a 100644 --- a/src/common/models/series/measure-series.ts +++ b/src/common/models/series/measure-series.ts @@ -54,8 +54,4 @@ export class MeasureSeries extends Record(defaultMeasureSeri plywoodKey(derivation = SeriesDerivation.CURRENT): string { return getNameWithDerivation(this.reference, derivation); } - - measures(): string[] { - return [this.reference]; - } } diff --git a/src/common/models/series/quantile-series.ts b/src/common/models/series/quantile-series.ts index 48626956d..935c2b972 100644 --- a/src/common/models/series/quantile-series.ts +++ b/src/common/models/series/quantile-series.ts @@ -71,8 +71,4 @@ export class QuantileSeries extends Record(defaultQuantileS plywoodKey(derivation = SeriesDerivation.CURRENT): string { return getNameWithDerivation(this.key(), derivation); } - - measures(): string[] { - return [this.reference]; - } } diff --git a/src/common/models/series/series.ts b/src/common/models/series/series.ts index 95e8b7eb7..b30d7c376 100644 --- a/src/common/models/series/series.ts +++ b/src/common/models/series/series.ts @@ -30,7 +30,6 @@ export interface BasicSeriesValue { export interface SeriesBehaviours { key: () => string; plywoodKey: (period?: SeriesDerivation) => string; - measures: () => string[]; } export type Series = MeasureSeries | ExpressionSeries | QuantileSeries; diff --git a/src/common/models/series/used-measures.mocha.ts b/src/common/models/series/used-measures.mocha.ts new file mode 100644 index 000000000..764ba35e4 --- /dev/null +++ b/src/common/models/series/used-measures.mocha.ts @@ -0,0 +1,123 @@ +/* + * Copyright 2017-2022 Allegro.pl + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from "chai"; +import { ArithmeticExpression } from "../expression/concreteArithmeticOperation"; +import { ExpressionSeriesOperation } from "../expression/expression"; +import { PercentExpression } from "../expression/percent"; +import { MeasureFixtures } from "../measure/measure.fixtures"; +import { ExpressionSeries } from "./expression-series"; +import { MeasureSeries } from "./measure-series"; +import { QuantileSeries } from "./quantile-series"; +import { usedMeasures } from "./used-measures"; + +const avgDelta = MeasureFixtures.avgDelta(); +const avgAdded = MeasureFixtures.avgAdded(); +const histogram = MeasureFixtures.histogram(); + +describe("usedMeasures", () => { + describe("MeasureSeries", () => { + it("should return array with measure reference", () => { + const series = MeasureSeries.fromMeasure(avgDelta); + expect(usedMeasures(series)).to.be.deep.equal(["avg_delta"]); + }); + }); + + describe("QuantileSeries", () => { + it("should return array with measure reference", () => { + const series = QuantileSeries.fromQuantileMeasure(histogram); + expect(usedMeasures(series)).to.be.deep.equal(["histogram"]); + }); + }); + + describe("ExpressionSeries", () => { + describe("Percent of total", () => { + it("should return array with measure reference", () => { + const series = ExpressionSeries.fromJS({ + reference: avgDelta.name, + expression: new PercentExpression({ + operation: ExpressionSeriesOperation.PERCENT_OF_TOTAL + }) + }); + expect(usedMeasures(series)).to.be.deep.equal(["avg_delta"]); + }); + }); + + describe("Percent of parent", () => { + it("should return array with measure reference", () => { + const series = ExpressionSeries.fromJS({ + reference: avgDelta.name, + expression: new PercentExpression({ + operation: ExpressionSeriesOperation.PERCENT_OF_PARENT + }) + }); + expect(usedMeasures(series)).to.be.deep.equal(["avg_delta"]); + }); + }); + + describe("Arithmetic ADD", () => { + it("should return array with measure reference and reference of operand", () => { + const series = ExpressionSeries.fromJS({ + reference: avgDelta.name, + expression: new ArithmeticExpression({ + operation: ExpressionSeriesOperation.ADD, + reference: avgAdded.name + }) + }); + expect(usedMeasures(series)).to.be.deep.equal(["avg_delta", "avg_added"]); + }); + }); + + describe("Arithmetic SUBTRACT", () => { + it("should return array with measure reference and reference of operand", () => { + const series = ExpressionSeries.fromJS({ + reference: avgDelta.name, + expression: new ArithmeticExpression({ + operation: ExpressionSeriesOperation.SUBTRACT, + reference: avgAdded.name + }) + }); + expect(usedMeasures(series)).to.be.deep.equal(["avg_delta", "avg_added"]); + }); + }); + + describe("Arithmetic MULTIPLY", () => { + it("should return array with measure reference and reference of operand", () => { + const series = ExpressionSeries.fromJS({ + reference: avgDelta.name, + expression: new ArithmeticExpression({ + operation: ExpressionSeriesOperation.MULTIPLY, + reference: avgAdded.name + }) + }); + expect(usedMeasures(series)).to.be.deep.equal(["avg_delta", "avg_added"]); + }); + }); + + describe("Arithmetic DIVIDE", () => { + it("should return array with measure reference and reference of operand", () => { + const series = ExpressionSeries.fromJS({ + reference: avgDelta.name, + expression: new ArithmeticExpression({ + operation: ExpressionSeriesOperation.DIVIDE, + reference: avgAdded.name + }) + }); + expect(usedMeasures(series)).to.be.deep.equal(["avg_delta", "avg_added"]); + }); + }); + }); +}); diff --git a/src/common/models/series/used-measures.ts b/src/common/models/series/used-measures.ts new file mode 100644 index 000000000..5f2884ab9 --- /dev/null +++ b/src/common/models/series/used-measures.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2017-2022 Allegro.pl + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ExpressionSeriesOperation } from "../expression/expression"; +import { ExpressionSeries } from "./expression-series"; +import { Series } from "./series"; +import { SeriesType } from "./series-type"; + +function usedMeasuresInExpressionSeries(series: ExpressionSeries): string[] { + switch (series.expression.operation) { + case ExpressionSeriesOperation.PERCENT_OF_PARENT: + case ExpressionSeriesOperation.PERCENT_OF_TOTAL: + return [series.reference]; + case ExpressionSeriesOperation.ADD: + case ExpressionSeriesOperation.SUBTRACT: + case ExpressionSeriesOperation.MULTIPLY: + case ExpressionSeriesOperation.DIVIDE: + return [series.reference, series.expression.reference]; + } +} + +export function usedMeasures(series: Series): string[] { + switch (series.type) { + case SeriesType.MEASURE: + return [series.reference]; + case SeriesType.EXPRESSION: + return usedMeasuresInExpressionSeries(series); + case SeriesType.QUANTILE: + return [series.reference]; + } +} diff --git a/src/server/routes/query/routes/visualization.ts b/src/server/routes/query/routes/visualization.ts index f33108f9c..a13827e79 100644 --- a/src/server/routes/query/routes/visualization.ts +++ b/src/server/routes/query/routes/visualization.ts @@ -21,6 +21,7 @@ import makeGridQuery from "../../../../client/visualizations/grid/make-query"; import { Logger } from "../../../../common/logger/logger"; import { Essence } from "../../../../common/models/essence/essence"; import { FixedTimeFilterClause } from "../../../../common/models/filter-clause/filter-clause"; +import { usedMeasures } from "../../../../common/models/series/used-measures"; import { Timekeeper } from "../../../../common/models/timekeeper/timekeeper"; import makeQuery from "../../../../common/utils/query/visualization-query"; import { executeQuery } from "../../../utils/query/execute-query"; @@ -70,7 +71,7 @@ function logQueryInfo(essence: Essence, timekeeper: Timekeeper, logger: Logger) visualization: essence.visualization.name, filters: nonTimeFilters.clauses.map(clause => clause.reference).toArray(), splits: essence.splits.splits.map(split => split.reference).toArray(), - measures: essence.series.series.flatMap(series => series.measures()).toSet().toArray() + measures: essence.series.series.flatMap(usedMeasures).toSet().toArray() }); }