Add billing currency filter to Data Explorer dashboard (#2093)#2103
Merged
RolandKrummenacher merged 6 commits intodevfrom Apr 22, 2026
Merged
Add billing currency filter to Data Explorer dashboard (#2093)#2103RolandKrummenacher merged 6 commits intodevfrom
RolandKrummenacher merged 6 commits intodevfrom
Conversation
Aggregating cost columns across multiple BillingCurrency values produces mathematically invalid totals and savings rates. This adds a "Billing currency" query-based parameter sourced from distinct BillingCurrency values in Costs_v1_2 and applies it as a filter in the CostsPlus base query so it propagates to all downstream queries. Defaults to "All" to preserve existing behavior for single-currency customers; multi-currency customers can now filter to a single currency for correct results. Addresses #2093 (Phase 1, item 1). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Rename the "Billing currency" parameter display name to "Currency". - Apply the currency filter to the "Summary of list, contracted, and effective cost alignment" data-quality tile on the Data ingestion page. That tile queried the Costs() function directly, bypassing CostsPlus, and aggregated cost columns across currencies. All other dashboard queries inherit the filter through the CostsPlus chain (CostsThisMonth / CostsLastMonth / CostsByMonth / CostsByDay / CostsByDayAHB all derive from CostsPlus). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the built-in "All" option with a conditional synthetic row in the parameter query. When the data contains more than one billing currency, the dropdown surfaces "⚠️ All" as the first entry, which is also the default. Selecting it applies no filter (mixed totals), so the warning marker is shown exactly when the dashboard would otherwise display mathematically invalid aggregates. Single-currency tenants see only their currency — no "All", no noise. Defaults change from kind=all to kind=query-result so the first row from the parameter query is selected; ordering guarantees the "⚠️ All" row comes first when it exists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
flanakin
approved these changes
Apr 22, 2026
Collaborator
Author
|
@copilot resolve the merge conflicts in this pull request |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
Currencyparameter to the FinOps hub Data Explorer dashboard so cost totals and savings KPIs can be scoped to a single billing currency. Implements Phase 1 items 1 + 2 of #2093; remaining items (Phase 1 item 3, savings-plan FX distortion, Phase 2 USD normalization) continue to be tracked there.Why
The dashboard aggregates
BilledCost/EffectiveCost/ContractedCost/ListCostacross rows without anyBillingCurrencyawareness. For any tenant with more than one billing currency (EA→MCA transitions, M&A, CSP partners with customers in multiple currencies, multi-cloud via FOCUS), the resulting totals and savings rates are mathematically invalid — currencies get summed as if they were comparable numbers.The
CostsPlusbase query feeds ~74 of the 86 dashboard queries, so adding the filter there propagates the fix everywhere downstream with minimal blast radius.Changes
1. New
selectedBillingCurrencyparameter (displayed as Currency)distinct BillingCurrencyover the hub's configured retention window.CostsPlusbase query as| where isempty(selectedBillingCurrency) or BillingCurrency == selectedBillingCurrency, immediately after the time-range filter. Inherited by all ~74 downstream tile queries throughCostsPlusand its derived base variables (CostsThisMonth,CostsLastMonth,CostsByMonth,CostsByDay,CostsByDayAHB).CostsPlus— the Summary of list, contracted, and effective cost alignment data-quality table on the Data ingestion page (queriesCosts()directly).2. Conditional⚠️ All option — implicit mixed-currency warning
Rather than adding a separate warning tile (no clean place on the dense Summary page), the warning is embedded into the parameter dropdown itself:
This is done via a synthetic row unioned into the parameter query only when
dcount(BillingCurrency) > 1, with an emptyBillingCurrencyvalue that the filter treats as "no filter applied".Scope / what this PR does NOT do
Phase 1 item 3 from the issue (replace
sum(ListCost) - sum(EffectiveCost)patterns withsum(x_TotalSavings)etc.) is intentionally out of scope — orthogonal to currency handling and warrants independent review of whether the row-level clamped savings columns actually produce different totals.Phase 2 (USD normalization toggle) is also deferred — blocked on
x_*InUsdcolumn coverage across ingestion paths per the issue.Coverage audit
All 87 queries in the dashboard were reviewed:
CostsPlus(directly or via the five derived base variables)..show cluster extentsqueries (ingestion row counts) — no cost aggregation, no currency risk.HubSettings,range) — no cost data.Costs()directly (data-quality tile on the ingestion page) — now also filtered.Test plan
npm run buildpasses (already verified).🤖 Generated with Claude Code