Welcome to the Learning FOCUS blog series. If this is your first post, I recommend you start with Introducing an open billing data format to get a high-level picture of what the FinOps Open Cost and Usage Specification (FOCUS) is and what it covers. This week, I’ll cover the columns that describe the type of charges and pricing models you’ll find in a FOCUS dataset. These columns will be used in many of the queries and reports you use due to how they help break down the charges you’ll find in a FOCUS dataset.
⮜ Previous post (Costs) · Next post (Dates) ⮞
Understanding charges in FOCUS
It's important to understand the various types of charges (or rows) you’ll find in a FOCUS dataset. Each type of charge manifests itself in slightly different ways which will be important as you formulate queries and build reports to answer specific questions. FOCUS includes three main columns that help you understand the type of charge each row represents: ChargeCategory, ChargeClass, and PricingCategory. Microsoft also provides an additional x_PricingSubcategory for additional context. I’ll share more about that later.
ChargeCategory and ChargeClass describe the type of charge while PricingCategory and x_PricingSubcategory describe the pricing model or how each charge was priced. While PricingCategory isn’t explicitly linked to ChargeCategory, it provides the next level of detail to explain the type of charge represented by the row. For those familiar with Microsoft’s actual and amortized cost details, ChargeCategory and ChargeClass loosely map to ChargeType while PricingCategory and x_PricingSubcategory loosely map to PricingModel. While you can do a direct map with these, ChargeType also includes additional values for used and unused commitment discounts, which FOCUS tracks in another column. We’ll cover that later when we get into commitment discounts.
You’ll notice a few naming conventions with these columns: First, FOCUS tries to name most columns with a consistent prefix when they’re related. In this batch, we have two Charge columns and two Pricing columns, but there are more in both of these sets, which we’ll cover in future blog posts. Second, FOCUS has two different kinds of “type” columns. Columns that describe a type of thing using provider-specific terms are named “Type” and columns that use a predefined set of provider-agnostic terms are named “Category”. This is why FOCUS has a ChargeCategory column rather than a ChargeType column. There’s only one case where both columns exist today, but several have been discussed and may come in a future release. We’ll talk more about the one instance when we get to commitment discount columns. Lastly, you’ll notice that x_PricingSubcategory has this extra “x_” prefix. FOCUS uses “x_” to denote external or extended columns that are not part of the specification. The purpose of the prefix is to ensure there are no collisions when FOCUS releases a new version with a column of the same name. We don’t want FOCUS releases to “break” provider-specific amendments. Any time you see an “x_” prefix, remember that this is not part of FOCUS and may not be included in data from other providers.
Highest level classification of charges
At the highest level, FOCUS can include five different types of charges, which are indicated using the ChargeCategory column:
- Usage represents a charge based on how much a service was used or consumed over a given period.
- Purchase represents a charge for the acquisition of a service that is generally not tied to how much it was used.
- Credit represents a voucher or incentive that providers offer, often to encourage the use of one or more services.
- Tax represents governmental or regulatory fees imposed on services to comply with legal obligations.
- Adjustment represents charges not directly tied to service acquisition or usage and that don’t fit into other categories.
And as a “Category” column, you know that these values will be consistent across providers as well. This means, if you want to build a report that looks at all purchases across providers, you can consistently filter on ChargeCategory == "Purchase". Or if you want to look at usage over time, you can filter on ChargeCategory == "Usage".
While this may seem simplistic, the four main cloud providers that offer FOCUS data today all use slightly different columns and values to represent what FOCUS calls ChargeCategory, so having this consistency goes a long way to making your life easier as a FinOps practitioner.
And beyond understanding what each of these categories mean, it’s also important to understand how these charges work and the inherent “business logic” that sits behind each category.
As an example, Usage charges are generally aggregated per day or hour while Purchase charges are generally emitted when incurred. If two separate purchases happen at the same time, this will generally result in separate rows; while usage will be aggregated for the entire hour or day into a single row. Credit charges are similar to purchases in this regard. Tax charges are often applied at the end of the month after all other charges are finalized. Adjustment charges may differ based on their purpose. As an example, Microsoft includes rounding adjustments at the end of the month to ensure costs match the invoice, which is trimmed when finalized.
As we explore other columns, I’ll share details about how they may change based on ChargeCategory or other columns.
Refunds and corrections
Most of the data we see – at least in the cloud – is for usage of services consumed over time with the occasional purchase and maybe credits, taxes, and adjustments based on dealings with the provider. But sometimes you may cancel or exchange purchases, like commitment discounts. Or perhaps you might receive a refund for billing errors or service outages. FOCUS represents all of these with a Correction value in the ChargeClass column.
One important note about ChargeClass is that it slightly differs from what you’ll find in other Cost Management datasets because of the separation from ChargeCategory. FOCUS can convey usage refunds separately from purchase refunds. This offers the added benefit of summing all usage or purchase charges with their refunds, for example. The same applies for corrections to credits, taxes, or even adjustments.
How charges are priced
Given usage charges are most prominent in cloud costs, understanding how your usage is priced is critical and can even help you quantify where you can improve or hopefully already have maximized cost efficiency. Of course, not everything has a pricing model. As an example, credits are essentially money being given to an organization to offset other charges and do not necessarily have a predefined price outside of the corresponding usage charges that consume the credits.
FOCUS defines the following allowed values in the PricingCategory column:
- Standard pricing is based on a predefined, agreed upon rate, which includes negotiated discounts. Standard pricing does not change within the billing period.
- Dynamic pricing is variable and can change within the billing period without explicit notice.
- Committed pricing is reduced based on commitment discount purchases. This generally only applies to usage and not the purchase of a commitment discount since the price of that purchase was not reduced because the purchase was previously committed to.
- Other pricing is any other model that is not covered by another value.
- Null (no value) is also allowed when a charge does not have a pricing model.
While discussing the PricingCategory column within the FOCUS working group, we also discussed the need to break each of these down to a lower level. In those discussions, we started to define a PricingSubcategory column, but that didn’t make it into FOCUS 1.0 and is still in the backlog. This is where the x_PricingSubcategory column comes from. x_PricingSubcategory is only available in Microsoft’s FOCUS implementation today, but we do hope other providers follow suit to offer the next level pricing model details. x_PricingSubcategory can include the following values:
- Standard pricing is at a flat rate and does not change based on how much is consumed.
- Tiered pricing changes as more is consumed.
- Committed Usage pricing is for reservations which offer a higher discounts compared to savings plans.
- Committed Spend pricing is for savings plans which offer more flexibility with lower discounts than reservations.
- Spot pricing is based on market demand which could change daily or even hourly, depending on the provider.
- Other pricing is any other model that is not covered by another value.
Also note that each x_PricingSubcategory value applies to a specific PricingCategory value. Standard and Tiered apply only to the Standard PricingCategory, Committed Usage and Committed Spend to the Committed PricingCategory, and Spot to the Dynamic PricingCategory. Other can be applied to any PricingCategory value.
If you’re curious about the original FOCUS discussions about pricing models, refer to PricingCategory supporting content.
Transitioning to FOCUS
Whether you’re updating reports, transforming data, validating FOCUS, or simply curious about how FOCUS compares to the historical actual and amortized datasets, you’re probably looking for a more direct mapping of columns. We have separate articles covering each of these scenarios in more detail, but here’s a summary regarding the charge types we’ve discussed today. We’ll start with ChargeCategory and ChargeClass, which map to ChargeType:
CM ChargeType |
FOCUS ChargeCategory |
FOCUS ChargeClass |
Notes |
Usage |
Usage |
(null) |
|
Purchase |
Purchase |
(null) |
|
Refund |
Purchase |
Correction |
All refunds in Cost management are purchase refunds as of December 2024. |
RoundingAdjustment |
Adjustment |
(null) |
|
UnusedReservation |
Usage |
(null) |
Unused status tracked in another column. |
UnusedSavingsPlan |
Usage |
(null) |
Unused status tracked in another column. |
PricingCategory and x_PricingSubcategory map to PricingModel:
CM PricingModel |
FOCUS PricingCategory |
FOCUS x_PricingSubcategory |
Notes |
OnDemand |
Standard |
Standard or Tiered |
Pricing subcategory values may differ based on the type of on-demand usage. |
Reservation |
Committed |
Committed Usage |
|
SavingsPlan |
Committed |
Committed Spend |
|
Spot |
Dynamic |
Spot |
|
For more detail, refer to the following articles:
Reviewing cost in Power BI
At this point in the Learning FOCUS blog series, we’ve covered cost, charge type, and pricing model columns. It’s still early, so we won’t get into any advanced scenarios, but I do want to share two of the pages we have available in the FinOps toolkit Cost summary report: Charge breakdown and Purchases.
For those who aren’t familiar, the Cost summary report offers various breakdowns of cost data to provide a starting point for building out your own reports. While we’re using the FinOps toolkit reports here, the same concept can be applied in most reporting tools.
The Charge breakdown page shows a high-level breakdown of all charges using ChargeCategory, PricingCategory, x_PricingSubcategory, and other useful columns which we’ll discuss in future blog posts. The goal of this page is to offer an at a glance view of all charges with an interactive drilldown to explore what they are. There’s a lot of information on this page, so take time to understand how each level breaks down into meaningful details of the higher levels.
The Cost summary report generally includes all charge categories. The main page that pinpoints specific data is the Purchases page, which shows all purchases and refunds in the account.
The most common use of PricingCategory is to filter usage to only see usage either with or without commitment discounts. The FinOps toolkit also offers a Rate optimization report that focuses on commitment discounts. Most of the pages in this report have a PricingCategory = “Committed” filter to only see committed usage. As an example, the Commitments page shows a list of the commitment discounts that are in active use with cost, utilization, and savings for each. Of specific note for this topic is the Filters pane on the right, which shows the ChargeCategory and PricingCategory filters applied to the entire page.
The Rate optimization report has many pages that leverage ChargeCategory and PricingCategory. Similar to Cost summary, Rate optimization also includes a Purchases page. The only difference being the Rate optimization report only shows commitment discount purchases and refunds, which Cost summary shows all.
And if we look a little deeper, we can also build a very simple coverage report with what we’ve learned so far. In the example below, I duplicated the Commitments page and:
- Removed the Utilization KPI
- Replaced the Commitment savings KPI with Total savings
- Changed the chart to group by x_PricingSubcategory
- Changed the table to a matrix
- Set the matrix rows to PricingCategory, x_PricingSubcategory, etc.
- Set the matrix columns to the month
- Set the values to show savings and EffectiveCost
This is a very basic conceptual coverage report that doesn’t account for everything needed for accurate commitment discount coverage reporting, but I wanted to show how easy it is to put this information to good use. I was able to build this within the storage report in less than 5 minutes. Of course, if I need to monitor more than $2M/mo, I can also use the KQL reports with FinOps hubs and Data Explorer to achieve the same with month over month reporting and more.
For those familiar with the FinOps toolkit Power BI reports, you may notice this is new. We’ll include this in the 0.8 release of the FinOps toolkit coming in early January.
Hopefully, these visuals help demonstrate the usefulness of each of the cost columns. We’ll dig into the other columns shown here in future posts. To learn more about these and other reports, see FinOps toolkit Power BI reports.
Querying cost in FinOps hubs
With FOCUS costs available in Azure Data Explorer in FinOps hubs 0.7, you now have a powerful and performant query engine that can give you the answers you need faster than ever. I can’t emphasize enough the power of having years of data at your fingertips with answers just seconds away.
Let’s start out the same way we did last week with a simple query that summarizes based on the columns we’ve discussed so far:
Costs | summarize BilledCost = round(sum(BilledCost), 4), EffectiveCost = round(sum(EffectiveCost), 4), x_RowCount = count() by ChargeCategory, ChargeClass, PricingCategory, x_PricingSubcategory, BillingCurrency
This is with 13 months of data running at around $3.5M per month. The query is simple, but the beauty of this example is the response time. This answer came back in 0.9 seconds, covering over 50 million rows!
I included a custom x_RowCount column to count the rows, which isn’t part of FOCUS. I also included BillingCurrency here, which might not be obvious. I’ll keep calling this out since it’s easy to forget: Always include BillingCurrency when summarizing data to ensure you aren’t mixing numbers with different currencies.
Mixing charge type, pricing model, and cost columns unlocks answers to some interesting questions, but most require columns we haven’t covered yet, so I’ll hold off on those for now. But to share another simple example, we can also identify the most expensive purchases with a simple filter:
Costs | where ChargeCategory == 'Purchase' | order by BilledCost desc | limit 10
I didn’t summarize in this query since purchase charges are recorded as they’re incurred and we want to see each individual purchase event. I sorted by BilledCost since commitment discount purchases are amortized and won’t have an EffectiveCost. I discussed this in the cost columns blog post.
One more example that I’ll leave you with is similar to the very basic commitment discount coverage in Power BI above. We already have the underlying data in the previous query, where we can see the x_PricingSubcategory values that indicate standard vs. committed vs. spot usage. But we can get more specific and include a custom extended column for the total savings compared to ListCost:
Costs | where ChargeCategory == 'Usage' | summarize ListCost = round(sum(ListCost), 4), EffectiveCost = round(sum(EffectiveCost), 4) by PricingCategory, x_PricingSubcategory, BillingCurrency | extend x_TotalSavings = round(ListCost - EffectiveCost, 4)
I only included usage in this due to how ListCost is includes both purchase and usage cost for amortized rows. I mentioned this in the cost columns blog post but will dig into more details when I cover commitment discounts in a future blog post.
We’ll continue to build on these columns in future blog posts to demonstrate more interesting scenarios as we go. Leave a comment if you’d like to see any specific queries and I’ll make sure to cover it.
What next?
While we’ve only covered the highest-level concepts so far, I hope you can start to see how things are beginning to take shape. If you need a refresher or have any questions about the cost columns that I didn’t cover here, check out the Cost columns blog post. Perhaps the most glaring omission so far is that none of the example queries include time. But since every question needs to factor time into it, I’ll cover the different date columns included in FOCUS in the next blog post in January.
If you want to learn more, the FinOps Foundation offers a free Introduction to FOCUS course. And if you’re ready to dig into your own FOCUS data, check out the Power BI reports in the FinOps toolkit. These reports offer a great starting point that you can customize to meet your needs. And if you’re looking for more advanced analytics, check out FinOps hubs, which offers additional benefits, like pre-calculated savings for EA and MCA accounts.
Happy holidays, everyone! See you in the new year!
⮜ Previous post (Costs) · Next post (Dates) ⮞
Updated Jan 15, 2025
Version 2.0flanakin
Microsoft
Joined October 08, 2019
FinOps Blog
Follow this blog board to get notified when there's new activity