Skip to content

Commit

Permalink
Expose measures for metrics on MFEngine (#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
courtneyholcomb authored Aug 29, 2023
1 parent 42d5d03 commit 30e9a02
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20230823-131738.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Expose measures for metrics on MFEngine with agg_time_dimension
time: 2023-08-23T13:17:38.517068-07:00
custom:
Author: courtneyholcomb
Issue: "735"
30 changes: 28 additions & 2 deletions metricflow/engine/metricflow_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import pandas as pd
from dbt_semantic_interfaces.implementations.elements.dimension import PydanticDimensionTypeParams
from dbt_semantic_interfaces.pretty_print import pformat_big_objects
from dbt_semantic_interfaces.references import EntityReference, MetricReference
from dbt_semantic_interfaces.references import EntityReference, MeasureReference, MetricReference
from dbt_semantic_interfaces.type_enums import DimensionType

from metricflow.assert_one_arg import assert_exactly_one_arg_set
Expand All @@ -27,7 +27,7 @@
from metricflow.dataset.convert_semantic_model import SemanticModelToDataSetConverter
from metricflow.dataset.dataset import DataSet
from metricflow.dataset.semantic_model_adapter import SemanticModelDataSet
from metricflow.engine.models import Dimension, Entity, Metric
from metricflow.engine.models import Dimension, Entity, Measure, Metric
from metricflow.engine.time_source import ServerTimeSource
from metricflow.errors.errors import ExecutionException
from metricflow.execution.execution_plan import ExecutionPlan, SqlQuery
Expand Down Expand Up @@ -494,6 +494,32 @@ def _create_execution_plan(self, mf_query_request: MetricFlowQueryRequest) -> Me
def explain(self, mf_request: MetricFlowQueryRequest) -> MetricFlowExplainResult: # noqa: D
return self._create_execution_plan(mf_request)

def get_measures_for_metrics(self, metric_names: List[str]) -> List[Measure]: # noqa: D
metrics = self._semantic_manifest_lookup.metric_lookup.get_metrics(
metric_references=[MetricReference(element_name=metric_name) for metric_name in metric_names]
)
semantic_model_lookup = self._semantic_manifest_lookup.semantic_model_lookup

measures = set()
for metric in metrics:
for input_measure in metric.input_measures:
measure_reference = MeasureReference(element_name=input_measure.name)
# populate new obj
measure = semantic_model_lookup.get_measure(measure_reference=measure_reference)
measures.add(
Measure(
name=measure.name,
agg=measure.agg,
agg_time_dimension=semantic_model_lookup.get_agg_time_dimension_for_measure(
measure_reference=measure_reference
).element_name,
description=measure.description,
expr=measure.expr,
agg_params=measure.agg_params,
)
)
return list(measures)

def simple_dimensions_for_metrics( # noqa: D
self,
metric_names: List[str],
Expand Down
14 changes: 14 additions & 0 deletions metricflow/engine/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
DimensionTypeParams,
)
from dbt_semantic_interfaces.protocols.entity import Entity as SemanticManifestEntity
from dbt_semantic_interfaces.protocols.measure import MeasureAggregationParameters
from dbt_semantic_interfaces.protocols.metadata import Metadata
from dbt_semantic_interfaces.protocols.metric import Metric as SemanticManifestMetric
from dbt_semantic_interfaces.protocols.metric import MetricInputMeasure, MetricType, MetricTypeParams
from dbt_semantic_interfaces.protocols.where_filter import WhereFilter
from dbt_semantic_interfaces.transformations.add_input_metric_measures import AddInputMetricMeasuresRule
from dbt_semantic_interfaces.type_enums.aggregation_type import AggregationType
from dbt_semantic_interfaces.type_enums.entity_type import EntityType

from metricflow.model.semantics.linkable_spec_resolver import ElementPathKey
Expand Down Expand Up @@ -133,3 +135,15 @@ def from_pydantic(cls, pydantic_entity: SemanticManifestEntity) -> Entity:
role=pydantic_entity.role,
expr=pydantic_entity.expr,
)


@dataclass(frozen=True)
class Measure:
"""Dataclass representation of a Measure."""

name: str
agg: AggregationType
agg_time_dimension: str
description: Optional[str] = None
expr: Optional[str] = None
agg_params: Optional[MeasureAggregationParameters] = None
26 changes: 26 additions & 0 deletions metricflow/test/api/test_metricflow_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,32 @@ def test_list_dimensions(mf_client: MetricFlowClient) -> None: # noqa: D
assert tuple(dim.name for dim in dimensions) == ("metric_time", "metric_time")


def test_get_measures_for_metrics(mf_client: MetricFlowClient) -> None: # noqa: D
measures = mf_client.engine.get_measures_for_metrics(["bookings"])
assert len(measures) == 1
measure = measures[0]
assert measure.name == "bookings"
assert measure.agg_time_dimension == "ds"

# Multiple metrics
measures = mf_client.engine.get_measures_for_metrics(["bookings", "revenue"])
assert len(measures) == 2
assert {measure.name for measure in measures} == {"bookings", "txn_revenue"}
assert {measure.agg_time_dimension for measure in measures} == {"ds"}

# Derived metric with multiple metric inputs
measures = mf_client.engine.get_measures_for_metrics(["views_times_booking_value"])
assert len(measures) == 2
assert {measure.name for measure in measures} == {"views", "booking_value"}
assert {measure.agg_time_dimension for measure in measures} == {"ds"}

# Ratio metric with multiple measure inputs
measures = mf_client.engine.get_measures_for_metrics(["bookings_per_booker"])
assert len(measures) == 2
assert {measure.name for measure in measures} == {"bookings", "bookers"}
assert {measure.agg_time_dimension for measure in measures} == {"ds"}


def test_get_dimension_values(mf_client: MetricFlowClient) -> None: # noqa: D
dim_vals = mf_client.get_dimension_values(
["bookings"], "metric_time", start_time="2020-01-01", end_time="2024-01-01"
Expand Down

0 comments on commit 30e9a02

Please sign in to comment.