Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ mod tests {
#[test]
fn registry_declares_the_expected_counts() {
assert_eq!(builtin_sources().len(), 6, "builtin source count");
assert_eq!(builtin_metrics().len(), 65, "builtin metric count");
assert_eq!(builtin_metrics().len(), 66, "builtin metric count");
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,31 @@ this file and the registry disagree.
- Reads: cost_usd
- Formula: sum(cost_usd)
- Shape: currency, lower_is_better
- Notes: Person-attributed AI usage priced at the vendor's token or usage rates — what the consumption would cost if billed purely by usage. Includes usage a seat or subscription already covered, and excludes seat and subscription fees, so it is not the amount invoiced. Covers the tools whose connector prices usage per person. Overlaps ai.extra_usage_cost, which is the part of that same consumption the vendor actually billed on top of the seat fee — the two are served side by side and are never added, since adding them counts the billed part twice.
- Notes: Person-attributed AI usage priced at the vendor's token rates — what the consumption would cost if billed purely by usage. It includes usage a seat already covered and excludes seat fees, so it is not the invoiced amount, and only tools that price usage per person contribute. Never add it to actual usage cost, which is the billed part of this same consumption.

## ai.seat_cost — AI seat cost

- Source: ai_cost (ai_cost_metric_observations)
- Reads: seat_cost_usd
- Formula: sum(seat_cost_usd)
- Shape: currency, lower_is_better
- Notes: The invoiced price of a person's seat for a billing month, read from the per-seat amount on the invoice's subscription lines — the only place the vendor states a price for one seat. A monthly fact reported against the day the seat snapshot was last read; a window covering part of a month returns that month in full rather than a fraction, and a window spanning two months returns both fees. Distinct from ai.extra_usage_cost, which is what the vendor billed on top of this fee; the two add up to what a seat cost in total. A seat carrying no tier returns no value, as does a month whose invoice priced several tiers and none of them is the seat's — a share of the invoice total would be an invention. Attribution mode is derived — the invoice prices a tier, not a person.
- Notes: The invoiced price of one seat for a billing month, read from the per-seat amount on the invoice. A monthly figure, so a partial window returns the whole month and a window spanning two months returns both fees. A seat whose tier the invoice does not price returns no value rather than a share of the total. Add actual usage cost for the full cost of a seat.

## ai.extra_usage_cost — AI actual usage cost

- Source: ai_cost (ai_cost_metric_observations)
- Reads: extra_usage_usd
- Formula: sum(extra_usage_usd)
- Shape: currency, lower_is_better
- Notes: What the vendor billed a person on top of their seat fee, once the usage included in that fee was exhausted, priced at API rates. A monthly fact reported against the day the seat snapshot was last read; a window covering part of a month returns that month in full rather than a fraction. Distinct from ai.cost, which prices all consumption including what the seat fee already covered — the two are never summed. Attribution mode is direct — the vendor reports this amount per seat.
- Notes: What the vendor billed on top of the seat fee, once the usage that fee covered was exhausted, priced at API rates. A monthly figure, so a window covering part of a month returns the whole month rather than a fraction. This is the exact billed amount; its per-day distribution approximates the same money, and neither adds to potential usage cost.

## ai.daily_approximate_extra_usage_cost — AI actual usage cost — approximate distribution

- Source: ai_cost (ai_cost_metric_observations)
- Reads: daily_extra_usage_usd
- Formula: sum(daily_extra_usage_usd)
- Shape: currency, lower_is_better
- Notes: The billed extra-usage cost placed on the days it was spent. The vendor reports only a running month-to-date total, so a day's figure is the step between two readings — exact in sum over a month, approximate in placement. A day with no reading shows no point, and a correction never produces a negative day.

## ai.extra_usage_utilisation — Extra-usage ceiling used

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ sources:
evidence_granularity: source_summary
- key: seat_cost_usd
evidence_granularity: source_summary
- key: daily_extra_usage_usd
evidence_granularity: source_summary
dimensions:
- tool
- seat_tier
Expand Down Expand Up @@ -260,7 +262,7 @@ metrics:
label: AI potential usage cost
short_label: Potential cost
description: Potential cost of all AI usage at vendor rates, never the actual invoice
explanation: Person-attributed AI usage priced at the vendor's token or usage rates — what the consumption would cost if billed purely by usage. Includes usage a seat or subscription already covered, and excludes seat and subscription fees, so it is not the amount invoiced. Covers the tools whose connector prices usage per person. Overlaps ai.extra_usage_cost, which is the part of that same consumption the vendor actually billed on top of the seat fee — the two are served side by side and are never added, since adding them counts the billed part twice.
explanation: Person-attributed AI usage priced at the vendor's token rates — what the consumption would cost if billed purely by usage. It includes usage a seat already covered and excludes seat fees, so it is not the invoiced amount, and only tools that price usage per person contribute. Never add it to actual usage cost, which is the billed part of this same consumption.
format: currency
direction: lower_is_better
entity_type: person
Expand All @@ -277,7 +279,7 @@ metrics:
label: AI seat cost
short_label: Seat cost
description: What a seat costs before any usage
explanation: The invoiced price of a person's seat for a billing month, read from the per-seat amount on the invoice's subscription lines — the only place the vendor states a price for one seat. A monthly fact reported against the day the seat snapshot was last read; a window covering part of a month returns that month in full rather than a fraction, and a window spanning two months returns both fees. Distinct from ai.extra_usage_cost, which is what the vendor billed on top of this fee; the two add up to what a seat cost in total. A seat carrying no tier returns no value, as does a month whose invoice priced several tiers and none of them is the seat's — a share of the invoice total would be an invention. Attribution mode is derived — the invoice prices a tier, not a person.
explanation: The invoiced price of one seat for a billing month, read from the per-seat amount on the invoice. A monthly figure, so a partial window returns the whole month and a window spanning two months returns both fees. A seat whose tier the invoice does not price returns no value rather than a share of the total. Add actual usage cost for the full cost of a seat.
format: currency
direction: lower_is_better
entity_type: person
Expand All @@ -294,8 +296,8 @@ metrics:
subject: cost
label: AI actual usage cost
short_label: Actual cost
description: Actual cost billed on top of the seat fee, part of the potential total
explanation: What the vendor billed a person on top of their seat fee, once the usage included in that fee was exhausted, priced at API rates. A monthly fact reported against the day the seat snapshot was last read; a window covering part of a month returns that month in full rather than a fraction. Distinct from ai.cost, which prices all consumption including what the seat fee already covered — the two are never summed. Attribution mode is direct — the vendor reports this amount per seat.
description: Exact monthly cost billed on top of the seat fee, part of the potential total
explanation: What the vendor billed on top of the seat fee, once the usage that fee covered was exhausted, priced at API rates. A monthly figure, so a window covering part of a month returns the whole month rather than a fraction. This is the exact billed amount; its per-day distribution approximates the same money, and neither adds to potential usage cost.
format: currency
direction: lower_is_better
entity_type: person
Expand All @@ -307,6 +309,24 @@ metrics:
dimensions:
- tool
- seat_tier
- metric_key: ai.daily_approximate_extra_usage_cost
source_key: ai_cost
subject: cost
label: AI actual usage cost — approximate distribution
short_label: Actual cost / day
description: Approximate distribution across days of the exact monthly billed cost
explanation: The billed extra-usage cost placed on the days it was spent. The vendor reports only a running month-to-date total, so a day's figure is the step between two readings — exact in sum over a month, approximate in placement. A day with no reading shows no point, and a correction never produces a negative day.
format: currency
direction: lower_is_better
entity_type: person
computation: sum
peer_cohort_key: org_unit
inputs:
- input_role: value
measure_key: daily_extra_usage_usd
dimensions:
- tool
- seat_tier
- metric_key: ai.extra_usage_utilisation
source_key: ai_cost
subject: cost
Expand Down
88 changes: 88 additions & 0 deletions src/ingestion/gold/ai_cost_metric_evidence.sql
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,61 @@ seat_month_priced AS (
ON prices.tenant_id = seat.tenant_id
AND prices.source = seat.source
AND prices.period_month = seat.period_month
),
-- Every reading of a seat inside its billing month. The vendor reports a
-- cumulative month-to-date figure, so a day's spend is the step between two
-- readings and nothing else.
seat_day_source AS (
SELECT
insight_tenant_id AS tenant_id,
source,
source_id,
account_id,
lower(email) AS entity_id,
snapshot_date AS metric_date,
toDateTime64(collected_at, 3) AS observed_at,
period_month,
CAST(
[
tuple('tool', tool, {{ ai_tool_label('tool') }}),
tuple('seat_tier', coalesce(seat_tier, 'unknown'), CAST(NULL AS Nullable(String)))
] AS Array(Tuple(key String, value String, label Nullable(String)))
) AS seat_dimensions,
used_amount_cents
FROM {{ ref('class_ai_overage_daily') }} FINAL
WHERE email IS NOT NULL
AND email != ''
AND snapshot_date IS NOT NULL
),
-- INVARIANT: the suffix minimum is what keeps every step non-negative and makes
-- the steps add up to the month's final reading, which the monthly metric serves.
seat_day_corrected AS (
SELECT
*,
min(used_amount_cents) OVER (
PARTITION BY tenant_id, source, source_id, account_id, period_month
ORDER BY metric_date
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS corrected_cents
FROM seat_day_source
),
seat_day_step AS (
SELECT
*,
corrected_cents - lagInFrame(corrected_cents, 1, toUInt32(0)) OVER w
AS step_cents,
-- INVARIANT: covers_days spans from the previous reading, or from the 1st
-- for a month's first one — above 1 the step is not one day's spend.
toUInt16(dateDiff(
'day',
lagInFrame(metric_date, 1, toDate(period_month) - 1) OVER w,
metric_date
)) AS covers_days
FROM seat_day_corrected
WINDOW w AS (
PARTITION BY tenant_id, source, source_id, account_id, period_month
ORDER BY metric_date
)
)

SELECT
Expand Down Expand Up @@ -156,6 +211,39 @@ ARRAY JOIN arrayConcat(
[]
)
) AS seat_measure
WHERE tenant_id IS NOT NULL
AND entity_id IS NOT NULL
AND metric_date IS NOT NULL

UNION ALL

SELECT
assumeNotNull(tenant_id) AS tenant_id,
'ai_cost' AS source_key,
'person' AS entity_type,
assumeNotNull(entity_id) AS entity_id,
assumeNotNull(metric_date) AS metric_date,
toNullable(observed_at) AS observed_at,
'daily_extra_usage_usd' AS measure_key,
-- Keyed on the read day: unlike the month rows, the day IS the grain here.
concat(
toString(metric_date), ':daily_extra_usage_usd:',
hex(sipHash64(concat(coalesce(source_id, ''), ':', coalesce(account_id, ''))))
) AS record_id,
'seat_day' AS record_kind,
'source_summary' AS granularity,
formatDateTime(metric_date, '%Y-%m-%d') AS record_label,
toNullable(toFloat64(step_cents) / 100) AS contribution,
CAST(NULL AS Nullable(String)) AS subject_key,
seat_dimensions AS dimensions,
map(
'billing_month', toString(period_month),
'month_to_date_usd', toString(toFloat64(corrected_cents) / 100),
-- Above 1 the figure is a span, not a day: say so rather than let a
-- reader take it for one day's spend.
'covers_days', toString(covers_days)
) AS details
FROM seat_day_step
WHERE tenant_id IS NOT NULL
AND entity_id IS NOT NULL
AND metric_date IS NOT NULL
Expand Down
5 changes: 4 additions & 1 deletion src/ingestion/gold/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ models:
amount on the invoice's subscription lines; extra_usage_usd is the money
the vendor billed once that seat exhausted the usage included in its fee;
extra_usage_limit_usd is the admin-set ceiling on that spend, and serves
only as the utilisation denominator.
only as the utilisation denominator; daily_extra_usage_usd is the same
billed money as extra_usage_usd, stepped across the days it was spent.
Comment thread
Gregory91G marked this conversation as resolved.
columns:
- name: tenant_id
description: "Tenant isolation field"
Expand Down Expand Up @@ -162,8 +163,10 @@ models:
- accepted_values:
arguments:
values:
- seat_cost_usd
- extra_usage_usd
- extra_usage_limit_usd
- daily_extra_usage_usd
- name: value
description: >
Measure value. Rows are emitted only when the source provides a
Expand Down
Loading