MetricFlow
MetricFlow is a Python library (version 0.209.0) developed by dbt Labs that serves as the engine for defining, querying, and serving metrics from dbt projects. It translates high-level metric definitions into reusable SQL and executes them against various data platforms. While it powers the dbt Semantic Layer, direct programmatic API usage is primarily for advanced scenarios like custom metric servers or programmatic SQL generation, rather than typical application-level querying. Releases typically align with dbt Core release cycles or critical updates for MetricFlow's standalone capabilities.
Common errors
-
ModuleNotFoundError: No module named 'metricflow'
cause The `metricflow` package is not installed in the active Python environment, or the environment is not correctly activated.fixRun `pip install metricflow` to install the package. If using virtual environments, ensure the correct environment is activated before running your script. -
Metric not found: 'my_metric_name'
cause The requested metric name does not exist in the loaded semantic manifest, or there's a typo in the name, or the semantic model file wasn't loaded correctly.fixVerify the exact spelling and casing of the metric name in your `MetricRequest` against its definition in your semantic model YAML. Ensure the `dbt_project_path` in `MetricFlowConfig` correctly points to your dbt project containing the semantic models. -
dbt.exceptions.MissingProfileError: Could not find profile named 'default'
cause MetricFlow, like dbt, needs a `profiles.yml` file to connect to data warehouses. The specified profile (or the default 'default') is missing or misconfigured.fixEnsure a `profiles.yml` file is present in your dbt profiles directory (usually `~/.dbt/`). Verify that the `profile` key in `dbt_project.yml` matches a profile in `profiles.yml`. -
metricflow.errors.MetricFlowException: Could not resolve measure 'some_measure' for metric 'some_metric'
cause A metric's `calculation_config` references a measure that is not defined within the same semantic model, or the measure name is incorrect.fixCheck the `measures` section of your semantic model YAML. Ensure that the `measure` referenced by a metric's `calculation_config` exists and is spelled correctly within that specific semantic model.
Warnings
- breaking MetricFlow has tight Python version requirements. Version 0.209.0 requires Python >=3.9 and <3.13. Using incompatible Python versions can lead to installation failures or runtime errors.
- breaking MetricFlow relies on specific versions of `dbt-common`, `dbt-extractor`, and `dbt-semantic-interfaces`. Upgrading these dependencies independently or with incompatible versions of dbt-core can cause dependency conflicts.
- gotcha Ambiguous semantic model definitions or incorrect metric/dimension names can lead to 'Metric not found' or 'Dimension not found' errors, even if the names appear correct in YAML.
- breaking The YAML syntax for defining semantic models and metrics has evolved. Older syntax (e.g., `primary_entity` instead of `entities`) or deprecated configurations might no longer be supported.
Install
-
pip install metricflow
Imports
- MetricFlowEngine
from metricflow.engine.metricflow_engine import MetricFlowEngine
- MetricFlowConfig
from metricflow.config.metricflow_config import MetricFlowConfig
- MetricFlowQuerySpec
from metricflow.specs.query_specs import MetricFlowQuerySpec
Quickstart
import os
import tempfile
from pathlib import Path
import shutil
from metricflow.engine.metricflow_engine import MetricFlowEngine
from metricflow.config.metricflow_config import MetricFlowConfig
from metricflow.connection.null_metricflow_connection import NullMetricFlowConnection
from metricflow.specs.query_specs import MetricFlowQuerySpec, MetricTimeDimension
from metricflow.specs.metric_request import MetricRequest
from metricflow.specs.dimension_spec import DimensionSpec
# This quickstart demonstrates programmatic SQL generation for a minimal semantic model.
# Actual execution requires a configured database connection.
# 1. Create a dummy dbt project directory with a semantic model YAML file
temp_dir = Path(tempfile.mkdtemp())
dbt_project_dir = temp_dir / "my_dbt_project"
dbt_project_dir.mkdir()
(dbt_project_dir / "dbt_project.yml").write_text("""
name: 'my_dbt_project'
version: '1.0.0'
config-version: 2
profile: 'default'
""")
models_dir = dbt_project_dir / "models"
models_dir.mkdir()
(models_dir / "my_semantic_model.yml").write_text("""
semantic_models:
- name: my_transactions_semantic_model
description: "Transactions data"
entities:
- name: user_id
type: primary
measures:
- name: sum_amount
agg: sum
expr: amount
dimensions:
- name: transaction_date
type: time
expr: created_at
time_granularity: day
metrics:
- name: total_revenue
calculation_config:
measure: sum_amount
""")
# 2. Configure MetricFlow by pointing to the dbt project
mf_config = MetricFlowConfig(
dbt_project_path=str(dbt_project_dir)
)
# 3. Use NullMetricFlowConnection for generating SQL plans without executing against a real DB
mf_connection = NullMetricFlowConnection()
# 4. Initialize MetricFlowEngine
engine = MetricFlowEngine(mf_config, mf_connection)
# 5. Define a query for the 'total_revenue' metric, grouped by user_id and day
metric_requests = [
MetricRequest(metric_name="total_revenue")
]
time_dimension = MetricTimeDimension(
grain="day",
date_spec=('2023-01-01', '2023-01-31')
)
query_spec = MetricFlowQuerySpec(
metric_requests=metric_requests,
group_by_dimensions=[DimensionSpec(element_name="user_id")],
time_dimension=time_dimension
)
print("\n--- Generating SQL Query Plan ---")
try:
# plan_query returns the SQL query string for the given spec
query_plan_result = engine.plan_query(query_spec)
print("Generated SQL Query:")
print(query_plan_result.sql_query)
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Clean up the temporary dbt project directory
shutil.rmtree(temp_dir)