{% extends "base.html" %} {% block content %} {% set primary_entity = group.entity_columns[0] if group.entity_columns else None %} {% set entity_color = entity_palette.get(primary_entity) if primary_entity else None %}

{% if entity_color %}{% endif %} {{ group.name }}

{% if group.lifecycle.value != 'active' %}{{ group.lifecycle.value }}{% endif %} {% if group.definition_version > 1 %}v{{ group.definition_version }}{% endif %} {% if group.materialization %}{{ group.materialization }}{% endif %} {% for tag in group.tags %}{{ tag }}{% endfor %}
{% if group.description %}

{{ group.description }}

{% endif %}
{{ group.fully_qualified_name }}
{% if group.lifecycle.value == 'deprecated' and group.replacement %}

Deprecated. Use {{ group.replacement }} instead.

{% elif group.lifecycle.value == 'deprecated' %}

Deprecated.

{% elif group.lifecycle.value == 'preview' %}

Preview. This feature table is not yet considered production-ready.

{% endif %}
{% if snapshot %} {% set status = freshness_status(snapshot, group.freshness) %}
{% if status.label == 'fresh' %}Fresh {% elif status.label == 'warn' %}Warning — past warn threshold {% elif status.label == 'error' %}Stale — past error threshold {% elif status.label == 'unknown' %}Status unknown {% endif %} {% if snapshot.error %} {{ snapshot.error }} {% else %} last updated {{ status.age_human }} {% endif %}
{% endif %}

Trust

{% if group.owner %}
Owner
{{ group.owner }}
{% endif %}
Lifecycle
{{ group.lifecycle.value }}{% if group.replacement %} → {{ group.replacement }}{% endif %}
{% if group.freshness %}
Freshness SLA
{% if group.freshness.warn_after %}warn {{ group.freshness.warn_after.count }}{{ group.freshness.warn_after.period.value[0] }}{% endif %} {% if group.freshness.warn_after and group.freshness.error_after %} · {% endif %} {% if group.freshness.error_after %}error {{ group.freshness.error_after.count }}{{ group.freshness.error_after.period.value[0] }}{% endif %}
{% endif %} {% if snapshot and snapshot.max_timestamp %}
Last update
{{ snapshot.max_timestamp.strftime('%Y-%m-%d %H:%M UTC') }}
{% endif %}

Join keys

{% if group.entity_columns %}
Entity
{% for c in group.entity_columns %}{{ c }}{% if not loop.last %}, {% endif %}{% endfor %}
{% endif %} {% if group.grain %}
Grain
{% for c in group.grain %}{{ c }}{% if not loop.last %}, {% endif %}{% endfor %}
{% endif %} {% if group.time_grain %}
Cadence
{{ group.time_grain }}
{% endif %} {% if group.timestamp_column %}
Timestamp
{{ group.timestamp_column }}
{% endif %} {% if not group.entity_columns and not group.grain and not group.timestamp_column %}
No join metadata declared
{% endif %}

Storage

{% if snapshot and snapshot.row_count is not none %}
Row count
{{ snapshot.row_count|humanize_count }}
{% endif %} {% if group.materialization %}
Materialization
{{ group.materialization }}
{% endif %}
Source file
{{ group.file_path }}

Use this feature group

{{ sql_select_snippet(group) }}

Features

{% if not group.features %}

No feature columns found in this model.

{% else %}
{% if not snapshot %}

Connect a warehouse profile to see null %, distinct counts, and freshness here.

{% endif %}
{% if snapshot %}{% endif %} {% for feature in group.features %} {% set col_stats = snapshot.columns.get(feature.name) if snapshot else None %} {% if snapshot %} {% endif %} {% endfor %}
Features in {{ group.name }}
Name Type Column typeNull %DistinctNull behavior Status Declared ML consumers
{{ feature.name }} {% if feature.definition_version > 1 %}v{{ feature.definition_version }}{% endif %} {% if feature.description %}
{{ feature.description }}
{% endif %}
{% if feature.feature_type %}{{ feature.feature_type.value }}{% else %}{% endif %} {% if feature.column_type %}{{ feature.column_type }}{% else %}{% endif %}{% if col_stats %}{{ humanize_percent(col_stats.null_count, snapshot.row_count) }}{% else %}{% endif %} {% if col_stats and col_stats.distinct_count is not none %}{{ col_stats.distinct_count|humanize_count }}{% else %}{% endif %}{% if feature.null_behavior %}{{ feature.null_behavior.value }}{% else %}{% endif %} {% if feature.lifecycle.value != 'active' %}{{ feature.lifecycle.value }}{% else %}{% endif %} {% if feature.used_by %} {% for u in feature.used_by %}{{ u }}{% endfor %} {% else %}{% endif %}
{% endif %}

Lineage

Upstream {{ group.upstream|length }}

{% if group.upstream %}
    {% for ref in group.upstream %}
  • {% if ref.is_feature_table %}{{ ref.name }}{% else %}{{ ref.name }}{% endif %} {{ ref.resource_type }}
  • {% endfor %}
{% else %}

None

{% endif %}

Downstream dbt models {{ group.downstream|length }}

{% if group.downstream %}
    {% for ref in group.downstream %}
  • {% if ref.is_feature_table %}{{ ref.name }}{% else %}{{ ref.name }}{% endif %} {{ ref.resource_type }}
  • {% endfor %}

Auto-derived from the dbt graph.

{% else %}

None.

{% endif %}

ML consumers {{ declared_consumers|length }}

{% if declared_consumers %}
    {% for c in declared_consumers %}
  • {{ c }} {% if c in catalog.exposure_info %}exposure{% else %}manual{% endif %}
  • {% endfor %}
{% if catalog.exposure_info %}

Auto-derived from dbt exposures and manual used_by.

{% else %}

Declared via column-level used_by (deprecated; prefer type: ml exposures).

{% endif %} {% else %}

None declared. Add type: ml exposures, or set the deprecated used_by on features.

{% endif %}
{% endblock %} {% block scripts %} {% endblock %}