Metrics
Metrics define how to aggregate and calculate measures. Sidemantic distinguishes between model-level metrics (aggregations) and graph-level metrics (formulas/references).
Model-Level Metrics
Model-level metrics are aggregations defined on a single model. These become building blocks for graph-level metrics.
Simple Aggregations
Basic aggregations on a single column:
models:
- name: orders
metrics:
- name: revenue
agg: sum
sql: amount
- name: order_count
agg: count
- name: avg_price
agg: avg
sql: price
- name: max_amount
agg: max
sql: amountAvailable aggregations: sum, count, count_distinct, avg, min, max, median
Filtered Metrics
Apply filters to specific metrics:
metrics:
- name: completed_revenue
agg: sum
sql: amount
filters: ["status = 'completed'"]
- name: us_orders
agg: count
filters: ["country = 'US'", "amount > 0"]Filters are ANDed together.
SQL Expressions
Metrics support full SQL expressions:
metrics:
- name: total_value
agg: sum
sql: "quantity * price * (1 - discount_pct)"Graph-Level Metrics
Graph-level metrics are defined at the top level and can reference model-level metrics or other graph-level metrics. Dependencies are auto-detected!
Metric References
The simplest graph-level metric references a model-level metric:
metrics:
# Dependencies auto-detected from sql!
- name: total_revenue
sql: orders.revenue
description: "Total revenue from all orders"No type field needed - dependencies are automatically detected from the sql expression.
Ratio Metrics
Divide one metric by another:
metrics:
- name: conversion_rate
type: ratio
numerator: orders.completed_revenue
denominator: orders.revenue
- name: profit_margin
type: ratio
numerator: orders.profit
denominator: orders.revenueResults in: numerator / NULLIF(denominator, 0)
Derived Metrics
Formula-based calculations with automatic dependency detection:
metrics:
# Dependencies auto-detected!
- name: profit
type: derived
sql: "revenue - cost"
- name: margin_pct
type: derived
sql: "(revenue - cost) / revenue * 100"
- name: revenue_per_customer
type: derived
sql: "total_revenue / total_customers"No need to manually list dependencies - they’re extracted from the SQL expression!
Cumulative Metrics
Running totals and period-to-date:
metrics:
# Rolling window
- name: last_7_days_revenue
type: cumulative
sql: orders.revenue
window: "7 days"
# Month-to-date
- name: mtd_revenue
type: cumulative
sql: orders.revenue
grain_to_date: month
# Year-to-date
- name: ytd_revenue
type: cumulative
sql: orders.revenue
grain_to_date: yearRequires a time dimension in the query.
Time Comparison Metrics
Year-over-year, month-over-month changes:
metrics:
# Year-over-year growth
- name: yoy_revenue_growth
type: time_comparison
base_metric: total_revenue
comparison_type: yoy
calculation: percent_change
# Month-over-month
- name: mom_revenue
type: time_comparison
base_metric: total_revenue
comparison_type: mom
calculation: difference
# Custom offset
- name: vs_last_quarter
type: time_comparison
base_metric: total_revenue
time_offset: "3 months"
calculation: ratioCalculation types: - percent_change: (current - prior) / prior * 100 - difference: current - prior - ratio: current / prior
Conversion Metrics
Track funnel conversions:
metrics:
- name: signup_to_purchase
type: conversion
entity: user_id
base_event: signup
conversion_event: purchase
conversion_window: "7 days"Calculates: users who did conversion_event within window after base_event / total users who did base_event
Metric Properties
Model-Level Metrics
- name: Unique identifier
- agg: Aggregation function (sum, count, avg, etc.)
- sql: SQL expression to aggregate (defaults to
*for count) - filters: WHERE conditions for this metric
- description: Human-readable description
- label: Display name (defaults to name)
Graph-Level Metrics
Untyped (Metric References)
- name: Unique identifier
- sql: Reference to model.metric (e.g., “orders.revenue”)
- description: Human-readable description
Typed Metrics
- type: Metric type (ratio, derived, cumulative, time_comparison, conversion)
- Type-specific properties (see sections above)
Null Handling
metrics:
- name: revenue
agg: sum
sql: amount
fill_nulls_with: 0 # Return 0 instead of NULLPython API
from sidemantic import Metric
# Model-level: Simple aggregation
revenue = Metric(name="revenue", agg="sum", sql="amount")
# Model-level: Filtered
completed = Metric(
name="completed_revenue",
agg="sum",
sql="amount",
filters=["status = 'completed'"]
)
# Graph-level: Reference (dependencies auto-detected!)
total_revenue = Metric(
name="total_revenue",
sql="orders.revenue"
)
# Graph-level: Ratio
margin = Metric(
name="margin",
type="ratio",
numerator="orders.profit",
denominator="orders.revenue"
)
# Graph-level: Derived (dependencies auto-detected!)
profit = Metric(
name="profit",
type="derived",
sql="revenue - cost"
)
# Graph-level: Cumulative
running_total = Metric(
name="running_total",
type="cumulative",
sql="orders.revenue",
window="7 days"
)Best Practices
Define basic aggregations first, then build complex metrics on top: 1. Model-level metrics (revenue, count) 2. Filtered metrics (completed_revenue) 3. Graph-level references (total_revenue) 4. Ratios (conversion_rate = completed / total) 5. Derived (margin = profit / revenue)
Define metrics once, use everywhere: - In SQL queries: SELECT revenue FROM orders - In Python: layer.query(metrics=["orders.revenue"]) - In other metrics: sql: "revenue - cost"