Skip to content

Guard monthly cost change against a zero prior month - #2327

Open
Roland Krummenacher (RolandKrummenacher) wants to merge 5 commits into
devfrom
RolandKrummenacher/monthly-cost-change-divide-by-zero
Open

Roland Krummenacher (RolandKrummenacher) wants to merge 5 commits into
devfrom
RolandKrummenacher/monthly-cost-change-divide-by-zero

Conversation

@RolandKrummenacher

@RolandKrummenacher Roland Krummenacher (RolandKrummenacher) commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

🛠️ Description

monthly-cost-change-percentage.kql guards its division with isempty(PreviousBilledCost). That covers the null prev() returns on the first row, but isempty() is false for 0.0, so a prior month of exactly zero falls through — and KQL evaluates x / 0.0 as inf rather than raising, so an infinity is returned as the percentage.

Both guards now also test for zero:

-    BilledCostChangePct = iff(isempty(PreviousBilledCost), 0.0, ...),
+    BilledCostChangePct = iff(isempty(PreviousBilledCost) or PreviousBilledCost == 0.0, 0.0, ...),

The == 0.0 form matches the convention already used in service-price-benchmarking.kql.

A zero prior month is reachable rather than theoretical: BilledCost is zero on usage rows covered by a commitment discount, since the charge was billed at purchase time and the amortized amount lands in EffectiveCost. A scope whose month is entirely commitment-covered therefore sums BilledCost to exactly zero.

Deliberately out of scope: returning 0.0 when there is no prior month conflates "no change" with "nothing to compare against". real(null) would separate them, but that is a behaviour change for existing consumers, so this PR only closes the divide-by-zero hole. Happy to follow up if you would prefer the stricter version.

Fixes #2323

📋 Checklist

🔬 How did you test this change?

  • 👍 Manually deployed + verified

Ran the pipeline's shape against a live ADX hub with a datatable, so no ingestion is involved:

datatable(ChargePeriodStart:datetime, BilledCost:real)
[
    datetime(2025-01-01), 100.0,
    datetime(2025-02-01),   0.0,
    datetime(2025-03-01),  50.0,
]
| order by ChargePeriodStart asc
| extend PreviousBilledCost = prev(BilledCost)
| project ChargePeriodStart,
    Before = tostring(iff(isempty(PreviousBilledCost), 0.0, toreal((BilledCost - PreviousBilledCost) * 100.0 / PreviousBilledCost))),
    After  = tostring(iff(isempty(PreviousBilledCost) or PreviousBilledCost == 0.0, 0.0, toreal((BilledCost - PreviousBilledCost) * 100.0 / PreviousBilledCost)))
ChargePeriodStart Before After
2025-01-01 0 0
2025-02-01 -100 -100
2025-03-01 inf 0

Rows with a non-zero prior month are unaffected, so the change is limited to the case that was previously returning an infinity.

📦 Deploy to test?

Not needed — the change is one query file in the catalog.

🙋‍♀️ Do any of the following that apply?

  • 🚨 This is a breaking change.
  • 🤏 The change is less than 20 lines of code.

📑 Did you update docs/changelog.md?

  • ✅ Updated changelog (required for dev PRs)

Added under FinOps hubs → Fixed in docs-mslearn/toolkit/changelog.md.

📖 Did you update documentation?

  • ❎ Docs not needed (small/internal change)

🤖 Generated with Claude Code

isempty() is false for 0.0, so the existing guard only covers the first row,
where prev() returns null. A month whose prior month summed to exactly zero
falls through and KQL evaluates x / 0.0 to inf rather than raising an error,
so the result reaches the caller as an infinity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No unresolved issues remain.

Pull request overview

Guards monthly cost change calculations against zero prior-month values to prevent inf results.

Changes:

  • Adds zero-denominator guards for billed and effective cost percentages.
  • Preserves existing behavior for null and non-zero prior values.
File summaries
File Description
src/queries/catalog/monthly-cost-change-percentage.kql Prevents divide-by-zero results in both percentage calculations.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@microsoft-github-policy-service microsoft-github-policy-service Bot added the Micro PR 🔬 Very small PR that should be especially easy for newcomers label Sep 16, 2026
…-by-zero

Resolved the ms.date conflict in docs-mslearn/toolkit/changelog.md to today
per the repo convention. Changelog body entries from both sides were kept.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…y-zero

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch is waiting to be deployed

1 waiting (outdated) deployment
ftk-fork — 8f05194f Waiting Sep 16, 2026 by RolandKrummenacher via Clean up PR resources #60
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Micro PR 🔬 Very small PR that should be especially easy for newcomers Needs: Review 👀 PR that is ready to be reviewed Skill: KQL KQL queries and Data Explorer integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

monthly-cost-change-percentage returns inf when the prior month is zero

5 participants