Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Conversion Metrics Properties #209

Merged
merged 9 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20231127-124601.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Added spec changes for conversion metrics.
time: 2023-11-27T12:46:01.036548-05:00
custom:
Author: WilliamDee
Issue: "210"
27 changes: 25 additions & 2 deletions dbt_semantic_interfaces/implementations/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
)
from dbt_semantic_interfaces.implementations.metadata import PydanticMetadata
from dbt_semantic_interfaces.references import MeasureReference, MetricReference
from dbt_semantic_interfaces.type_enums import MetricType, TimeGranularity
from dbt_semantic_interfaces.type_enums import (
ConversionCalculationType,
MetricType,
TimeGranularity,
)


class PydanticMetricInputMeasure(PydanticCustomInputParser, HashableBaseModel):
Expand Down Expand Up @@ -114,6 +118,13 @@ def parse(window: str) -> PydanticMetricTimeWindow:
)


class PydanticConstantPropertyInput(HashableBaseModel):
"""Input of a constant property used in conversion metrics."""

base_property: str
conversion_property: str


class PydanticMetricInput(HashableBaseModel):
"""Provides a pointer to a metric along with the additional properties used on that metric."""

Expand All @@ -134,6 +145,17 @@ def post_aggregation_reference(self) -> MetricReference:
return MetricReference(element_name=self.alias or self.name)


class PydanticConversionTypeParams(HashableBaseModel):
"""Type params to provide context for conversion metrics properties."""

base_measure: PydanticMetricInputMeasure
conversion_measure: PydanticMetricInputMeasure
entity: str
calculation: ConversionCalculationType = ConversionCalculationType.CONVERSION_RATE
window: Optional[PydanticMetricTimeWindow]
constant_properties: Optional[List[PydanticConstantPropertyInput]]


class PydanticMetricTypeParams(HashableBaseModel):
"""Type params add additional context to certain metric types (the context depends on the metric type)."""

Expand All @@ -144,6 +166,7 @@ class PydanticMetricTypeParams(HashableBaseModel):
window: Optional[PydanticMetricTimeWindow]
grain_to_date: Optional[TimeGranularity]
metrics: Optional[List[PydanticMetricInput]]
conversion_type_params: Optional[PydanticConversionTypeParams]

input_measures: List[PydanticMetricInputMeasure] = Field(default_factory=list)

Expand Down Expand Up @@ -172,7 +195,7 @@ def measure_references(self) -> List[MeasureReference]:
@property
def input_metrics(self) -> Sequence[PydanticMetricInput]:
"""Return the associated input metrics for this metric."""
if self.type is MetricType.SIMPLE or self.type is MetricType.CUMULATIVE:
if self.type is MetricType.SIMPLE or self.type is MetricType.CUMULATIVE or self.type is MetricType.CONVERSION:
return ()
elif self.type is MetricType.DERIVED:
assert self.type_params.metrics is not None, f"{MetricType.DERIVED} should have type_params.metrics set"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,61 @@
},
"type": "object"
},
"constant_property_input_schema": {
"$id": "constant_property_input_schema",
"additionalProperties": false,
"properties": {
"base_property": {
"type": "string"
},
"conversion_property": {
"type": "string"
}
},
"required": [
"base_property",
"conversion_property"
],
"type": "object"
},
"conversion_type_params_schema": {
"$id": "conversion_type_params_schema",
"additionalProperties": false,
"properties": {
"base_measure": {
"$ref": "#/definitions/metric_input_measure_schema"
},
"calculation": {
"enum": [
"CONVERSIONS",
"CONVERSION_RATE",
"conversions",
"conversion_rate"
]
},
"constant_properties": {
"items": {
"$ref": "#/definitions/constant_property_input_schema"
},
"type": "array"
},
"conversion_measure": {
"$ref": "#/definitions/metric_input_measure_schema"
},
"entity": {
"type": "string"
},
"window": {
"type": "string"
}
},
"required": [
"base_measure",
"conversion_measure",
"entity"
],
"type": "object"
},
"dimension_schema": {
"$id": "dimension_schema",
"additionalProperties": false,
Expand Down Expand Up @@ -347,10 +402,12 @@
"RATIO",
"CUMULATIVE",
"DERIVED",
"CONVERSION",
"simple",
"ratio",
"cumulative",
"derived"
"derived",
"conversion"
]
},
"type_params": {
Expand All @@ -368,6 +425,9 @@
"$id": "metric_type_params",
"additionalProperties": false,
"properties": {
"conversion_type_params": {
"$ref": "#/definitions/conversion_type_params_schema"
},
"denominator": {
"$ref": "#/definitions/metric_input_measure_schema"
},
Expand Down
34 changes: 33 additions & 1 deletion dbt_semantic_interfaces/parsing/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@


# Enums
metric_types_enum_values = ["SIMPLE", "RATIO", "CUMULATIVE", "DERIVED"]
metric_types_enum_values = ["SIMPLE", "RATIO", "CUMULATIVE", "DERIVED", "CONVERSION"]
WilliamDee marked this conversation as resolved.
Show resolved Hide resolved
metric_types_enum_values += [x.lower() for x in metric_types_enum_values]

calculation_types_enum_values = ["CONVERSIONS", "CONVERSION_RATE"]
calculation_types_enum_values += [x.lower() for x in calculation_types_enum_values]

entity_type_enum_values = ["PRIMARY", "UNIQUE", "FOREIGN", "NATURAL"]
entity_type_enum_values += [x.lower() for x in entity_type_enum_values]

Expand Down Expand Up @@ -85,6 +88,32 @@
"additionalProperties": False,
}

conversion_type_params_schema = {
"$id": "conversion_type_params_schema",
"type": "object",
"properties": {
"base_measure": {"$ref": "metric_input_measure_schema"},
"conversion_measure": {"$ref": "metric_input_measure_schema"},
"calculation": {"enum": calculation_types_enum_values},
"entity": {"type": "string"},
"window": {"type": "string"},
"constant_properties": {"type": "array", "items": {"$ref": "constant_property_input_schema"}},
},
"additionalProperties": False,
"required": ["base_measure", "conversion_measure", "entity"],
}

constant_property_input_schema = {
"$id": "constant_property_input_schema",
"type": "object",
"properties": {
"base_property": {"type": "string"},
"conversion_property": {"type": "string"},
},
"additionalProperties": False,
"required": ["base_property", "conversion_property"],
}

metric_type_params_schema = {
"$id": "metric_type_params",
"type": "object",
Expand All @@ -99,6 +128,7 @@
"type": "array",
"items": {"$ref": "metric_input_schema"},
},
"conversion_type_params": {"$ref": "conversion_type_params_schema"},
},
"additionalProperties": False,
}
Expand Down Expand Up @@ -382,6 +412,8 @@
filter_schema["$id"]: filter_schema,
metric_input_measure_schema["$id"]: metric_input_measure_schema,
metric_type_params_schema["$id"]: metric_type_params_schema,
conversion_type_params_schema["$id"]: conversion_type_params_schema,
constant_property_input_schema["$id"]: constant_property_input_schema,
entity_schema["$id"]: entity_schema,
measure_schema["$id"]: measure_schema,
dimension_schema["$id"]: dimension_schema,
Expand Down
2 changes: 2 additions & 0 deletions dbt_semantic_interfaces/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
)
from dbt_semantic_interfaces.protocols.metadata import FileSlice, Metadata # noqa:F401
from dbt_semantic_interfaces.protocols.metric import ( # noqa:F401
ConstantPropertyInput,
ConversionTypeParams,
Metric,
MetricInput,
MetricInputMeasure,
Expand Down
72 changes: 71 additions & 1 deletion dbt_semantic_interfaces/protocols/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
from dbt_semantic_interfaces.protocols.metadata import Metadata
from dbt_semantic_interfaces.protocols.where_filter import WhereFilterIntersection
from dbt_semantic_interfaces.references import MeasureReference, MetricReference
from dbt_semantic_interfaces.type_enums import MetricType, TimeGranularity
from dbt_semantic_interfaces.type_enums import (
ConversionCalculationType,
MetricType,
TimeGranularity,
)


class MetricInputMeasure(Protocol):
Expand Down Expand Up @@ -113,6 +117,67 @@ def post_aggregation_reference(self) -> MetricReference:
pass


class ConstantPropertyInput(Protocol):
"""Provides the constant property set for conversion metrics.

Constant properties are additional elements linking a base event to a conversion event.
The specified properties will typically be a reference to a dimension or entity, and will be used
to join the base event to the final conversion event. Typical constant properties are things like
session keys (for services where conversions are measured within a user session), or secondary entities
(like a user/application pair for an app platform or a user/shop pair for a retail/online storefront platform).
"""

@property
@abstractmethod
def base_property(self) -> str: # noqa: D
pass

@property
@abstractmethod
def conversion_property(self) -> str: # noqa: D
pass


class ConversionTypeParams(Protocol):
"""Type params to provide context for conversion metrics properties."""

@property
@abstractmethod
def base_measure(self) -> MetricInputMeasure:
"""Measure used to calculate the base event."""
pass

@property
@abstractmethod
def conversion_measure(self) -> MetricInputMeasure:
"""Measure used to calculate the conversion event."""
pass

@property
@abstractmethod
def entity(self) -> str:
"""Specified join entity."""
pass

@property
@abstractmethod
def calculation(self) -> ConversionCalculationType:
"""Type of conversion metric calculation."""
pass

@property
@abstractmethod
def window(self) -> Optional[MetricTimeWindow]:
"""Maximum time range for finding successive conversion events."""
pass

@property
@abstractmethod
def constant_properties(self) -> Optional[Sequence[ConstantPropertyInput]]:
"""Return the list of defined constant properties."""
pass


class MetricTypeParams(Protocol):
"""Type params add additional context to certain metric types (the context depends on the metric type)."""

Expand Down Expand Up @@ -157,6 +222,11 @@ def grain_to_date(self) -> Optional[TimeGranularity]: # noqa: D
def metrics(self) -> Optional[Sequence[MetricInput]]: # noqa: D
pass

@property
@abstractmethod
def conversion_type_params(self) -> Optional[ConversionTypeParams]: # noqa: D
pass


class Metric(Protocol):
"""Describes a metric."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ def _get_measures_for_metric(
measures.update(
AddInputMetricMeasuresRule._get_measures_for_metric(semantic_manifest, input_metric.name)
)
elif matched_metric.type is MetricType.CONVERSION:
conversion_type_params = matched_metric.type_params.conversion_type_params
assert conversion_type_params, "Conversion metric should have conversion_type_params."
measures.add(conversion_type_params.base_measure)
measures.add(conversion_type_params.conversion_measure)
else:
assert_values_exhausted(matched_metric.type)
else:
Expand Down
3 changes: 3 additions & 0 deletions dbt_semantic_interfaces/type_enums/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from dbt_semantic_interfaces.type_enums.aggregation_type import ( # noqa:F401
AggregationType,
)
from dbt_semantic_interfaces.type_enums.conversion_calculation_type import ( # noqa:F401
ConversionCalculationType,
)
from dbt_semantic_interfaces.type_enums.dimension_type import DimensionType # noqa:F401
from dbt_semantic_interfaces.type_enums.entity_type import EntityType # noqa:F401
from dbt_semantic_interfaces.type_enums.metric_type import MetricType # noqa:F401
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from dbt_semantic_interfaces.enum_extension import ExtendedEnum


class ConversionCalculationType(ExtendedEnum):
"""Types of calculations for a conversion metric."""

CONVERSIONS = "conversions"
CONVERSION_RATE = "conversion_rate"
1 change: 1 addition & 0 deletions dbt_semantic_interfaces/type_enums/metric_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ class MetricType(ExtendedEnum):
RATIO = "ratio"
CUMULATIVE = "cumulative"
DERIVED = "derived"
CONVERSION = "conversion"
Loading
Loading